Docker for Mac の container のログを空にする

Docker for Mac で container のログを空にする方法の紹介です。
執筆時の環境は Docker for Mac 18.06.1-ce-mac73 (26764) です。

前置き

docker inspect を実行すると、container のログファイルのパスを取得できます。

$ docker inspect CONTAINER_ID --format "{{.LogPath}}" /var/lib/docker/containers/3d0305c254c33ff5e78d675f45e60fdcef65937ed8b53e21baf07f818d34ce9b/3d0305c254c33ff5e78d675f45e60fdcef65937ed8b53e21baf07f818d34ce9b-json.log
Code language: JavaScript (javascript)

Linux 上で dockerd や containerd が docker container と同じホストで動いている場合は、以下のようなコマンドを実行することでログを空にできます。

$ sudo truncate $(docker inspect CONTAINER_ID --format "{{.LogPath}}") --size 0 $ sudo bash -c ":> $(docker inspect CONTAINER_ID --format "{{.LogPath}}")"
Code language: JavaScript (javascript)

しかし、macOS の Docker for Mac で docker inspect を実行すると、ログファイルのパスは取得できますが、macOS 上には /var/lib/docker がないので、上記の方法ではログを空にできません。
これは、macOS 上の HyperKit という仮想化環境で LinuxKit という軽量 Linux を動かし、そのうえで containerd を動かしているためです(雑な図にしたものが以下です)。

+------------+ | containerd | +------------+ | LinuxKit | +------------+ | HyperKit | +------------+ | macOS | +------------+

Docker for Mac 環境で container のログを空にしたい場合、macOS ではなく LinuxKit 上のログファイルを空にする必要があります。

LinuxKit への接続

LinuxKit には screen でシリアル接続します。

$ screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty # Ctrl-d を入力すると、以下が出力されます(Ctrl-a + k -> y でコンソールから抜けられます) Welcome to LinuxKit ## . ## ## ## == ## ## ## ## ## === /"""""""""""""""""___/ === { / ===- ______ O __/ __/ ___________/ linuxkit-025000000001 login: root (automatic login) Welcome to LinuxKit! NOTE: This system is namespaced. The namespace you are currently in may not be the root. System services are namespaced; to access, use `ctr -n services.linuxkit ...` login[7397]: root login on 'ttyS0'
Code language: PHP (php)

ただ、LinuxKit 上では docker コマンドを実行できないので、macOS 上でログファイルのパスを取得します。取得後に LinuxKit 上で以下を実行すればログを空にできます。

$ :> /path/to/logfile
Code language: JavaScript (javascript)

しかし、これを毎回実行するのは面倒ですので、shell の関数を定義しておくと良いです。

clear_docker_log() { local container_id="${1}" logfile=$(docker inspect $container_id --format "{{.LogPath}}") screen_name="docker_$(date +%s)" # LinuxKit にシリアル接続(detached screen として) screen -d -m -S ${screen_name} ~/Library/Containers/com.docker.docker/Data/vms/0/tty # ログを空にするコマンドを送信 # 末尾の echo は Enter キー入力のエミュレート screen -S ${screen_name} -p 0 -X stuff $":> ${logfile}"$(echo -ne '\015') # シリアル接続を閉じる screen -S ${screen_name} -X quit }
Code language: PHP (php)

引数に渡した container ID のログを空にできます。
docker-compose を使っている場合は docker-compose ps -q CONTAINER_NAME の結果を渡すような関数を用意しておくと良さそうです。

参考

Leave a Reply