Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

導入

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
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away