ロギングドライバー
Dockerの標準出力はロギングドライバーの設定によって出力先が変わる。
ロギングドライバーの設定はdocker-compose.yml
のlogging
で指定する。
version: "3.9"
services:
linux:
image: ...
logging:
driver: ドライバー名
logging
を指定していない場合、デフォルトではjson-file
になっている。
JSON File logging driver | Docker Docs
json-file
ドライバーの場合、コンテナの標準出力は/var/lib/docker/containers/コンテナID/コンテナID-json.log
に出力される。
コンテナIDはdocker ps
コマンドで確認できる。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4485fc9e22f1 public.ecr.aws/amazonlinux/amazonlinux:2023.2.20231018.2 "/bin/bash" 4 minutes ago Up 4 minutes docker-test-linux-1
上記の場合は/var/lib/docker/containers/
以下のa7a6696a3640
から始まるフォルダを探せばよい。
$ ls /var/lib/docker/containers/4485fc9e22f1028654e02f6485048efc88b1c01b35993c7c60887bdeb26cd4bf/4485fc9e22f1028654e02f6485048efc88b1c01b35993c7c60887bdeb26cd4bf-json.log
{"log":"Hello, world!\n","stream":"stdout","time":"2021-11-03T01:59:02.000000000Z"}
journaldドライバー
journald
ドライバーを使うとコンテナの標準出力をjournald
に出力できる。
Journald logging driver | Docker Docs
version: "3.9"
services:
linux:
image: public.ecr.aws/amazonlinux/amazonlinux:2023.2.20231018.2
logging:
driver: journald
シェルスクリプトでDockerログ(コンテナの標準出力)に出力する
まずコンテナ内で実行するシェルスクリプトの標準出力をDockerログ(コンテナの標準出力)に出力する。
シェルスクリプトでDockerログ(コンテナの標準出力)に出力するには/proc/1/fd/1
に出力すればよい。
#!/bin/sh
echo "Hello, world" > /proc/1/fd/1
/proc/1/fd/1
はコンテナの標準出力のファイルディスクリプタ。
ホストOS側のjournalctl -f
で出力を表示すれば確認できる。
$ journalctl -f
Nov 03 03:59:23 ip-10-0-13-80.ap-northeast-1.compute.internal 1f2417b25f21[27000]: Hello, world
標準エラーに出力したい場合は/proc/1/fd/2
に出力すればよい。
#!/bin/sh
echo "Hello, world" > /proc/1/fd/2
標準エラーの場合もDockerログに出力されるので、journald
ロギングドライバーを指定していればjournalctl
で確認できる。
コンテナIDを指定してjournalctlで出力を確認する
journaldへのログにコンテナ名をつける
docker-compose.yml
に以下の設定を加えるとjournaldへ出力されるログにコンテナ名をつけられる。
container_name
でコンテナ名をつけるlogging.options
以下にtag="{{.Name}}
を追加する
例えば以下のような設定となる。
version: "3.9"
services:
linux:
image: public.ecr.aws/amazonlinux/amazonlinux:2023.2.20231018.2
container_name: test-container
logging:
driver: journald
options:
tag: "{{.Name}}"
動作確認としてコンテナ内で以下を実行する。
$ echo "Hello, world" >> /proc/1/fd/1
ホストOS側でjournalctl -f
を実行すると以下のように出力される。
$ journalctl -f
Nov 03 04:09:13 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: Hello, world
test-containerというコンテナ名が表示されている。
journalctlでコンテナ名で絞り込む
コンテナ名で絞り込むにはjournalctl
の引数にCONTAINER_NAME=コンテナ名
を追加して実行する。
例えば以下のようになる。
$ journalctl -f CONTAINER_NAME=test-container
Nov 03 04:09:13 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: Hello, world
シェルスクリプトでDockerログに出力する
/proc/1/fd/1、/proc/1/fd/2 に出力する
コンテナ内で実行するシェルスクリプトの標準出力をDockerログ(コンテナの標準出力)に出力するには/proc/1/fd/1
に出力すればよい。
#!/bin/sh
echo "Hello, world" > /proc/1/fd/1
echo "Hello, world" > /proc/1/fd/2
/proc/1/fd/1
はコンテナの標準出力のファイルディスクリプタ。/proc/1/fd/2
はコンテナの標準エラー出力のファイルディスクリプタ。
コンテナ内で上記スクリプトを実行する。
$ sh ./test.sh
ホストOS側のjournalctlで出力を確認する。
$ journalctl -f
Nov 03 04:32:50 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: Hello, world
Nov 03 04:32:50 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: Hello, world
標準出力、標準エラー出力の両方が出力されている。
exec コマンドで一括でDockerログ(コンテナの標準出力)に出力する
exec
コマンドを使うとコンテナ内で実行したコマンドの標準出力をDockerログ(コンテナの標準出力)に出力できる。
シェルスクリプトの先頭で実行しておくと以降のコマンドの出力先を個別に指定する必要がなくなる。
そのためスクリプトを簡潔にできる。
例えば以下のようなシェルスクリプトを実行する。
#!/bin/sh
exec 1>> /proc/1/fd/1 2>> /proc/1/fd/2
echo "Hello, world"
ls aaa # 存在しないパスでエラーを発生させる
コンテナ内で上記スクリプトを実行する。
$ sh ./test.sh
ホストOS側のjournalctlで出力を確認する。
$ journalctl -f CONTAINER_NAME=test-container
Nov 03 04:35:19 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: Hello, world
Nov 03 04:35:19 ip-10-0-13-80.ap-northeast-1.compute.internal test-container[27000]: ls: cannot access 'aaa': No such file or directory
標準出力、標準エラー出力の両方が出力されている。