Docker 容器日誌分析

查看容器日誌

先使用 docker run -it --rm -d -p 80:80 nginx:1.15.8-alpine 命令啓動一個nginx容器。若是沒有異常,會獲得容器ID如 d2408a7931c95a3a83ffeca2fba887763cf925a67890ef3be4d9ff838aa25b00 的長串。再使用 curl -i http://127.0.0.1 訪問服務,確認nginx容器正常啓動運行。最後使用 docker logs -f d24 查看容器的日誌輸出,大概以下:html

172.17.0.1 - - [24/Mar/2019:03:51:21 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
複製代碼

通常來講使用容器ID的前3位便可mysql

以上就是咱們查看容器日誌的平常方法了,很是簡單實用。linux

容器日誌文件存儲

容器的日誌會以json文件方式存儲在本地磁盤,可使用下面方式查看文件路徑 docker inspect d42 | grep Log 能夠找到:nginx

"LogPath": "/var/lib/docker/containers/d2408a7931c95a3a83ffeca2fba887763cf925a67890ef3be4d9ff838aa25b00/d2408a7931c95a3a83ffeca2fba887763cf925a67890ef3be4d9ff838aa25b00-json.log",
複製代碼

注意1:mac上沒有/var/lib/docker目錄 ,由於docker for mac的運做方式不同,最好使用linux系統練習。git

注意2: 若是LogPath內容爲空,大概是由於docker engine版本,升級docker版本能到docker-ce 18.09.3github

查看 d2408a7931c95a3a83ffeca2fba887763cf925a67890ef3be4d9ff838aa25b00-json.log 文件,能夠看到:sql

{"log":"172.17.0.1 - - [24/Mar/2019:03:51:21 +0000] \"GET / HTTP/1.1\" 200 612 \"-\" \"curl/7.29.0\" \"-\"\r\n","stream":"stdout","time":"2019-03-24T03:51:21.982476951Z"}
複製代碼

這條信息的log字段內容和以前經過 docker logs 命令查看的內容一致。docker

容器日誌會跟隨容器生命週期,容器銷燬後日志也會銷燬。使用 docker stop 24 關停測試的nginx服務。由於容器啓動使用時候用了 --rm 參數,關停後會自動清理刪除,因此會發現 /var/lib/docker/containers/d2408a7931c95a3a83ffeca2fba887763cf925a67890ef3be4d9ff838aa25b00 目錄不存在了,相應的日誌文件也就刪除了。shell

容器日誌文件滾動策略

docker容器日誌默認寫入json文件,在線上運行時候會有磁盤寫滿的風險。能夠調整策略,讓其進行滾動。修改/etc/docker/daemon.json(若是沒有就手工建立一個),增長下面內容:json

{
  "log-opts": {
    "max-size": "1m",
    "max-file": "3"
  }
}
複製代碼

修改完成後重啓docker服務:

systemctl daemon-reload
systemctl restart docker.service
複製代碼

測試一下新的日誌策略,使用下面的命令建立一個容器:

docker run -d --rm alpine:3.6 sh -c "while true; do echo hello world; usleep 10; done"
複製代碼

這個alpine容器就是每隔10微秒輸出hello world,保持高頻度輸出,快速生產日誌文件。

注:shell中的時間控制
一、sleep : 默認爲秒。
sleep 1s 表示延遲一秒  
sleep 1m 表示延遲一分鐘  
sleep 1h 表示延遲一小時  
sleep 1d 表示延遲一天    
  
二、usleep : 默認以微秒。  
1s = 1000ms = 1000000us
複製代碼

按照前文中查看日誌文件的方法

# pwd
/var/lib/docker/containers/aa3307f5b42770319129e126122be123cfd8e0ebe1c412371ad27e62faa007e3
# ls -lah
total 2.6M
drwx------ 4 root root 4.0K Mar 24 16:22 .
drwx------ 3 root root 4.0K Mar 24 16:21 ..
-rw-r----- 1 root root 647K Mar 24 16:22 aa3307f5b42770319129e126122be123cfd8e0ebe1c412371ad27e62faa007e3-json.log
-rw-r----- 1 root root 977K Mar 24 16:22 aa3307f5b42770319129e126122be123cfd8e0ebe1c412371ad27e62faa007e3-json.log.1
-rw-r----- 1 root root 977K Mar 24 16:21 aa3307f5b42770319129e126122be123cfd8e0ebe1c412371ad27e62faa007e3-json.log.2
複製代碼

很容易發現,日誌文件的策略就是維持3個1m大小文件存在,和咱們設置保持一致。

測試完成後,記得使用docker stop aa3 清理測試現場,max-size也能夠按照真實需求調整大小。

nginx容器日誌

瞭解docker容器的日誌策略後,再看看經常使用的容器是如何處理的。先看看nginx容器。

首先 docker run -it --rm -d -p 80:80 nginx:1.15.8-alpine 建立一個nginx容器,而後 docker exec -it b6d sh 進入容器,查看/etc/nginx/nginx.conf能夠看到下面內容:

error_log  /var/log/nginx/error.log warn;
access_log  /var/log/nginx/access.log  main;
複製代碼

也就是nginx會將錯誤日誌和訪問日誌寫入對應的日誌文件。繼續查看/var/log/nginx目錄:

/var/log/nginx # ls -lah
total 0
drwxr-xr-x    2 root     root          39 Mar  4 07:54 .
drwxr-xr-x    3 root     root          18 Mar  4 07:54 ..
lrwxrwxrwx    1 root     root          11 Jan 31 23:32 access.log -> /dev/stdout
lrwxrwxrwx    1 root     root          11 Jan 31 23:32 error.log -> /dev/stderr
複製代碼

這就發現奧祕了,access.log文件會經過軟連接重定向到標準輸出,而錯誤日誌error.log則會重定向標準錯誤。這樣使用docker log命令就能夠看到nginx的訪問日誌了。

爲了進一步驗證,查看nginx dockerfile文件,其中有:

# forward request and error logs to docker log collector
	&& ln -sf /dev/stdout /var/log/nginx/access.log \
	&& ln -sf /dev/stderr /var/log/nginx/error.log
複製代碼

可見nginx鏡像建立時候就定義好了日誌文件的輸出。

一樣使用docker stop 524清理現場,之後就再也不介紹清理這一步驟了。

mysql容器日誌

啓動一個mysql容器

docker run --rm -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
複製代碼

不難看到mysql容器日誌輸出, 截取其中片斷以下:

Initializing database
2019-03-24T08:48:19.102726Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2019-03-24T08:48:20.241459Z 0 [Warning] InnoDB: New log files created, LSN=45790
2019-03-24T08:48:20.414933Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2019-03-24T08:48:20.509897Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 935a6ee7-4e11-11e9-b135-0242ac110002.
2019-03-24T08:48:20.519148Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
2019-03-24T08:48:20.519843Z 1 [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2019-03-24T08:48:24.066683Z 1 [Warning] 'user' entry 'root@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066730Z 1 [Warning] 'user' entry 'mysql.session@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066740Z 1 [Warning] 'user' entry 'mysql.sys@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066756Z 1 [Warning] 'db' entry 'performance_schema mysql.session@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066761Z 1 [Warning] 'db' entry 'sys mysql.sys@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066772Z 1 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066814Z 1 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
2019-03-24T08:48:24.066822Z 1 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
Database initialized
Initializing certificates
Generating a RSA private key
複製代碼

查看mysql Dockerfile 文件,能夠知道mysql鏡像啓動入口在entrypoint.sh,從腳本中發現:

echo 'Initializing database'
"$@" --initialize-insecure
echo 'Database initialized'
複製代碼

這樣就是mysql容器啓動時候的輸出對應起來了。entrypoint.sh比較複雜,主要功能就是啓動mysqld,並將日誌輸出,由於不是本文重點,就不詳細介紹了。

總結

  1. docker容器默認輸出到本地json文件,而且能夠對其進行大小和數量控制。
  2. 應用容器日誌能夠先生成日誌文件,而後將應用日誌文件軟鏈接到標準輸出,好比nginx;也能夠在啓動時候直接將日誌打印到標準輸出,好比mysql。

參考連接

Docker 日誌都在哪裏?怎麼收集?

JSON File logging driver

docker mysql

相關文章
相關標籤/搜索