Docker Compose で複数コンテナ構築＆管理



### ■ 概要
---

+ Docker Compose は、Dockerのコンテナ管理ツール
+ 複数コンテナの構築・管理を、設定ファイルと docker-compose コマンドで一括管理できて便利
+ Docker for Mac には同梱されている

今回は、とりあえず最小構成(？)の WEBサーバーコンテナ + MySQLコンテナ で構築してみる

※MySQLのコンテナは、通常は公式のイメージを使用するが、今回は個別にDockerfileを指定する方法を試してみたかったので、あえて別途作成した。

　
### ■ 参考URL
---

http://qiita.com/jey0taka/items/3fca0d0acb8aa4278284

http://qiita.com/naga3/items/d1a6e8bbd0799159042e

http://qiita.com/zembutsu/items/9e9d80e05e36e882caaa

http://inamuu.com/docker-composeでコンテナが起動しない/

http://qiita.com/okamu_/items/1c8e5fde742ca165fa12

https://docs.docker.com/engine/reference/run/

　
### ■ フォルダ・ファイル構成
---

以下の構成で、設定ファイルや確認用コンテンツなどを用意する。
それぞれのファイルの記述例については後述。

※フォルダ構成は一例で、こうしなければいけないというわけではない。今回は、DBとWEBでフォルダを分けたほうがわかりやすいと思ったのでそうしている。

```
~/docker/compose-test
     |
     |-- docker-compose.yml
     |
     |-- db01/build/Dockerfile
     |       /data
     |
     |-- web01/build/Dockerfile
              /conf.d/vhosts.conf
              /public_html/index.html
              /webapps/mytestapp/public/index.html
```

　
### ■ フォルダ・ファイル作成
---

前述の、想定するフォルダツリーにしたがって、フォルダ・ファイルを作成する

```bash
mkdir -p ~/docker/compose-test/db01/build
mkdir ~/docker/compose-test/db01/data

mkdir -p ~/docker/compose-test/web01/build
mkdir ~/docker/compose-test/web01/conf.d
mkdir ~/docker/compose-test/web01/public_html
mkdir -p ~/docker/compose-test/web01/webapps/mytestapp/public

# HTMLファイルの内容は適当に用意しておく
vi ~/docker/compose-test/web01/public_html/index.html
    # 「this is public_html/index.html」とか書いておく
vi ~/docker/compose-test/web01/webapps/mytestapp/public/index.html
    # 「this is webapps/mytestapp/public/index.html」とか書いておく
```

　
### ■ vhosts.conf を用意
---

WEBアプリケーションの設置先をMac側に用意してコンテナからマウントする想定なので、そのマウント先を VirtualHost として動かすためのApache設定ファイルを用意する。
このファイル自体もコンテナからマウントさせて、Apacheから読み込まれるようにする。

※ホスト名の「mytestapp.local」は、Mac の /etc/hosts の 127.0.0.1 の行に追加しておく

vi ~/docker/compose-test/web01/conf.d/vhosts.conf

```apacheconf
NameVirtualHost *:80

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/html
    ServerAdmin root@localhost

    # DocumentRoot
    <Directory "/var/www/html">
        Options All
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

<VirtualHost *:80>
    ServerName mytestapp.local
    DocumentRoot /usr/local/webapps/mytestapp/public
    ServerAdmin root@mytestapp.local

    # DocumentRoot
    <Directory "/usr/local/webapps/mytestapp/public">
        Options All
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

　
### ■ docker-compose.yml
---

これが肝となる Docker Compose の設定ファイル。各項目の意味については後述。

```yaml
version: '2'
services:
  # db server ( mysql )
  db01:
    build: ./db01/build
    image: miro/centos7db01:1.0
    ports:
      - "3306:3306"
    volumes:
      - ./db01/data:/docker-host/db01/data
    environment:
      MYSQL_ROOT_PASSWORD: root
    tty: true
    stdin_open: true
    privileged: true
    command: /sbin/init

  # web server 01 ( apache )
  web01:
    build: ./web01/build
    image: miro/centos7web01:1.0
    ports:
      - "80:80"
      - "3000:3000"
    links:
      - "db01:db01"
    volumes:
      - ./web01/conf.d/vhosts.conf:/etc/httpd/conf.d/vhosts.conf
      - ./web01/public_html:/var/www/html
      - ./web01/webapps:/usr/local/webapps
    tty: true
    stdin_open: true
    privileged: true
    command: /sbin/init
```

「version: '2'」
　　設定の書き方にバージョンがあるらしい。2で良いかと。

「services:」
　　この配下に、コンテナを定義していく

「db01:」「web01:」
　　各コンテナの定義名なので、内容が分かるような名称を指定する。

「build:」
　　Dockerfile が置いてあるディレクトリのパスを記述。
　　配布されているイメージ（公式イメージなど）を取得する場合は指定不要

「image:」
　　イメージ名とタグ
　　「build:」を指定した場合は、この名前でイメージが作成される。
　　「build:」を指定しなかった場合は、ここに指定されたイメージを取得して構築する。
　　たとえば MySQL5.7の公式イメージを取得するなら、「image: mysql5.7」と指定し、「build:」は指定しない

「ports:」
　　ポートマッピングを指定。ホストのMac側からアクセスできるように指定している

「volumes:」 
　　ディレクトリマウント。ホストのMac側からファイルを設置したり編集したりできるようにマウントしている

「environment:」
　　docker run の「-e」オプションに当たるもの。環境変数を指定できる。

「links:」
　　コンテナ同士の接続設定。上記の例だと、web01 から db01 というホスト名でMySQL側のコンテナへ接続できる

「tty: true」 と 「stdin_open: true」
　　docker run の「-it」オプションに当たるもの。これを指定しないと、コンテナを起動してもすぐ終了してしまうので注意

「privileged: true」
　　docker run の「--privileged」オプションに当たるもの。これを指定しないと、systemctl コマンドが使えないので注意

「command: /sbin/init」
　　docker run の引数として指定するコマンドに当たる部分。これを指定しないと、systemctl コマンドが使えないので注意

※ビルド後にコンテナにログインして systemctl コマンドを実行したときに以下のようなエラーが出る場合は、たいていは上記の「privileged: true」「command: /sbin/init」あたりが指定されていない。
<font color="green">
「Failed to get D-Bus connection: Operation not permitted」
</font>

　
### ■ Dockerfile（ db01 ）
---


※MySQLのサーバーは、通常は公式のイメージを使用する。
その場合は、「image: 〜」に "mysql:5.7" 等の公式イメージを指定し、「build: 〜」は指定しない
今回は、個別にDockerfileを指定する方法を試してみたかったので、以下の通り別途作成した。

(参考) このDockerfile から単体でビルド&起動をテストする場合のコマンドは以下。

```bash
# ビルド
docker build -t miro/centos7mysql57:1.0 .

# コンテナ起動
docker run --privileged -it -d --name cent7mysql57 miro/centos7mysql57:1.0 /sbin/init

# 接続
docker exec -it cent7mysql57 bash
```

　
「db01/build/Dockerfile」

```
FROM centos:centos7

# Import the Centos-7 RPM GPG key to prevent warnings
RUN rpm --import http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-7
RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7

# system update
RUN yum -y update && yum clean all

# set locale
RUN yum reinstall -y glibc-common && yum clean all
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

# ===============================================================================
# BASE packages
# ===============================================================================
RUN yum --enablerepo=extras clean metadata
RUN yum install -y zlib zlib-devel make gcc gcc-c++ openssl openssl-devel readline-devel pcre pcre-devel
RUN yum install -y openssh openssh-server
RUN yum install -y net-tools wget sudo
RUN yum install -y tar zip unzip bzip2 which tree
RUN yum install -y git

# ===============================================================================
# Install Applications
# ===============================================================================

# MySQL
RUN yum localinstall -y http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
RUN yum install -y mysql mysql-devel mysql-server mysql-utilities

# write to my.cnf
#RUN sed -i -e 's~datadir=/var/lib/mysql~datadir=/docker-host/data/mysql~g' /etc/my.cnf

# init mysql
#RUN mysqld --user=mysql --initialize

# enable mysql
RUN systemctl enable mysqld
```

　
### ■ Dockerfile（ web01 ）
---


(参考) このDockerfile から単体でビルド&起動をテストする場合のコマンドは以下。

```
# ビルド
docker build -t miro/centos7apache:1.0 .

# コンテナ起動
docker run --privileged -it -d --name centos7apache miro/centos7apache:1.0 /sbin/init

# 接続
docker exec -it centos7apache bash
```

　
「web01/build/Dockerfile」

```
FROM centos:centos7

# Import the Centos-7 RPM GPG key to prevent warnings
RUN rpm --import http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-7
RUN rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7

# system update
RUN yum -y update && yum clean all

# set locale
RUN yum reinstall -y glibc-common && yum clean all
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

# ===============================================================================
# BASE packages
# ===============================================================================
RUN yum --enablerepo=extras clean metadata
RUN yum install -y zlib zlib-devel make gcc gcc-c++ openssl openssl-devel readline-devel pcre pcre-devel
RUN yum install -y openssh openssh-server
RUN yum install -y net-tools wget sudo
RUN yum install -y tar zip unzip bzip2 which tree
RUN yum install -y git

# ===============================================================================
# Install Applications
# ===============================================================================

# Apache
RUN yum install -y httpd

# enable httpd
RUN systemctl enable httpd
```

　
### ■ ビルド＆起動してみる
---

① ビルド＆起動

```bash
docker-compose up -d
```

　
② 起動したか確認する

```bash
$ docker-compose ps
       Name            Command     State                     Ports                    
-------------------------------------------------------------------------------------
composetest_db01_1    /sbin/init   Up      0.0.0.0:3306->3306/tcp                     
composetest_web01_1   /sbin/init   Up      0.0.0.0:3000->3000/tcp, 0.0.0.0:80->80/tcp
```

　
③ web01 にログインし、db01に疎通しているか確認する

```bash
$ docker exec -it composetest_web01_1 bash

[root@1d9e354ac39c /]# ping db01
PING db01 (172.18.0.2) 56(84) bytes of data.
64 bytes from composetest_db01_1.composetest_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.165 ms
64 bytes from composetest_db01_1.composetest_default (172.18.0.2): icmp_seq=2 ttl=64 time=0.178 ms

# ↑ 通った！
```

　
④ Macのブラウザから、WEBサーバーのコンテンツにアクセスできるか確認
http://localhost/
↓
this is public_html/index.html

http://mytestapp.local/
↓
this is webapps/mytestapp/public/index.html


　
### ■ Docker Compose の基本操作
---

● ビルドと起動

```bash
docker-compose up -d
```

・初回起動時にビルドも実行される
・-d で、コンテナをバックグラウンドで実行

　
● コンテナの起動状態の確認

```bash
docker-compose ps
```

　
● 接続

```bash
docker exec -it コンテナ名
```

　
● コンテナの停止

```bash
docker-compose stop コンテナ名
```

※コンテナ名を指定しなければ、yamlに書かれた全コンテナが対象となる

　
● コンテナの削除

```bash
docker-compose rm コンテナ名
```

※コンテナ名を指定しなければ、yamlに書かれた全コンテナが対象となる

　
● コンテナの再起動

```bash
docker-compose restart コンテナ名
```

※コンテナ名を指定しなければ、yamlに書かれた全コンテナが対象となる