dockerのコンテナの自動起動をsystemdにて行う際の注意点について
Linuxのsystemdを使用してコンテナの自動起動を行う方法がDocker公式ドキュメントに載ってましたので、試してみたのですが、意外にハマってしまいました。
その検証で行ったことや解消方法などをまとめてみました。
本記事は、systemdを使用してコンテナの自動起動を行う場合の注意点に関する記事です。Dockerの自動起動に関する色々な方法に関しましては、本サイト内の別記事「Docker(Linux版)のカテゴリ別の自動起動テクニック」をご参照ください。
Dockerをちょっと試してみる程度の頃は特に気にならないのですが、常駐サービスのコンテナを作るなど、実践的にDockerを使い始めてくると、コンテナの自動起動が必要になってくるのではないかと思います。
dockerには、コンテナ起動時の「docker run」コマンドに「restart」オプションがありまして、Dockerデーモン起動時のコンテナの動作を設定することが可能です。このオプションを利用することで、自動起動を実現することが出来ます。
でも、もっとシンプルに解決できる方法はないものかと調べていたところ、本家Dockerの公式ドキュメントにsystemdを利用する方法が載ってました。
その方法と注意点をまとめましたので、ご紹介します。
※本記事では、Linux(CentOS7)版のDocker Engine1.12.0を使用しております。
本記事の目次
テスト用コンテナの作成
※自動起動を行いたいコンテナが既に存在する場合でも、まずテスト用コンテナで動作確認することをおすすめいたします。
本記事では、Webサービス(Apache)のコンテナを使用して進めていきます。
まず初めに、以下のコマンドでコンテナを作成します。
$ docker create --name testwebserver -p 9999:80 httpd
「testwebserver」の部分はコンテナ名です。Docker環境内でユニークになる名前を指定してください。
以下のコマンドで、コンテナが作成されていることを確認します。
$ docker ps -a | grep testwebserver f665bc5f5304 httpd "httpd-foreground" 23 seconds ago Created testwebserver
念のため起動確認を行います。
$ docker start testwebserver
ブラウザにてDockerホストの9999番にアクセスして動作確認を行います。
確認が出来ましたら、以下のコマンドで停止しておきます。
$ docker stop testwebserver
コンテナをsystemdに登録する方法
では、準備が出来ましたのでsystemdに登録します。
※以下はroot権限にて作業を行う必要があります。
コンテナを登録する定義ファイルを/etc/systemd/systemディレクトリ内に作成します。
ファイル名は、「<サービス名>.service」としてください。<サービス名>はDockerホスト内でユニークな名前を指定してください。
以下では<サービス名>をwebserver1として進めます。
# vi /etc/systemd/system/webserver1.service
ファイル内に以下の内容を記述します。
[Unit] Description=Web container Requires=docker.service After=docker.service [Service] Restart=always ExecStart=/usr/bin/docker start -a testwebserver ExecStop=/usr/bin/docker stop -t 2 testwebserver [Install] WantedBy=default.target
[Service]タグ内の「ExecStart=」部分にコンテナ起動コマンドを、「ExecStop=」コンテナ停止コマンドを記述します。
(注意1)
「ExecStart=」の設定値は、「systemctl start」コマンドにてサービスを起動する際に実行される内容です。「docker start」コマンドには「-a」オプションを必ず指定してください。指定しない場合は、正常にコンテナが起動しない場合があります。(詳細は「まとめ」の章に記載)
(注意2)
「ExecStop=」の設定値は、「systemctl start」コマンドにてサービスを停止する際に実行される内容です。「docker stop」コマンドの「-t」オプションは、停止処理が開始してから、強制停止(プロセスのkill)が掛かるまでの時間(単位は秒、デフォルトは10秒)の指定です。コンテナ内のサービスに応じて調整してください。
ファイルを作成しましたら、以下のコマンドにて、systemdに登録します。
# systemctl daemon-reload
これでコンテナがsystemdに登録されました。
systemdに登録したコンテナの起動/停止確認
systemdに登録が終わりましたら、コンテナの起動確認を行います。
以下のコマンドでコンテナを起動します。
# systemctl start webserver1
以下のコマンドで起動確認を行います。
# systemctl status webserver1
正常に起動されている場合は、以下のような内容が出力されます。
● webserver1.service - Web container Loaded: loaded (/etc/systemd/system/webserver1.service; disabled; vendor preset: disabled) Active: active (running) since 2016-08-30 14:34:42 JST; 47s ago Main PID: 7104 (docker) Memory: 3.5M CGroup: /system.slice/webserver1.service mq7104 /usr/bin/docker start -a testwebserver (以下略)
上から3行目くらいのところの「active (running)」を確認します。
何度か起動確認を行い、コンテナが再起動を繰り返していないかなど、正常に動作していることを確認してください。
念のため、「docker ps」コマンドでも確認を行って下さい
# docker ps
次に、以下のコマンドにてコンテナの停止を行います。
# systemctl stop webserver1
以下のコマンドで停止確認を行います。
# systemctl status webserver1
正常に停止すると、以下のような内容が出力されます。
● webserver1.service - Web container Loaded: loaded (/etc/systemd/system/webserver1.service; disabled; vendor preset: disabled) Active: inactive (dead) (以下略)
systemdによるコンテナの自動起動設定
systemdによるコンテナの起動停止が確認できましたので、いよいよ自動起動の設定です。
以下のコマンドで自動起動の設定を行います。
# systemctl enable webserver1
正常に設定されると、以下のような内容が出力されます。
Created symlink from /etc/systemd/system/default.target.wants/webserver1.service to /etc/systemd/system/webserver1.service.
以下のコマンドで自動起動の設定になっているか確認します。
# systemctl status webserver1
以下のような現状のサービスのステータスが表示されます。
● webserver1.service - Web container Loaded: loaded (/etc/systemd/system/webserver1.service; enabled; vendor preset: disabled) Active: inactive (dead)
2行目の「Loaded: loaded (/etc/systemd/system/webserver1.service;」の次が「enabled;」になっていることを確認します。
では、Dockerホストを再起動して、コンテナが自動起動されているか確認しましょう。
Dockerホストが立ち上がりましたら、以下のコマンドでコンテナのステータスを確認しましょう。
# systemctl status webserver1
# docker ps
もし、どちらか1つでも異常な状態でしたら、本記事の最初から見直してください。特にコンテナ起動時のオプションとsystemdの定義ファイルの内容は、重点的にお願いします。
ちなみに、自動起動をやめる場合は、以下のコマンドを実行します。
# systemctl disable webserver1
以下のコマンドで自動起動の設定が解除されているか確認します。
# systemctl status webserver1
以下のような現状のサービスのステータスが表示されます。
● webserver1.service - Web container Loaded: loaded (/etc/systemd/system/webserver1.service; disabled; vendor preset: disabled) Active: inactive (dead)
2行目の「Loaded: loaded (/etc/systemd/system/webserver1.service;」の次が「disabled;」になっていることを確認します。
systemdで自動起動設定を行った場合の注意点
systemdで自動起動を行う場合の注意点を列挙します。
1.systemd登録ファイルのコンテナ起動コマンド「docker start」に「-a」を付ける
systemdでコンテナの起動停止を行うためには、対象コンテナをsystemd管理下に置く必要があります。「-a」を付けることによって、systemdによって起動されたコンテナは、systemdによって制御が可能となります。
2.コンテナの起動/停止はsystemctlコマンドを使用する
systemd管理下のコンテナの起動停止は、systemctlコマンドで行う必要があります。
systemd管理下のコンテナをdockerコマンドにて起動停止してしまった場合は、不整合が発生し、想定外の動作をする可能性があります。
例えば、systemdの「Restart=always」指定がある場合は、dockerコマンドでコンテナを停止しても、直ぐに起動されます。
3.「Restart」設定はsystemdの機能にて行う
systemd管理下のコンテナをDockerの「restart」オプションを付けて起動している場合、systemd管理外でコンテナの起動停止が行われる可能性があります。
もし起動停止が行われた場合は、不整合が発生し、想定外の動作をする可能性があります。
まとめ
最初は、Windowsのスタートアップの機能のノリでsystemdを試していたのですが、考えが甘すぎました。
中でも、「docker start」時の「-a」オプションはハマリポイントでした。
最初は「-a」を付けずに試していまして、サクっと起動したので、お手軽だあ、と思っていたのですが、実際にマシンを再起動したり、わざとdockerコマンドで停止させたり起動させたりしている内に、どうやってもコンテナが起動できなくなってしまいました。
その時には「-a」を外したことなんてすっかり忘れてまして・・・。「-a」を付けてからは、問題は出なくなりました。
あと、Dockerの公式ドキュメントには、systemdの「Restart=always」オプションが指定してあり、私の記事でも付けてます。
このオプションに関する私の考えは、コンテナがなんらかの原因で落ちた場合の自動再起動はあったほうが良いと思うが、systemd管理下のコンテナでDockerのrestart機能は使わないほうが良いので、結果としてsystemdのrestartオプションを指定する、です。
色々書いては見ましたが、結局のところ、コンテナの管理をsystemdに任せた場合、Docker側の立場からすると、なにかと面倒な気がするので、systemdにはあまり任せたくない気がします。
最後までご覧いただきありがとうございました。
ご意見など御座いましたら、どんな些細なことでも構いませんのでコメントいただけるとありがたいです。場合によっては、本記事に反映させたいと思います。