結論
書き換わってほしくない設定は、docker.service
ではなく /etc/docker/daemon.json
に書きましょう。
前提
- CentOS Linux release 7.8.2003 (Core)
- Docker version 19.03
概要
yum updateをcronで走らせていたところ、ある日のアップデート後にDockerイメージがすっからかんになっていました。
原因はDockerデーモンの実行時のルートをサービスファイル内で書き替えていたためでした。
yum updateのタイミングでdocker.service
が新しいバージョンのデフォルト設定に置き換わり、実行時のルートが既定値(/var/lib/docker
)に戻ってしまっていたわけですね。
再現手順
もともとdocker-ceが入っていたマシンでyum remove docker-ce
した後を想定しています。
ちょっと前のバージョンのDockerをインストールする
ちょっと前のバージョンは以下のコマンドで確認できます。
# yum list --showduplicates | grep docker-ce.x86_64
docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.3.ce-1.el7 docker-ce-stable
docker-ce.x86_64 17.06.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.1.ce-1.el7.centos docker-ce-stable
(以下略)
アーキテクチャがx86_64
でない場合は適宜読み替えてください。適当に 19.03.10
でもインストールします。(最新でなければ何でもいいです。)
# yum install -y docker-ce-19.03.10-3.el7
docker.service
を書き替える
もとのファイルは以下の通りです。長いので書き替える予定の[Service]の部分だけ抜粋します。
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
これを以下のように変更します。/opt/docker
はあらかじめ作っておきます。
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --graph /opt/docker --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
hello-world
を実行し、イメージが/opt/docker
配下に行ったことを確認します。
# systemctl start docker
# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
(省略)
# ll /opt/docker
total 0
drwx------. 2 root root 24 Nov 2 04:46 builder
drwx--x--x. 4 root root 92 Nov 2 04:46 buildkit
drwx------. 3 root root 78 Nov 2 04:46 containers
drwx------. 3 root root 22 Nov 2 04:46 image
drwxr-x---. 3 root root 19 Nov 2 04:46 network
drwx------. 6 root root 261 Nov 2 04:46 overlay2
drwx------. 4 root root 32 Nov 2 04:46 plugins
drwx------. 2 root root 6 Nov 2 04:46 runtimes
drwx------. 2 root root 6 Nov 2 04:46 swarm
drwx------. 2 root root 6 Nov 2 04:46 tmp
drwx------. 2 root root 6 Nov 2 04:46 trust
drwx------. 2 root root 25 Nov 2 04:46 volumes
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
良いですね。
yum update する
2020/11/02時点で最新の 19.03.13
に更新します。
# yum update -y docker-ce
# docker --version
Docker version 19.03.13, build 4484c46d9d
サービスファイルを確認します。([Service]のみ抜粋)
# cat /usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
先ほど設定したはずの --graph=/opt/docker
が消えていますね。
以下のように /opt/docker
には元のファイルが残っているにもかかわらず、イメージ一覧はからっぽになりました。
# ll /opt/docker/
total 0
drwx------. 2 root root 24 Nov 2 04:46 builder
drwx--x--x. 4 root root 92 Nov 2 04:46 buildkit
drwx------. 3 root root 78 Nov 2 04:46 containers
drwx------. 3 root root 22 Nov 2 04:46 image
drwxr-x---. 3 root root 19 Nov 2 04:46 network
drwx------. 6 root root 261 Nov 2 04:46 overlay2
drwx------. 4 root root 32 Nov 2 04:46 plugins
drwx------. 2 root root 6 Nov 2 04:46 runtimes
drwx------. 2 root root 6 Nov 2 04:46 swarm
drwx------. 2 root root 6 Nov 2 04:46 tmp
drwx------. 2 root root 6 Nov 2 04:46 trust
drwx------. 2 root root 25 Nov 2 04:46 volumes
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
解決方法
/etc/docker/daemon.json
を利用します。
デフォルトで入るdocker.service
のexecStart
の内容は以下の通り
/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ここに設定されているオプション以外はすべてデフォルト値が利用されます。公式ガイドをもとに、関係ありそうなオプションをチェックしましょう。
オプション | 既定値 | 説明 |
---|---|---|
-g, --graph | /var/lib/docker | Docker 実行時の Docker ルート |
--config-file | /etc/docker/daemon.json | デーモン設定ファイル |
--graph
は更新時に入るサービスファイルでは未指定のため、どうあがいても/var/lib/docker
に戻ってしまいます。なのでデフォルトで --config-file
として指定されている /etc/docker/daemon.json
を編集すれば良いです。
Dockerインストール時には存在しないファイルなので、新しく作成します。
以下の内容になるようファイルを編集しましょう。
# cat /etc/docker/daemon.json
{
"graph": "/opt/docker"
}
確認
一度docker-ceをアンインストールし、もう一度アップデートを試します。確認のためDocker実行時のルートの中身も消しておきます。
# yum remove docker-ce
# rm -rf /var/lib/docker/*
# rm -rf /opt/docker/*
・過去バージョンのインストール
# yum -y yum install -y docker-ce-19.03.10-3.el7
# systemctl stard docker
・設定ファイルの確認
# cat /usr/lib/systemd/system/docker.service
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# cat /etc/docker/daemon.json
{
"graph": "/opt/docker"
}
・hello-world実行
# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
(以下省略)
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
# ll /opt/docker/
total 0
drwx------. 2 root root 24 Nov 2 05:14 builder
drwx--x--x. 4 root root 92 Nov 2 05:14 buildkit
drwx------. 3 root root 78 Nov 2 05:14 containers
drwx------. 3 root root 22 Nov 2 05:14 image
drwxr-x---. 3 root root 19 Nov 2 05:14 network
drwx------. 6 root root 261 Nov 2 05:14 overlay2
drwx------. 4 root root 32 Nov 2 05:14 plugins
drwx------. 2 root root 6 Nov 2 05:14 runtimes
drwx------. 2 root root 6 Nov 2 05:14 swarm
drwx------. 2 root root 6 Nov 2 05:14 tmp
drwx------. 2 root root 6 Nov 2 05:14 trust
drwx------. 2 root root 25 Nov 2 05:14 volumes
・yum update 実行
# yum -y update docker-ce
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 10 months ago 13.3kB
これでcronでDockerを更新しても大丈夫ですね!
終わりに
daemon.json
はサービスファイルの execStart
で設定できる部分はおそらく全てカバーできるはずです。docker.service
はノータッチで、daemon.json
を更新しましょう。
ちなみに僕はこれにしばらく気づかずcronのyum updateの後処理でsedかけてました。そんなゴリ押しはやめましょう。(自戒)
参考
-
Docker-docs-ja daemon
デーモン起動時のオプションの日本語リファレンス