はじめに
Docker上でsystemdを使用したサービスを起動したいと思ったが調べるのに思いのほか苦戦してしまったのでここに残します
※systemdで起動しているものを直接起動してよいのならばsystemdを使用する必要はありません
※この記事ではprivilegedオプションを使用するため権限には十分注意してください
systemdとは
Linuxカーネルが起動する(PID 1)のinitプロセス。
このsystemdはすべてのプロセスの親となります
Docker(centos7)上のsystemd
Docker上では基本的にsystemdを有効にされていません。
systemdが起動していないとsystemctlコマンドを使って操作するサービスを使うことができません。
有効にするためにはprivilegedオプションで特権を許可、PID1で/sbin/initを実行する必要があります。
しかし、PID1で起動するためにはDocker run時に/sbin/initを実行しなければならないためユーザースクリプトを起動できません。
ユーザースクリプトを起動しその中で/sbin/initを実行してもPID1にならないためです。
サービスの自動実行
本来起動時に実行されるサービスは以下のようなコマンドで有効にします
systemctl enable <サービス名>
しかし、/sbin/init起動前には実行できず、/sbin/init起動後はユーザースクリプトを起動できません。
そのため、手動でsystemctl enableと同じ操作を行います。
準備
単純な自作サービスを作成し、自動実行することを目指します。
以下のサービス設定ファイルをmyService.serviceとして保存します
[Unit]
Description=自作のテストサービス
[Service]
Type=simple
ExecStart=/test/startup.sh
Restart=no
[Install]
WantedBy=multi-user.target
また、startup.shとして以下を保存します。
#! /bin/sh
echo "hogehoge"
最後にDockerfileを作成します。
自動起動の手動設定としてシンボリックリンクをデフォルトの自動起動ユニット(multi-user.target)の依存関係に追加しています
FROM centos:7
COPY myService.service /etc/systemd/system/myService.service
RUN ln -s /etc/systemd/system/myService.service /etc/systemd/system/multi-user.target.wants/myService.service
COPY startup.sh /test/startup.sh
RUN chmod +x /test/startup.sh
CMD ["/sbin/init"]
実行
docker build -t systemdtest .
docker run -d --privileged --name systemdtest systemdtest
以下のコマンドで動作確認します
docker exec systemdTest systemctl status myService
実行結果は以下のようになっており、実際に起動し、終了したことがわかります。
● myService.service - 自作のテストサービス
Loaded: loaded (/etc/systemd/system/myService.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Mon 2021-04-26 13:42:42 UTC; 14s ago
Process: 53 ExecStart=/test/startup.sh (code=exited, status=0/SUCCESS)
Main PID: 53 (code=exited, status=0/SUCCESS)
Apr 26 13:42:42 4c44e9ad157e systemd[1]: Started 自作のテストサービス.
Apr 26 13:42:42 4c44e9ad157e startup.sh[53]: hogehoge
おわりに
誤った記述や誤字脱字など指摘あれば是非お願いします