Docker ComposeによるMySQL, Redis, nginx, Rails構成の設定例

  • 98
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

導入

Docker Composeを利用して、複数のdocker containerを使った環境の設定例を紹介します。なお、Docker ComposeはWindowsでは使えません。Max OSX or 64bit Linuxのみ対象となっています。

準備

Docker Toolboxをインストールできれば環境はすべて整います。
https://www.docker.com/products/docker-toolbox
docker, docker-machine, docker-composeといったツールとVirtualBoxがインストールされるはずです。

次にmachineの準備
https://docs.docker.com/machine/get-started/

$ docker-machine create --driver virtualbox default
$ docker-machine env default

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/user/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell: 
# eval $(docker-machine env default)

$ eval $(docker-machine env default)

これでdefault machineを使ってdocker containerを起動することができるようになりました。
docker-machine lsで確認できます

$ docker-machine ls
NAME         ACTIVE   DRIVER       STATE     URL                          SWARM   DOCKER    ERRORS
default      *        virtualbox   Running   tcp://192.168.99.100:2376            v1.10.1   
prod         -        google       Running   tcp://104.155.xxx.xxx:2376           v1.9.1    
prod2        -        google       Running   tcp://104.199.xxx.xxx:2376           v1.10.1 

Version

今回利用したdockerツール類のversionを記載しておきます。

$ docker-machine -v
docker-machine version 0.6.0, build e27fb87
$ docker-compose -v
docker-compose version 1.6.0, build d99cad6
$ docker -v        
Docker version 1.10.1, build 9e83765

Docker Compose 1.6からの書式変更

docker-composeは1.6からconfigurationの書式が変更になっているのでご注意ください。
以下のように構造が変わっています。

1.5系まで(version 1)

db:
  image: postgres
web:
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  volumes:
    - .:/myapp
  ports:
    - "3000:3000"
  links:
    - db

1.6以降

以下のようにversionを明示し, 各serviceの設定を束ねるservicesが追加されました。

version: '2'
services:
  db:
    image: postgres
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    links:
      - db

1.6でもversion1の書式を受け付けてくれますが、サポートは1.6系までのため新規のものはversion 2で設定してください。

Docker Compose 設定例

rails new myappで作成し、myappは以下の構成となっていることを前提とします。

$ ls -1F 
Dockerfile
Dockerfile.prod
Gemfile
Gemfile.lock
README.rdoc
Rakefile
app/
bin/
config/
config.ru
db/
doc/
docker-compose.prod.yml
docker-compose.yml
lib/
log/
nginx/
public/
script/
test/
tmp/
vendor/
  • docker-compose.ymlがcurrent dirにあるとdocker-compose up -dのみでbuildからcontainer起動まですみます。
  • docker-compose.prod.ymlのようにdefault以外の名前をつけた場合、-fオプションで指定する必要があります
    • 例: docker-compose -f docker-compose.prod.yml up -d

以下のページを参考に設定してきます。
https://docs.docker.com/compose/compose-file/

development(docker-compose.yml)

version: '2'
services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: $MYAPP_DATABASE_PASSWORD
    volumes:
      - db-data:/var/lib/mysql
  redis:
    image: redis:3.0.5
  app:
    build: .
    environment:
      MYAPP_DATABASE_USERNAME: root
      MYAPP_DATABASE_PASSWORD: $MYAPP_DATABASE_PASSWORD
      MYAPP_DATABASE_HOST: db
      MYAPP_SLACK_API_TOKEN: $MYAPP_SLACK_API_TOKEN
  web:
    extends:
      service: app
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    links:
      - db
      - redis
  worker:
    extends:
      service: app
    command: bundle exec sidekiq -q notification
    volumes:
      - .:/myapp
    links:
      - db
      - redis

volumes:
  db-data:
    driver: local

image

image: mysqlimage: mysql:latest省略であり、2016/02/17現在はimage: mysql:5.7.11を意味します
buildのたびにバージョンがばらけてしまうことになるので、image: mysql:5.7image: mysql:5.7.11というようにversion指定したほうがよいです。

基本的なものは https://hub.docker.com/ から探すことができます。
- https://hub.docker.com/_/mysql/
- https://hub.docker.com/_/redis/
- https://hub.docker.com/_/nginx/

environment

containerに渡す環境変数の設定ですが、password類をyamlに書いてrepositoryに突っ込むわけにもいかないので、以下のようにshellの環境変数を渡します。

    environment:
      MYSQL_ROOT_PASSWORD: $MYAPP_DATABASE_PASSWORD

volumes

databaseのように永続的なストレージが欲しい場合に必要な設定です。

    volumes:
      - db-data:/var/lib/mysql

volumes:
  db-data:
    driver: local

https://docs.docker.com/compose/compose-file/#volume-configuration-reference

extends

今回の例のようにwebとworker containerがあり、設定が共通している場合にはextendsを利用して共通化することができます。

  app:
    build: .
  web:
    extends:
      service: app
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
  worker:
    extends:
      service: app
    command: bundle exec sidekiq -q notification

設定ファイルを分けて管理することもできます。
https://docs.docker.com/compose/compose-file/#extends

links

linksを設定すると、container内で名前が引けるようになります。今回の例ではwebがdbとredisに接続するため、設定しています。

    links:
      - db
      - redis

production(docker-compose.prod.yml)

version: '2'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.prod
    environment:
      RAILS_SERVE_STATIC_FILES: 'true'
      MYAPP_SECRET_KEY_BASE: $MYAPP_SECRET_KEY_BASE
      MYAPP_DATABASE_USERNAME: app
      MYAPP_DATABASE_PASSWORD: $MYAPP_DATABASE_PASSWORD
      MYAPP_DATABASE_HOST: db
      MYAPP_SLACK_API_TOKEN: $MYAPP_SLACK_API_TOKEN
    logging:
      driver: syslog
      options:
        syslog-address: "udp://logs3.papertrailapp.com:xxx"
  web:
    extends:
      service: app
    command: bundle exec puma -C config/puma.rb
    links:
      - db
      - redis
  worker:
    extends:
      service: app
    command: bundle exec sidekiq -q notification
    links:
      - db
      - redis

  nginx:
    build: ./nginx
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
    links:
      - web
    logging:
      driver: syslog
      options:
        syslog-address: "udp://logs3.papertrailapp.com:xxx"

  db:
    image: mysql
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: $MYAPP_DATABASE_PASSWORD
      MYSQL_DATABASE: myapp_production
      MYSQL_USER: driver
      MYSQL_PASSWORD: $MYAPP_DATABASE_PASSWORD
    logging:
      driver: syslog
      options:
        syslog-address: "udp://logs3.papertrailapp.com:xxx"

  redis:
    image: redis:3.0.5
    logging:
      driver: syslog
      options:
        syslog-address: "udp://logs3.papertrailapp.com:xxx"

volumes:
  db-data:
    driver: local

build

build: .であれば./Dockerfileを使ってbuildしますが、別のdirectoryやfileの場合にはcontext,dockerfileで指定してください。

  app:
    build:
      context: .
      dockerfile: Dockerfile.prod

以下のように書くと、./nginx/Dockerfileを使ってbuildします。

  nginx:
    build: ./nginx

logging

特に設定しない場合はdriver: json-fileとなり、docker machine上の/var/lib/docker/containers/*/*-json.logにログが出力されています。
ログを何処かに集約したい場合は、fluentd containerを用意してあれこれしたり、以下の様なlogging設定をする方法などが考えられます。

    logging:
      driver: syslog
      options:
        syslog-address: "udp://logs3.papertrailapp.com:xxx"

https://papertrailapp.com/ に転送する例です。実際にはxxxに指定されたport番号を書いておく必要があります。

Docker本体に関わることですが、log周りは以下が片付くとまたかわってくると思います。
- Logging driver plugins
- Proposal: New logging driver that logs to tcp, udp and unix domain sockets

補足

Dockerfile

$ cat Dockerfile
FROM ruby:2.2.4
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile Gemfile.lock /myapp/
RUN bundle install
ADD . /myapp

Dockerfile.prod

FROM ruby:2.2.4
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential
RUN mkdir /myapp
WORKDIR /myapp

ADD Gemfile Gemfile.lock /myapp/
RUN bundle install --jobs 20 --retry 5 --without development test

ENV RAILS_ENV production
ADD . /myapp
RUN bundle exec rake tmp:create
RUN bundle exec rake assets:precompile

.dockerignore

.dockerignoreファイルを用意することで余計なものをcontainerに載せずにすみます。
https://docs.docker.com/engine/reference/builder/#dockerignore-file

.git
log
tmp