LoginSignup
6
6

More than 5 years have passed since last update.

docker-composeで開発したnginx+node.jsのアプリケーションをDocker Hubで配布する方法

Last updated at Posted at 2018-02-10

要約

配布方法

Dockerfileをdocker-composeでビルドして, nginx由来とnode.js由来の2つのimageを作り, Docker Hubにプッシュする. docker-composeでビルドするときに, buildの中でcontextを使うと便利.

アプリケーションを作るdocker-compose.yamlの例
https://github.com/Toyoharu-Nishikawa/jsnote/tree/docker

git clone -b docker https://github.com/Toyoharu-Nishikawa/jsnote.git
docker-compose up -d

利用方法

利用者がアプリケーションを使うときは, docker-compose.yamlでDocker Hubに登録したimageをpullして使う.

アプリケーションを使うdocker-compose.yamlの例
https://github.com/Toyoharu-Nishikawa/jsnote/tree/app

git clone -b app https://github.com/Toyoharu-Nishikawa/jsnote.git
docker-compose up -d

背景

jsnoteというブラウザで動くJavaScriptのエディタを作っていた. 静的ファイルの配布はnginxで行い, データの保存はnode.jsで行うことにした.

docker-composeでnginxとnode.jsのイメージを立ち上げて, それぞれに必要なソースコードをvolumeでマウントすることでコンテナとファイルを共有し, コーディングをしていた.

Docker Hubにイメージを登録して, 誰でも簡単に使えるようにしようと思ったけれど, Docker Hubに置くimageをどう作成するべきかわからなかった.

Imgur

jsnoteについてはこちらの記事

問題

下記のようなディレクトリ構成の下, public/でフロント側の開発を行い, src/でサーバ側の開発を行っていた場合, gitで管理したまま, public/とsrcを入れたdocker imageを如何に作成するか.
(例: jsnoteの階層の下に全ファイルをがあるとする.)

./jsnote
|-- docker-compose.yaml
|-- conf.d
|   |-- server.conf
|
|-- public
|   |-- index.html
|   |-- scripts
|   |-- styles
|
|-- src
|   |-- index.js
|   |-- node_modules
|   |-- package.json
|   |-- package-lock.json

開発中のdocker-compose.yamlの内容は下記.

docker-compose.yaml
version: '2'
services:
  node:
    image: node 
    restart: always 
    volumes:
      - ./src:/usr/src
      - ./public/sample:/usr/share/nginx/html/sample
      - /var/log/jsnote:/var/log/node
    working_dir: '/usr/src'
    command: npm start
  nginx:
    image: nginx
    restart: always 
    volumes:
      - ./public:/usr/share/nginx/html
      - ./conf.d:/etc/nginx/conf.d
      - /var/log/jsnote:/var/log/nginx
    ports:
      - "2555:80"

試行

3つの方法を思いついた順に試行した.

方法1: nginxとnode.jsをひとつのdockerのimageに入れるDockerfileを作成, build.shでビルドする.

nginxもしくはnode.jsのイメージを基に, もう一つを入れる. 例えば, node.jsを基に作るとしたら次のようになる.

FROM node:alpine
以下nginx:alipineのDocker HubのDockerfileの中身をコピペ
.
.
.
RUN rm /etc/nginx/conf.d/*
ADD conf.d /etc/nginx/conf.d
ADD public /usr/share/nginx/html
ADD src/ /usr/src
CMD nginxとnode.js起動するコマンド

nginxとnode.jsの2つを起動するコマンドをどう書くべきかで悩んだ. Dockerの公式サイト Dockerのベストプラクティスを見て, 方法1を中止した.

コンテナ毎に1つのプロセスだけ実行

ほとんどの場合、1つのコンテナの中で1つのプロセスだけ実行すべきです。アプリケーションを複数のコンテナに分離することは、水平スケールやコンテナの再利用を簡単にします。サービスとサービスに依存関係がある場合は、 コンテナのリンク を使います。

方法2: nginxとnode.jsのimageからから別々のimageを作成するようにDockerfileを作成し, 双方をbuild.shでビルドする.

nginxとnode.jsを基にimageを作るDockerfileをそれぞれ用意する.

web/Dockerfile
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/*
ADD conf.d /etc/nginx/conf.d
ADD public /usr/share/nginx/html
web/build.sh
build -t jsnote_web .
api/Dockerfile
FROM node:alpine
ADD  src/ /usr/src
WORKDIR /usr/src
ENTRYPOINT ["npm","start"]
api/build.sh
build -t jsnote_api .

docker-composeでまとめているメリットを活かせないことに気づき, 方法2を中止した.

方法3: 方法2をdocker-composeでまとめてビルドする.

docker-composeの中でbuildを使うことで, (2)のDockerfileをまとめてbuildできる. しかし, Dockerfileと同じディレクトリにADDするファイルを置かないといけない....

⇒対処法参照

解決法

buildの中で, contextを指定することで, 親ディレクトリのファイルをDockerfileでADDできる. ことを利用すると, 開発中のdirectory階層のままでDockerfileをビルドすることができる.

step1: webとapiのディレクトリを追加し, その中にDockerfileを置く.

docker-compose.yaml
./jsnote
|-- docker-compose.yaml
|-- web                   ← 追加
|   |-- Dockerfile        ← 追加
|
|-- api                   ← 追加
|   |-- Dockerfile        ← 追加
|
|-- conf.d
|   |-- server.conf
|
|-- public
|   |-- index.html
|   |-- scripts
|   |-- styles
|
|-- src
|   |-- index.js
|   |-- node_modules
|   |-- package.json
|   |-- package-lock.json

step2: docker-compose.yamlを下記のようにする.

docker-compose.yaml
version: '2'
services:
  api:
    build: 
      context: ./ 
      dockerfile: ./api/Dockerfile
  web:
    build:  
      context: ./ 
      dockerfile: ./web/Dockerfile 
    ports:
      - "2555:80"

step3: docker-composeでビルドする.

docker-compose build

これでdockerのimageが以下のように2つできる.

  • jsnote_web
  • jsnote_api

Docker Hubにpush

docker tagでimage名をDocker Hubに書き換えて, pushする.

step1: docker login

予めDocker Hubに作って置いたアカウントにログインする.

docker login

step2: docker tag

docker tagでDocker Hubに登録するimageの名前に変更する. この時, ユーザ名/を頭に付ける必要がある.

docker tag jsnote_web ユーザ名/jsnote_web:latest
docker tag jsnote_api ユーザ名/jsnote_api:latest

step3: docker push

docker push ユーザ名/jsnote_web:latest
docker push ユーザ名/jsnote_api:latest

以上で, Docker Hubでimageが公開され, 配布できるようになる.

以降は, 誰でもdocker pullでimageをダウンロードできる.

自分で試す場合は, docker rmiでimageを削除してから, pullできるか試す必要がある.

docker rmi ユーザ名/jsnote_web:latest
docker rmi ユーザ名/jsnote_api:latest

docker pull ユーザ名/jsnote_web_web:latest
docker pull ユーザ名/jsnote_api:latest

最後に(アプリケーションの使い方)

nginx+node.jsのアプリケーションとして使うには, docker-composeを使って, 2つをリンクさせる必要がある.

./jsnote              
|-- docker-compose.yaml
docker-compose.yaml
version: '2'
services:  
  api:
    image: ユーザ名/jsnote_api
  web:  
    image: ユーザ名/jsnote_web
    ports:
      - "80:80"

(注意)
本例のdocker-compose.yamlの場合, nginxのリバースプロキシproxy_pass(ロードバランサ―の設定はupstream)はserverとして, jsnote_api_1もしくは単にapiを参照しなくてはならない. nginxのリバースプロキシの設定はnginxの.confに書かれている. 上記 解決法 で作成したnginxのimageの中に適切なリバースプロキシの設定が書かれていない場合, 作者がconf.d/default.confの中の設定を書き直し, もう一度imageを作り直してDocker Hubにアップロードするか, アプリケーションの利用者がdocker-composeの中でvolumesで設定を上書きする必要がある.

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6