ดำทำไรบันทึกวิธีคิด · ชีวิต · เทคโนโลยี
← กลับหน้าแรก
Tech

ให้ docker เก็บ log ไว้ที่ syslog ดีกว่า ไม่ทำอะไร

ให้ docker เก็บ log ไว้ที่ syslog ดีกว่า ไม่ทำอะไร

โดยปกติ ถ้าไม่ทำอะไรกับ docker เลย เวลาที่เราสร้าง container แล้วอยากดูว่าโปรแกรมใน container มันทำงานอย่างไร มีปัญหาอะไรไหม หนึ่งในวิธีที่เราทำได้ก็คือใช้คำสั่ง docker logs <container_id> แล้วพอเราสั่งลบ container เราก็ไม่รู้จะไปตามหา log จากที่ไหน log ถูกลบไปด้วย พร้อม ๆ กับ container ไปแล้ว

วิถีปกติ

ผมสร้าง container ตัวหนึ่งโดยใช้ image ของ nginx เป็นพระเอกในบทความนี้ และลองเรียกดู log ที่เกิดขึ้น

bash
hostname ~  > docker -v
Docker version 20.10.12, build 20.10.12-0ubuntu4

hostname ~  > docker container run -d --rm --name nginx -p 80:80 nginx
5ee69ab5553717b651de0374c7f0d44553e1445ee917df83b97eadfb2c080774

hostname ~  > docker logs -f nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2023/01/02 06:27:23 [notice] 1#1: using the "epoll" event method
2023/01/02 06:27:23 [notice] 1#1: nginx/1.23.3
2023/01/02 06:27:23 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
[... truncated output ...]
2023/01/02 06:27:57 [error] 30#30: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 192.168.254.191, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.254.195", referrer: "http://192.168.254.195/"
192.168.254.191 - - [02/Jan/2023:06:27:57 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://192.168.254.195/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" "-"

log ที่เห็นเก็บไว้ที่อื่นอีกไหม

มีครับ จริง ๆ แล้วค่าปกติของการจัดการ log ของ docker หรือที่เรียกกันว่า log driver ก็คือ json-file ซึ่งไฟล์นี้จะเก็บอยู่ที่ /var/lib/docker/containers/<container_id>/<container_id>-json.log และที่สำคัญคือ ไฟล์นี้จะถูกลบไปพร้อมกับ container

bash
hostname ~  > docker inspect -f "\{\{ .Id \}\}" nginx
5ee69ab5553717b651de0374c7f0d44553e1445ee917df83b97eadfb2c080774

hostname ~  > CID=$(docker inspect -f "\{\{ .Id \}\}" nginx)
hostname ~  > sudo ls /var/lib/docker/containers/$CID/$CID-json.log
/var/lib/docker/containers/5ee69ab5553717b651de0374c7f0d44553e1445ee917df83b97eadfb2c080774/5ee69ab5553717b651de0374c7f0d44553e1445ee917df83b97eadfb2c080774-json.log

hostname ~  > sudo cat /var/lib/docker/containers/$CID/$CID-json.log
{"log":"/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration\n","stream":"stdout","time":"2023-01-02T06:27:23.793803275Z"}
{"log":"/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/\n","stream":"stdout","time":"2023-01-02T06:27:23.793827012Z"}
{"log":"/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh\n","stream":"stdout","time":"2023-01-02T06:27:23.794500821Z"}
{"log":"10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf\n","stream":"stdout","time":"2023-01-02T06:27:23.82084299Z"}
{"log":"10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf\n","stream":"stdout","time":"2023-01-02T06:27:23.825442382Z"}
{"log":"/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh\n","stream":"stdout","time":"2023-01-02T06:27:23.825618342Z"}
{"log":"/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh\n","stream":"stdout","time":"2023-01-02T06:27:23.828134441Z"}
{"log":"/docker-entrypoint.sh: Configuration complete; ready for start up\n","stream":"stdout","time":"2023-01-02T06:27:23.829238856Z"}
{"log":"2023/01/02 06:27:23 [notice] 1#1: using the \"epoll\" event method\n","stream":"stderr","time":"2023-01-02T06:27:23.832350202Z"}
{"log":"2023/01/02 06:27:23 [notice] 1#1: nginx/1.23.3\n","stream":"stderr","time":"2023-01-02T06:27:23.832418889Z"}
[... truncated output ...]
{"log":"2023/01/02 06:27:57 [error] 30#30: *1 open() \"/usr/share/nginx/html/favicon.ico\" failed (2: No such file or directory), client: 192.168.254.191, server: localhost, request: \"GET /favicon.ico HTTP/1.1\", host: \"192.168.254.195\", referrer: \"http://192.168.254.195/\"\n","stream":"stderr","time":"2023-01-02T06:27:57.569741223Z"}
{"log":"192.168.254.191 - - [02/Jan/2023:06:27:57 +0000] \"GET /favicon.ico HTTP/1.1\" 404 555 \"http://192.168.254.195/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36\" \"-\"\n","stream":"stdout","time":"2023-01-02T06:27:57.570030401Z"}

จะเห็นได้ว่า ข้อมูลในไฟล์ก็จะเป็นข้อมูลเดียวกับ ข้อมูลที่เรียกดูด้วยคำสั่ง docker logs <container_id>

เตรียม Syslog Server เอาไว้เก็บ log จาก container

bash
syslog ~  >  cat <<-EOF | sudo tee /etc/rsyslog.d/01-container-log.conf 
\$template containerLogs,"/var/log/docker/%hostname%_%syslogtag:R,ERE,1,ZERO:.*cname/([^\[]+)--end%.log"

if \$syslogtag contains 'cname'  then -?containerLogs

& stop
EOF

syslog ~  > sudo vi /etc/rsyslog.conf
[ ... truncated output ... ]

# unmark both lines
module(load="imtcp")
input(type="imtcp" port="514")

[ ... truncated output ... ]

syslog ~  > sudo systemctl restart rsyslog

กำหนดให้ log driver เป็น syslog

bash
hostname ~  > vi /etc/docker/daemon.json
{
   "log-driver": "syslog",
   "log-opts": {
           "syslog-address": "tcp://<syslog server ip address>:514",
           "tag": "cname/\{\{.Name\}\}"
   }
}

ตามไปดู log เก็บไว้ที่ไหน

เมื่อกำหนดค่าทั้ง syslog server และ docker host เรียบร้อย ทุกครั้งที่สร้าง container และ container นั้น ๆ มีการส่ง log ออกมา จะมีการส่ง log ไปยัง syslog server และ syslog server จะเขียน log ไว้ที่ /var/log/docker/<docker host name>_<container name>.log

bash
[at Docker Host]
hostname ~  > docker container run -d --rm --name nginx -p 80:80 nginx
093890b14e01cd75f237c990b541556462c68807999cdfa36a20cca75db99101
hostname ~  > docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
093890b14e01   nginx     "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   nginx

[at Syslog Server]
syslog ~  > sudo ls -la /var/log/docker
total 16
drwxr-xr-x 2 syslog syslog 4096 Jan  2 17:19 .
drwxrwxr-x 9 root   syslog 4096 Jan  2 17:00 ..
-rw-r----- 1 syslog adm    5221 Jan  2 17:21 192.168.254.195_nginx.log
syslog ~  > sudo cat /var/log/docker/192.168.254.195_nginx.log
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: /docker-entrypoint.sh: Configuration complete; ready for start up
Jan  2 17:19:58 192.168.254.195 cname/nginx[13453]: 2023/01/02 10:19:58 [notice] 1#1: using the "epoll" event method
[... truncated output ...]

เราจะไม่ทิ้งขว้าง log ของ application ใน container ที่สร้างด้วย docker กันนะครับ

Made by มูลค่าความสุข