こんにちは、Mashです。
本業でDockerを触る機会がありまして、自分の知識整理のためと、せっかくならということで初学者さんに向けて記事を作成しています。
今回はDocker入門第5回です。
前回記事で、Docker Composeを利用して複数コンテナで構成されるシステム(WordPress)を立ち上げることができました。
今回は docker-compose.yml ファイルの中身についてじっくり見ていきたいと思います。
座学中心になりますが、Dockerをより深く理解するための情報を盛り込みましたので、じっくり読み込んでいただけるとうれしいです。
- docker-compose.ymlで最低限必要なパラメータを知る
- Dockerの内部構造を理解して、頭の中でイメージできるようになる
※本シリーズはDocker初心者向けではありますが、前提として多少のLinux知識が必要となります。ご了承ください。
それではいきましょう!
前回のおさらい
まずは前回使用したdocker-compose.ymlファイルを再掲します。
いまからこのYAMLファイルの内容を読み解いていきます。
version: '3' networks: default: external: name: bridge mash-network: driver: bridge volumes: db_data: services: db: image: mysql container_name: db hostname: db volumes: - db_data:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: wordpress MYSQL_USER: mash MYSQL_PASSWORD: mash_password networks: - mash-network wordpress: depends_on: - db image: wordpress container_name: wordpress hostname: wordpress ports: - 80:80 restart: always environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: mash WORDPRESS_DB_PASSWORD: mash_password networks: - mash-network phpmyadmin: depends_on: - db image: phpmyadmin container_name: phpmyadmin hostname: phpmyadmin ports: - 8080:80 restart: always networks: - mash-network
そしてこの定義をもとに $ docker-compose up して立ち上がる環境がこちらになります。
以下、文章での説明がつづきます。わからなくなったらこのイメージ図に戻ってきてください。

今回docker-compseファイルの中身について確認していきますが、お伝えしたい内容はおおきく2つです。
- Dockerのネットワーク
- Dockerのデータボリューム
docker-composeファイルを解析
ひとつずつ追いかけていきましょう。
version
docker-composeのこの部分です。
version: '3'
文字どおり、docker-composeファイルのバージョンを指定しています。公式リファレンスはこちら。
もちろん新しいバージョンになるほど機能が拡充しているわけですが、ホストに導入するDockerエンジンのバージョンによってサポートされない場合があるのでご注意ください。
ひとまず本日時点(2020年11月23日)ではバージョン3系を選択しておけば問題ありません。
networks
docker-composeのこの部分です。
networks:
default:
external:
name: bridge
mash-network:
driver: bridge
重要ポイント1つ目です。
networksセクションでは、Docker内で使用するネットワークを定義します。公式リファレンスはこちら。
これまであまり触れませんでしたが、Dockerを導入したホストの内部にはホストに割り当てられたIPアドレスとは別にDockerが利用する独自のネットワークが出来あがっています。
そして起動したコンテナたちはこの内部ネットワーク内でIPアドレスが割り当てられています。
docker-compose.ymlのnetworksセクションでは、Docker Composeで構築するコンテナ環境用のネットワークを定義することができます。
ホストOS上でIPアドレス一覧を取得するコマンドを実行してみましょう。(私の環境はUbuntu 20.04です)
みなさんの環境でも試してみてください。
$ ip a
(中略)
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:5a:b1:0b brd ff:ff:ff:ff:ff:ff
inet 10.10.1.1/24 brd 10.10.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::215:5dff:fe5a:b10b/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:b1:11:0c:83 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: br-b818ceb630f4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ef:59:b2:49 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.1/16 brd 172.19.255.255 scope global br-b818ceb630f4
valid_lft forever preferred_lft forever
inet6 fe80::42:efff:fe59:b249/64 scope link
valid_lft forever preferred_lft forever
(以下略)
「eth0」がDockerホストに割り当てられている実IPアドレスです。
そして分かりづらいのですが、「br-b818ceb630f4」がdocker-compose.ymlファイルで定義した 「mash-network」 というDockerネットワークの入り口になります。
割り当てられているIPアドレスが「172.19.0.1」であることがわかりますね。
ちなみに docker0 は、Dockerエンジンをインストールすると必ず作成されるデフォルトのDockerネットワークです。
今回はあえて mash-network を作成しましたが、特になにも指定しない場合はこのdocker0ネットワークにコンテナが所属していくことになります。
docker network コマンド
Dockerネットワークを確認してみましょう。下記コマンドを実行してください。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c42fba611ebf bridge bridge local
b818ceb630f4 dockercompose-test01_mash-network bridge local
ひとつめの bridge がデフォルトネットワーク。OS側で docker0 として見えてたやつね。
で、ふたつめがNAMEをみていただくとわかるとおり今回利用するmash-networkとなります。
実はさきほど $ ip a コマンドで表示されたネットワークデバイスとNETWORK IDが一致しています。少し戻って確認してみてください。
つづいて、mash-networkの詳細を確認するコマンドです。
最後の引数はネットワーク名かIDを指定します。(今回はネットワーク名を指定して実行)
$ docker network inspect dockercompose-test01_mash-network
実行結果が長いため省略しますが、このDockerネットワークの名称やIPアドレス帯、所属しているコンテナなどの情報がバッチリ取得できます。みなさんの環境でも確認してみてください。
コンテナ同士が通信できていないような事象が発生した際には、もしかすると各コンテナが別々のネットワークに所属している とかあるかもしれません。
volumes
docker-compsoseのこの部分です。
volumes:
db_data:
重要ポイント2つ目です。
volumesセクションでは、Dockerコンテナで使用するデータ領域を定義します。公式リファレンスはこちら。
Dockerボリュームもはじめて登場したので少し前段のお話から。
コンテナは基本的に使い捨てです。起動して使い終わったらコンテナは停止、そして破棄します。
コンテナに障害が発生した場合も、コンテナ復旧するために頑張るのではなく、使い捨てて新しいコンテナを起動するという運用をします。
このような考え方のことを「エフェメラル(一時的)」といい、Docker公式マニュアルにもベストプラクティスとして明記されています。
さて、ここで問題になることが一つあります。
それはデータベースのように情報を永続化しておく必要があるデータ保存はどうするの? です。
今回、Docker Compseの題材としてWordPressを取り上げています。
WordPressではブログ記事などを更新するとすべての情報がMySQLデータベースに蓄積していくわけですが、前述の通りコンテナに障害が発生したときには対象のコンテナを再起動して対処します。
何も手当をしていないとWordPressのデータはMySQLコンテナの中に保存されるため、コンテナを破棄するとデータ自体も消えてしまいます。
だれでもわかりますが、それはいかんですよね。
そこで登場するのが Dockerボリューム という考え方です。
ボリュームとは結論からお伝えすると、消えたら困るデータをDockerホスト側に保存しておく仕組みです。
コンテナが破棄され、新しいコンテナが起動してきても、MySQLのデータはDockerホスト側に残っています。
そのため、データが消失することなくMySQLコンテナが復活できるようになります。
今回使ったdocker-composeファイルでは、「db_data」というボリューム領域を作成しています。
docker volume コマンド
さて、ネットワークと同様にボリュームも確認してみましょう。
$ docker volume ls
DRIVER VOLUME NAME
local 4ed21e47499fbb17c5cf1e623875c13bebd916b3d992145749dd8a5a89117479
local 5f8d0656e11f7bd82e2e1ff36f0027daa0a628759743046474f2e3763299cc14
local d8b4815e82a52ac747a5a45a058d186b672dc282d4c7d79e76dc781a47fe4923
local dockercompose-test01_db_data
いろいろ作成されているようですが、4つめが今回作成した「db_data」ボリュームですね。
db_dataボリュームの詳細を確認してみましょう。
$ docker volume inspect dockercompose-test01_db_data
実際のコマンド結果は省略しますが、ここで確認しておきたいのは「db_data」というボリュームはDockerホストの「/var/lib/docker/volumes/dockercompose-test01_db_data/_data」に紐付いているという点です。
このPATHが、コンテナから見えるようになっていてデータを保存できるようになっている というわけですねー。
後ほど触れますが、今回のdocker-composeではMySQLコンテナでdb_data領域を使用しています。
services
docker-composeのこの部分です。
services:
db:
image: mysql
container_name: db
hostname: db
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: mash
MYSQL_PASSWORD: mash_password
networks:
- mash-network
wordpress:
depends_on:
- db
image: wordpress
container_name: wordpress
hostname: wordpress
ports:
- 80:80
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: mash
WORDPRESS_DB_PASSWORD: mash_password
networks:
- mash-network
phpmyadmin:
depends_on:
- db
image: phpmyadmin
container_name: phpmyadmin
hostname: phpmyadmin
ports:
- 8080:80
restart: always
networks:
- mash-network
servicesセクションでは、起動するコンテナに関するパラメータを定義します。公式リファレンスはこちら。
今回は「MySQL」、「WordPress(Apache)」、「phpMyAdmin」の3コンテナについて定義しています。
ひとまずMySQLを例にみていきましょう。すべてコメントをいれていきます。
# まずはじめにサービス名を定義
db:
# コンテナのもととなるイメージ名を定義
# image の代わりに build として、Dockerfileからコンテナ立ち上げることも可能
image: mysql
# コンテナ名を定義
container_name: db
# コンテナのホスト名を定義
hostname: db
# 先程登場したボリュームを使用する宣言
# ホスト側のdb_data領域が、コンテナの/var/lib/mysql(MySQLのデータ領域)とイコールになっている
volumes:
- db_data:/var/lib/mysql
# コンテナが終了したら再度起動するよう定義
restart: always
# 環境変数を定義
# MySQLコンテナの場合は、データベースのユーザ名やパスワードを指定する必要あり
# 定義が必要な環境変数は使用するイメージ毎に異なるため、公式ドキュメント要参照
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: mash
MYSQL_PASSWORD: mash_password
# 所属するネットワークを定義。新規作成したmash-networkに所属するよう指定
networks:
- mash-network
servicesで指定できるパラメータはほかにもたくさんありますので、ぜひさきほど貼り付けた公式リファレンスを一度ごらんいただければと思います。
このようにservices定義をどんどん追記していって、起動するコンテナを管理していくわけです。
docker container コマンド
コンテナの起動状況を確認してみましょう。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
99fbe830e4ad phpmyadmin "/docker-entrypoint.…" 3 days ago Up 28 hours 0.0.0.0:8080->80/tcp phpmyadmin
e61d634bb206 wordpress "docker-entrypoint.s…" 3 days ago Up 28 hours 0.0.0.0:80->80/tcp wordpress
466f72f6ba6d mysql "docker-entrypoint.s…" 3 days ago Up 28 hours 3306/tcp, 33060/tcp db
※これまで私の記事では $ docker ps コマンドを使用していましたが少し古いコマンドでした。失礼しました。
このように起動中のコンテナ一覧を取得できます。
そして、例えばdbコンテナの詳細を確認したいときはこちらのコマンド。
$ docker container inspect db
コンテナの状況や設定一覧がガバっと取得できます。
まとめ
少々端折った部分もありますが、docker-compose.ymlの「version」、「networks」、「volumes」、「services」それぞれのセクションで定義されている内容を確認しました。
今回使用したdocker-compose.ymlで立ち上がるDocker環境のイメージ図を再掲します。本記事を読み前と比べて、伝えたい内容が少しでも理解いただけるようになっていればうれしいです。

Docker Composeまで学習すれば、あとはみなさんご自身でコンテナ化したい環境をイメージしてもらって実践あるのみです。
ぜひDockerコンテナの世界に一歩足を踏み入れてチャレンジしていただければと思います。
それではいったんDocker入門シリーズは終了です。

追加で○○のことが知りたい!
とか

✕✕のような動きを実現したいんだけど教えて!
などなどあれば対応しますので、お気軽にコメント/メッセージください。
それじゃあまたね。
(Kubernetes入門シリーズを検討中です。。。おたのしみに。。。)