はじめに
ある日、Dockerでmysqlコンテナを起動させようとしたら、すでに指定したポートが利用されていますと表示されました。
なんでかなと思ってdocker psを実行してみると、別のmysqlコンテナが起動されていました。docker-compose.ymlを見てみると設定をミスってしまっていたのでその共有をしたいと思います。
TL;DR
-
restart: always
を記述するとローカル環境でもDocker再起動時にコンテナが自動的に立ち上がる - ローカル用と本番用などのdocker-compose.ymlを分けるべき
原因
原因としては、確認用だしざっと見て大丈夫そうだからコピペでいいやと思い、composeファイルの中身をコピペした中にrestart: always
が含まれていたためでした。
restartは何をしているのか
restartではDockerが終了した際や再起動した際の設定を決めることができます。
以下の4種類の設定があり、今回はalways
を指定していました。
-
no
: コンテナを自動的に再起動しない。デフォルトの設定はこれ。 -
on-failure[:max-retries]
: エラーが原因で終了した場合にコンテナを再起動する。max-retries
で指定した回数、起動を試行する。 -
always
: コンテナが停止した場合、自動的に起動される。 -
unless-stopped
:always
に似ているが、コンテナが停止している状態でDockerが再起動された場合にはコンテナは再起動されず、それ以外の状態の場合には再起動される。つまり、明示的にコンテナを停止させた状態で、Dockerが再起動された場合はコンテナは自動的に起動されない。
Dockerでは再起動ポリシーというものが指定されており、そのポリシーに従って再起動が行われます。特に2つ目のポイントが重要で、手動で停止したときは自動的に起動されません。そうしないとコンテナを削除しない限り永久に起動することになってしまうので...
A restart policy only takes effect after a container starts successfully. In this case, starting successfully means that the container is up for at least 10 seconds and Docker has started monitoring it. This prevents a container which doesn't start at all from going into a restart loop.
If you manually stop a container, the restart policy is ignored until the Docker daemon restarts or the container is manually restarted. This prevents a restart loop.
Restart policies only apply to containers. To configure restart policies for Swarm services, see flags related to service restart.
どうすれば良いか
ローカルで利用するdocker-compose.ymlの他に別の環境で利用するdocker-compose.ymlを用意してあげるのが良いと思います。
コンテナを起動させるときに-fオプションをつけることでファイルを指定することができるため、ローカルではrestart: always
を記述していないdocker-compose.ymlを利用し、本番環境などではrestart: always
を記述したdocker-compose.ymlを利用することでやりたいことを実現することができます。
この理由以外にもdocker-compose.ymlを分けることで環境毎に設定を変更することができるので環境毎にファイルを作ることをおすすめします。
参考