在 docker.service 文件中的 ExecStart 字段中,添加(或:docker run --log-driver=journald):
--log-driver=journald \
之后:
systemctl daemon-reload
systemctl restart docker.service
配置 journald.conf(此文件的各項正文必須單獨占一行,否則不生效) :
[Journal] #日志存儲到磁盤 Storage=persistent #壓縮日志 Compress=yes #為日志添加序列號 Seal=yes #每個用戶分別記錄日志 SplitMode=uid #日志同步到磁盤的間隔,高級別的日志,如:CRIT、ALERT、EMERG 三種總是實時同步 SyncIntervalSec=1m #即制日志的最大流量,此處指 30s 內最多記錄 100000 條日志,超出的將被丟棄 RateLimitInterval=30s #與 RateLimitInterval 配合使用 RateLimitBurst=100000 #限制全部日志文件加在一起最多可以占用多少空間,默認值是10%空間與4G空間兩者中的較小者 SystemMaxUse=64G #默認值是15%空間與4G空間兩者中的較大者 SystemKeepFree=1G #單個日志文件的大小限制,超過此限制將觸發滾動保存 SystemMaxFileSize=128M #日志滾動的最大時間間隔,若不設置則完全以大小限制為准 MaxFileSec=1day #日志最大保留時間,超過時限的舊日志將被刪除 MaxRetentionSec=100year #是否轉發符合條件的日志記錄到本機的其它日志管理系統,如:rsyslog ForwardToSyslog=yes ForwardToKMsg=no #是否轉發符合條件的日志到所有登陸用戶的終端 ForwardToWall=yes MaxLevelStore=debug MaxLevelSyslog=err MaxLevelWall=emerg ForwardToConsole=no #TTYPath=/dev/console #MaxLevelConsole=info #MaxLevelKMsg=notice
之后:
mkdir /var/log/journal chown root:systemd-journal /var/log/journal chmod 0770 /var/log/journal systemctl reset-failed systemd-journald.service && systemctl restart systemd-journald.service
日志查看工具 journalctl 的用法:
journalctl -u/--unit=docker.service \ #可以多次使用該選項,按 OR 邏輯篩選顯示 -o/--output=export \ #指定顯示格式,常用三種: export、json-pretty、cat -r/--reverse \ #反向顯示,即較新的日志顯示在最上面 --no-pager \ #不要使用 less 或 more 分頁顯示 -f/--follow \ #類似 tail -f 效果 --flush \ #將內存中日志同步到磁盤 -D/--directory=DIR \ #指定讀取日志的路徑 --file=zLogFilePath \ #同上,指定具體文件路徑,可同時使用多次指定多個文件 --priority= "emerg" (或 0), "alert" (1), "crit" (2), "err" (3), "warning" (4), "notice" (5), "info" (6), "debug" (7) \ #指定要顯示的日志等級 --since= "2012-10-30 18:17:16" \ --until= "2017-10-30 18:17:16" \ --disk-usage \ #顯示所有日志占用的磁盤空間
#export 格式顯示的特定進程的標識字段均可以用作篩選,例如: CONTAINER_ID= \ #以指定容器 ID 為標識顯示日志 CONTAINER_NAME= \ #同上,指定容器名稱 _PID= \ #以容器進程 ID 為標識顯示日志 _UID= \ #顯示以某個用戶 ID 身份運行的所有容器日志
export 格式輸出樣例:

1 __CURSOR=s=cc2bd54b07c04211996c7eb3a46b4ecc;i=11f8;b=9319f78348534d7c9231b3788881d1be;m=ea1d9a9ab;t=54f2a70366564;x=cb3b442de23e1b6d 2 __REALTIME_TIMESTAMP=1494418573387108 3 __MONOTONIC_TIMESTAMP=62844938667 4 _BOOT_ID=9319f78348534d7c9231b3788881d1be 5 PRIORITY=6 6 _UID=0 7 _GID=0 8 _SYSTEMD_SLICE=system.slice 9 _MACHINE_ID=783e916069bb40508bd037b154bf7593 10 _TRANSPORT=journal 11 _CAP_EFFECTIVE=1fffffffff 12 _HOSTNAME=x 13 _COMM=dockerd-current 14 _EXE=/usr/bin/dockerd-current 15 _SYSTEMD_CGROUP=/system.slice/docker.service 16 _SYSTEMD_UNIT=docker.service 17 _CMDLINE=/usr/bin/dockerd-current --log-driver=journald --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --selinux-enabled --log-driver=journald --signature-verification=false 18 _SELINUX_CONTEXT=system_u:system_r:container_runtime_t:s0 19 CONTAINER_TAG= 20 _PID=9109 21 CONTAINER_ID=bc31bfa22688 22 CONTAINER_ID_FULL=bc31bfa22688736403a5e5e0377630382b4e0ac696b97254e779ce2b90a95b2d 23 CONTAINER_NAME=hopeful_poitras 24 MESSAGE 25 3root@bc31bfa22688:/# date 26 _SOURCE_REALTIME_TIMESTAMP=1494418573386408 27 28 __CURSOR=s=cc2bd54b07c04211996c7eb3a46b4ecc;i=11f9;b=9319f78348534d7c9231b3788881d1be;m=ea1daab4f;t=54f2a70376708;x=e8ea5e3b827ffd6a 29 __REALTIME_TIMESTAMP=1494418573453064 30 __MONOTONIC_TIMESTAMP=62845004623 31 _BOOT_ID=9319f78348534d7c9231b3788881d1be 32 PRIORITY=6 33 _UID=0 34 _GID=0 35 _SYSTEMD_SLICE=system.slice 36 _MACHINE_ID=783e916069bb40508bd037b154bf7593 37 _TRANSPORT=journal 38 _CAP_EFFECTIVE=1fffffffff 39 _HOSTNAME=x 40 _COMM=dockerd-current 41 _EXE=/usr/bin/dockerd-current 42 _SYSTEMD_CGROUP=/system.slice/docker.service 43 _SYSTEMD_UNIT=docker.service 44 _CMDLINE=/usr/bin/dockerd-current --log-driver=journald --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-path=/usr/libexec/docker/docker-proxy-current --selinux-enabled --log-driver=journald --signature-verification=false 45 _SELINUX_CONTEXT=system_u:system_r:container_runtime_t:s0 46 CONTAINER_TAG= 47 _PID=9109 48 CONTAINER_ID=bc31bfa22688 49 CONTAINER_ID_FULL=bc31bfa22688736403a5e5e0377630382b4e0ac696b97254e779ce2b90a95b2d 50 CONTAINER_NAME=hopeful_poitras 51 MESSAGE 52 Wed May 10 12:16:13 UTC 2017 53 _SOURCE_REALTIME_TIMESTAMP=1494418573452545
每個容器對應日志中的多個唯一 ID,可以認為在宿主機上,能夠 100% 標識每一個容器,如:
-
- _BOOT_ID #標識宿主機是哪次啟動的
- _MACHINE_ID #宿主機機器標識
- CONTAINER_ID
- CONTAINER_ID_FULL
- CONTAINER_NAME
外部查看指定容器日志常用命令:
journalctl -u docker.service CONTAINER_ID=bc31bfa22688 -D </Path/To/LogBakDir> -o cat
形如這種的形式的,都是已滾動保存的日志(二進制形式):
system@6c8acebb0081486ba83d698c06cd1d33-0000000000000001-00054f2c2fe295f9.journal system@6c8acebb0081486ba83d698c06cd1d33-0000000000000017-00054f2c31c92008.journal system@6c8acebb0081486ba83d698c06cd1d33-000000000000001d-00054f2c3311307d.journal
最后,將這些滾動日志定時復制或移動到指定位置即可。
自動布署腳本示例:
1 #!/usr/bin/env sh 2 3 zBakDir="/tmp" 4 5 ########################### 6 ##### docker.service ###### 7 ########################### 8 9 zDockerPathA="/etc/systemd/system/docker.service" 10 zDockerPathB="/usr/lib/systemd/system/docker.service" 11 12 if [[ 1 -eq `ls $zDockerPathA 2>/dev/null | wc -l` ]];then 13 zPathToDockerService=$zDockerPathA 14 else 15 zPathToDockerService=$zDockerPathB 16 fi 17 18 if [[ 0 -lt `grep -c 'log-driver=' $zPathToDockerService` ]];then 19 perl -pi.bak -e 's/(?<=--log-driver=)\w+/journald/g' $zPathToDockerService 20 else 21 perl -pi.bak -e 's/(ExecStart=(\/\S+)+)/$1 --log-driver=journald /g' $zPathToDockerService 22 fi 23 24 ############################## 25 ## systemd-journald.service ## 26 ############################## 27 28 zJournaldConfPath="/etc/systemd/journald.conf" 29 zJournaldConf="[Journal]\nStorage=persistent\nCompress=yes\nSeal=yes\nSplitMode=uid\nSyncIntervalSec=30s\n\nRateLimitInterval=30s\nRateLimitBurst=100000\n\nSystemMaxUse=64G\nSystemKeepFree=1G\nSystemMaxFileSize=64M\nMaxFileSec=1day\nMaxRetentionSec=100year" 30 echo -e $zJournaldConf > $zJournaldConfPath 31 32 mkdir -p /var/log/journal 33 chown -R root:systemd-journal /var/log/journal 34 chmod -R 0770 /var/log/journal 35 36 ############################## 37 #### Back up docker log #### 38 ############################## 39 40 zPath="/etc/systemd/system" 41 mkdir -p ${zPath} 42 43 zServName="zDockerLogBakUp" 44 zBakExec="#!/usr/bin/env sh\n\ncp -np /var/log/journal/*/*@*.journal $zBakDir" 45 zBakService="[Unit]\nDescription=''\nAfter=docker.service systemd-journald.service\n\n[Service]\nExecStart=${zPath}/${zServName}.sh\n\n[Install]\nWantedBy=multi-user.target" 46 zBakTimer="[Unit]\nDescription=''\n\n[Timer]\nOnCalendar=*-*-* 02:30:00\nUnit=zDockerLogBakUp.service\n\n[Install]\nWantedBy=multi-user.target" 47 48 echo -e "$zBakExec" > "${zPath}/${zServName}.sh" 49 echo -e $zBakService > "${zPath}/${zServName}.service" 50 echo -e $zBakTimer > "${zPath}/${zServName}.timer" 51 52 chmod u+x ${zPath}/${zServName}.sh 53 54 ############################## 55 #### Start Services #### 56 ############################## 57 58 systemctl daemon-reload 59 systemctl reset-failed docker.service 60 systemctl restart docker.service 61 62 systemctl reset-failed systemd-journald.service 63 systemctl restart systemd-journald.service 64 65 systemctl enable ${zServName}.timer
...