docker-composeを使って色々やるとき割とよく使うことのまとめみたいなものです。
目次
基本形
カレントディレクトリにdocker-compose.ymlを作成します。
version: "3"
services:
app:
networks:
default:
「app」が(このdocker-compose内での)サービス名になります。ここの設定を元に、イメージやコンテナが作られ動きます。
タブに注意
インデントはタブではなくスペースで入れる必要があります。
エディタで書いてるとついタブが入ってしまうことがありますが、それだとエラーになります。
ERROR: yaml.scanner.ScannerError: while scanning for the next token
found character '\t' that cannot start any token
in ".\docker-compose.yml", line 2, column 1
ってなります。
docker-composeの一部を変更する
チームで共有しているdocker-composeの一部だけを変更したい場合など、一部を変更する場合にはdocker-compose.override.ymlを作成します。
このファイルに書いてある内容が、もとのdocker-comopse.ymlに上書きされます。
設定の一部を引き継ぐ
他のコンテナ設定をコピーする、引き継いで作成する場合はYAMLのアンカーとエイリアスが使えます。
「&」で目印を付けて「*」で展開する感じです。
services:
app1: &app
image: centos:7
app2: *app
こうするとapp1の内容をapp2に展開できます。
イメージを作る
既存のイメージを使う
services:
app:
image: centos:7
のように指定します。
イメージはDockerHubにあるものを使用できます。公式だけでなく、個人で公開されているものもあるみたいです。
Docker公式が配布しているイメージには「Docker Officeal Images」とあります。
例えばcentos。
Dockerfileを使う
Dockerfileを指定する場合はbuild.dockerfileを指定します。
services:
app:
build:
dockerfile: ./Dockerfile
コンテナ内のカレントディレクトリを指定する
working_dirで指定します。
services:
app:
working_dir: /var/log
$ docker-compose run app
[root@52d5c6f944b4 log]# pwd
/var/log
ファイルをマウントする
ファイルをマウントするにはvolumensに定義を書きます。
カレントディレクトリからの相対パスもできます。
services:
app:
image: centos:7
volumes:
- ./test:/test
volumesのマウントは、コンテナ内に同名のファイルやディレクトリがあっても優先されます。(逆にもともとコンテナにあったファイルおよびディレクトリは隠れてしまいます。単純にコンテナ内のファイルを共有するわけではありません)
また指定したパスまでのディレクトリがコンテナ内に無い場合でも、問題なくそのパスでマウントされます。
なので/var/log/nginxをマウントしてログを出力させたりとか、/etc/nginx/nginx.confをマウントして設定変えたりとかします。
up/runで実行するコマンドを指定する
コンテナを起動したときの動作を指定します。
※commandとentrypointは似て異なるものになりますがざっくりなのでまとめています。使用する際にはそれぞれの意味をご確認下さい。
DockerfileのCMDとENTRYPOINT
DockerfileのCMDとENTRYPOINTはそのまま動作します。
commandとentrypoint
commandとentrypointでDockerfileのそれを上書きできます。
services:
app:
command:
ls
または
services:
app:
entrypoint:
ls
lsだけして終わります。
複数のコマンドを指定する
複数のコマンドを指定するときはシェル引数で連結したりできます。
services:
app:
image: centos:7
command: |
sh -c ' \
ls && \
touch sample.file && \
echo "touch sample file" && \
ls '
これを実行してみるとsample.fileが作成されています。
$ docker-compose run app
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr
touch sample file
anaconda-post.log dev home lib64 mnt proc run sbin sys usr
bin etc lib media opt root sample.file srv tmp var
run時の引数に指定
docker-compose run時のコンテナ名以下の引数はそのまま実行されます。
$ docker-compose run app ls -a
. anaconda-post.log etc lib64 opt run sys usr
.. bin home media proc sbin test var
.dockerenv dev lib mnt root srv tmp
または
$ docker-compose run --entrypoint="ls -a" app
. anaconda-post.log etc lib64 opt run sys usr
.. bin home media proc sbin test var
.dockerenv dev lib mnt root srv tmp
run/upでコンテナを起動しっぱなしにする
基本的にコンテナはコマンドを実行し終えたら終了してしまいますが、nginxのようにサービスとして起動していて欲しいときもあります。
ttyをtrueにする
services:
app:
tty: true
おそらくターミナルの待ち受けになり、結果起動しっぱなしになるのかなと思います。
commandなどで終了しないようにする
何らかの方法でコマンドを終了しないようにすれば、起動しっぱなしになります。
例えばnginxはデーモン起動しないことでコンテナを起動させ続けていたりするようです。
CMD ["nginx", "-g", "daemon off;"]
次のように/dev/nullをtailし続けるとか。
services:
app:
command: tail -f /dev/null
こうなります。
$ docker-compose up app
Recreating sample_app_1 ... done
Attaching to sample_app_1
ここはそれぞれの環境にあわせて、どう実行させるかを決めて下さい。
コンテナ内部から他のサービスを参照する
docker-comopse.ymlにあるコンテナ群は閉じたネットワーク内のマシンとして認識されており、他のサービスのコンテナに(普通のネットワーク越しみたいな感じで)接続することも出来ます。
サービス名をホスト名として指定する
services:
app:
image: centos:7
nginx:
image: nginx
nginxに対してpingしてみます。
$ docker-compose up -d nginx
Creating sample_nginx_1 ... done
$ docker-compose run app ping nginx
PING nginx (172.20.0.2) 56(84) bytes of data.
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=1 ttl=64 time=0.108 ms
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=2 ttl=64 time=0.087 ms
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=3 ttl=64 time=0.072 ms
^C
--- nginx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2056ms
rtt min/avg/max/mdev = 0.072/0.089/0.108/0.014 ms
エイリアス名を設定する
nginxでVirtualHostを設定するときなど、他の名前解決をしたいときがあります。
その場合はaliasを使います。このときにはデフォルトでいいので、networkの指定も必要です。
services:
app:
image: centos:7
nginx:
image: nginx
networks:
default:
aliases:
- host1
- host2
pingしてみます。
$ docker-compose run app ping host1
PING host1 (172.20.0.2) 56(84) bytes of data.
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=1 ttl=64 time=0.161 ms
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=2 ttl=64 time=0.088 ms
^C
--- host1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1037ms
rtt min/avg/max/mdev = 0.088/0.124/0.161/0.038 ms
$ docker-compose run app ping host2
PING host2 (172.20.0.2) 56(84) bytes of data.
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=1 ttl=64 time=0.091 ms
64 bytes from sample_nginx_1.sample_default (172.20.0.2): icmp_seq=2 ttl=64 time=0.085 ms
^C
--- host2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.085/0.088/0.091/0.003 ms
ポートを開ける
コンテナのportをポートフォワードしたいときはportを指定します。
services:
nginx:
image: nginx
ports:
- 8000:80
左にホストOSのポート、右にコンテナ(この場合はnginxコンテナ)のポートを指定します。
これでhttp://localhost:8000/ としてアクセスできます。
変数を使う
変数には二種類あります。docker-compose.yml内で使用するものと、コンテナを起動したときに環境変数として設定されるものです。
このあたりのファイルにホスト名などの変更されやすい情報や、リポジトリに含めない設定ファイルにパスワードなどの重要な情報を設定してしたりしておくと便利です。重要情報はリポジトリに含めない設定ファイルにです。大事なことなので二回言いました。
docker-compose.ymlで使うための変数
カレントディレクトリに.envファイルを作ります。
HOGE=centos:7
それでdocker-compose.ymlではこう。
services:
app:
image: ${HOGE}
コンテナ内に設定する環境変数
environmentとenv_fileを使います。
environment
docker-compose.ymlに直接書きます。
services:
app:
environment:
ENV_SAMPLE: hoge
コンテナ内で確認。
$ docker-compose run app
[root@31bc6a655b81 /]# echo $ENV_SAMPLE
hoge
env_file
数が多いときはファイルにまとめます。
local_envファイルを作成して、次のように書いておきます。
ENV_LOCAL=hoge2
docker-composeのenv_fileでファイルを指定します。複数指定も可能です。(その場合、下に書いたファイルが優先されます)
services:
app:
env_file:
- local_env
コンテナ内で確認。
$ docker-compose run app
[root@7ccdfccb3d3c /]# echo $ENV_LOCAL
hoge2
[root@7ccdfccb3d3c /]#
environemntとenv_fileで同じ環境変数を指定した場合
environmentのほうが優先されます。docker-compose.ymlに直書きされているものが強いということですね。
.envの変数はenv_fileのファイルでは使えない
先ほど.envで指定したHOGEは、environmentでは使えますがenv_fileで指定したファイル内では使えません。
docker-comopse.yml
services:
app:
environment:
ENV_HOGE: ${HOGE}
env_file:
- local_env
local_env
ENV_HOGE_LOCAL=${HOGE}
コンテナ実行
$ docker-compose run app
[root@f0fd70a2f2f8 /]# echo $ENV_HOGE
centos:7
[root@f0fd70a2f2f8 /]# echo $ENV_HOGE_LOCAL
${HOGE}
[root@f0fd70a2f2f8 /]#
.envをそのままenv_fileに指定する
形式は同じなので.envをそのまま環境変数に設定できたりもします。
services:
app:
env_file:
- .env
コンテナでの確認
$ docker-compose run app
[root@2e4b9ac6253a /]# echo $HOGE
centos:7
自動起動しないようにする
デフォルトの状態だと、docker-compose upしたコンテナはDockerデーモンが再起動すると自動起動するようになっています。
その設定はrestartで変更できます。
services:
app:
image: centos:7
restart: no
restartに設定できるパラメータはDocker runの--restartオプションと一緒です。
参考
ざっくりなのでそれぞれの機能とか、深いところは必要に応じて調べていってもらえればと思います。
- 公式ドキュメント
細かいオプションなんかはリファレンスを見て下さい。
- 日本語ドキュメント
日本語ドキュメントはところどころ古いですが、そこまで大きな違いはないため参考になります。(あれっと思ったら本家公式のほうを当たることもあります)
- Dockerfileのベストプラクティス