docker diffコマンド

docker diffコマンドは、コンテナが起動してからファイルシステムに加えられた変更を確認するコマンド。

ベースイメージとコンテナの差分(追加・変更・削除されたファイル)を一覧で確認できる。

$ docker diff <コンテナ>

<コンテナ>にはコンテナ名かコンテナIDを指定する。

出力の読み方

出力は以下3種類のプレフィックスで表される。

プレフィックス意味
A追加(Added)
C変更(Changed)
D削除(Deleted)

実行例

Rocky LinuxのDockerコンテナを起動してファイルを操作する。

$ docker run -it --name diff-test rockylinux/rockylinux:8 /bin/bash
[root@diff-test /]# echo "hello" > /tmp/test.txt
[root@diff-test /]# echo "changed" >> /etc/motd

別のターミナルからdocker diffコマンドを実行すると、コンテナのファイルシステムの変更を確認できる。

$ docker diff diff-test
C /tmp
A /tmp/test.txt
C /etc/motd

/tmp/test.txtが追加(A)、/tmp/etc/motdが変更(C)されていることが分かる。

ECSでルートファイルシステムを読み取り専用にする際の活用

Amazon ECSのタスク定義ではreadonlyRootFilesystemtrueに設定すると、コンテナのルートファイルシステムを読み取り専用にできる。

{
  "containerDefinitions": [
    {
      "name": "my-app",
      "image": "my-app:latest",
      "readonlyRootFilesystem": true
    }
  ]
}

読み取り専用を有効にすると、コンテナが書き込みを試みたパスでエラーが発生する。
docker diffコマンドを使うと、コンテナが書き込みを行なうパスを事前に調査できる。

調査手順

readonlyRootFilesystemを設定せずにコンテナを起動し、アプリケーションを動作させる。
その後docker diffコマンドで書き込みが発生しているパスを確認する。

$ docker diff my-app
C /var
C /var/log
A /var/log/app.log
C /tmp
A /tmp/cache

書き込みが必要なパスを特定したら、ECSのタスク定義でそれらのパスにボリュームマウントを設定した上でreadonlyRootFilesystem: trueを有効にする。

{
  "containerDefinitions": [
    {
      "name": "my-app",
      "image": "my-app:latest",
      "readonlyRootFilesystem": true,
      "mountPoints": [
        {
          "sourceVolume": "tmp",
          "containerPath": "/tmp"
        },
        {
          "sourceVolume": "log",
          "containerPath": "/var/log"
        }
      ]
    }
  ],
  "volumes": [
    { "name": "tmp", "host": {} },
    { "name": "log", "host": {} }
  ]
}

docker diffで書き込みパスを洗い出してからマウント設定を行なうと、設定の抜け漏れを防げる。