จำกัดขนาด Log ของ Docker Container
ทุกข้อความที่โปรแกรมใน Container พิมพ์ออกทาง stdout และ stderr จะถูก Docker เก็บไว้ ค่าเริ่มต้นของ Docker Engine บน Linux คือ Log Driver แบบ json-file ซึ่ง ไม่จำกัดขนาด ไฟล์จึงโตขึ้นเรื่อย ๆ Container ที่พิมพ์ Log เยอะ เช่น Web Server ที่มีผู้เข้าชมมาก หรือแอปที่เปิดโหมด Debug ทิ้งไว้ สร้างไฟล์ Log หลายสิบ GB ได้ภายในไม่กี่สัปดาห์ จนดิสก์เต็ม
บทความนี้แสดงวิธีหาว่า Container ใดมี Log ใหญ่ ล้างไฟล์ที่ใหญ่อยู่แล้วอย่างปลอดภัย และตั้งการหมุนเวียน Log (Log Rotation) ทั้งแบบค่าเริ่มต้นของทั้งเครื่องและแบบรายโปรเจกต์ใน Docker Compose
สิ่งที่ต้องเตรียม
- Linux Server ที่ใช้ Docker Engine (ตัวอย่างนี้ทดสอบแนวทางกับ Ubuntu 22.04/24.04 และ AlmaLinux/Rocky Linux 8-9)
- สิทธิ์
sudo - ช่วงเวลาที่รีสตาร์ต Docker และสร้าง Container ใหม่ได้ เพราะการเปลี่ยนค่า Log มีผลกับ Container ที่สร้างใหม่เท่านั้น
ขั้นตอนที่ 1: หา Container ที่มีไฟล์ Log ใหญ่
ไฟล์ Log ของ Driver json-file อยู่ที่ /var/lib/docker/containers/<ID>/<ID>-json.log ดูขนาดทั้งหมดเรียงจากเล็กไปใหญ่
sudo sh -c 'du -h /var/lib/docker/containers/*/*-json.log' | sort -h | tail
120M /var/lib/docker/containers/3f2a.../3f2a...-json.log
8.4G /var/lib/docker/containers/9c1d.../9c1d...-json.log
ชื่อโฟลเดอร์เป็น ID ของ Container ดูว่าเป็นตัวไหนด้วยคำสั่งนี้ ซึ่งแสดงชื่อ Container คู่กับ path ของไฟล์ Log
docker ps -aq | xargs docker inspect --format '{{.Name}} {{.LogPath}}'
ตรวจว่า Container แต่ละตัวใช้ Log Driver และตัวเลือกใดอยู่
docker inspect --format '{{.HostConfig.LogConfig}}' web
ถ้าได้ {json-file map[]} แปลว่าไม่มีการจำกัดขนาด
ขั้นตอนที่ 2: ล้างไฟล์ Log ที่ใหญ่อยู่แล้ว
ถ้าดิสก์ใกล้เต็ม ให้ล้างไฟล์ก่อนเพื่อคืนพื้นที่ทันที ใช้ truncate เพื่อทำให้ไฟล์ว่างเปล่าโดยไม่ลบไฟล์ทิ้ง
sudo truncate -s 0 "$(docker inspect --format '{{.LogPath}}' web)"
หมายเหตุ: Log ที่ถูกล้างจะหายถาวร ถ้าต้องใช้เป็นหลักฐานหรือหาสาเหตุปัญหา ให้คัดลอกเก็บก่อน เช่น
docker logs --since 24h web > web-last24h.log 2>&1และห้ามใช้rmลบไฟล์-json.logขณะ Container ทำงาน เพราะ Docker ยังเปิดไฟล์ค้างไว้ พื้นที่จะไม่ถูกคืนจนกว่าจะรีสตาร์ต และคำสั่งdocker logsอาจใช้งานไม่ได้
การล้างเป็นแค่การแก้เฉพาะหน้า ไฟล์จะโตกลับมาอีก ขั้นตอนถัดไปคือการแก้ที่ต้นเหตุ
ขั้นตอนที่ 3: ตั้งค่าเริ่มต้นให้ทั้งเครื่องใน daemon.json
แก้หรือสร้างไฟล์ /etc/docker/daemon.json (ถ้ามีไฟล์อยู่แล้ว ให้เพิ่มคีย์เข้าไปใน Object เดิม อย่าเขียนทับค่าอื่นที่ตั้งไว้)
sudo nano /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
max-sizeขนาดสูงสุดของไฟล์ Log แต่ละไฟล์ ก่อนเริ่มไฟล์ใหม่ (หน่วยk,m,g)max-fileจำนวนไฟล์สูงสุดที่เก็บไว้ ไฟล์เก่าที่สุดจะถูกลบเมื่อครบ ตัวอย่างนี้จึงใช้พื้นที่ไม่เกินประมาณ 30 MB ต่อ Container- ค่าใน
log-optsต้องเป็นข้อความในเครื่องหมายคำพูด ทั้งหมด แม้จะเป็นตัวเลข เช่น"3"ถ้าเขียน3เฉย ๆ Docker จะเริ่มทำงานไม่ได้
ทางเลือก: Log Driver แบบ local
Driver local หมุนเวียนไฟล์และบีบอัดให้อัตโนมัติ โดยค่าเริ่มต้นเก็บไม่เกิน 5 ไฟล์ ไฟล์ละ 20 MB ใช้พื้นที่น้อยกว่า json-file แต่ไฟล์เป็นรูปแบบภายในของ Docker อ่านผ่าน docker logs ได้ตามปกติ แต่เครื่องมือเก็บ Log ภายนอกที่อ่านไฟล์ JSON โดยตรงจะอ่านไม่ได้
{
"log-driver": "local"
}
| Driver | จำกัดขนาดเอง | บีบอัด | เหมาะกับ |
|---|---|---|---|
json-file (ค่าเริ่มต้น) | ไม่ ต้องตั้ง max-size | ได้ ถ้าตั้ง "compress": "true" | ต้องการให้เครื่องมืออื่นอ่านไฟล์ JSON ได้ |
local | ใช่ (5 x 20 MB) | ใช่ | เซิร์ฟเวอร์ทั่วไปที่ดู Log ด้วย docker logs |
journald | ตามการตั้งค่าของ journald | ใช่ | ต้องการรวม Log กับ journalctl |
ถ้าเลือก journald ขนาดรวมถูกควบคุมโดยค่า SystemMaxUse ของ journald ดูรายละเอียดที่ อ่าน Log ระบบบน Linux ด้วย journalctl
ขั้นตอนที่ 4: ตรวจไฟล์และรีสตาร์ต Docker
ตรวจความถูกต้องของไฟล์ก่อนรีสตาร์ต (Docker Engine 23.0 ขึ้นไป)
sudo dockerd --validate --config-file=/etc/docker/daemon.json
ผลที่ถูกต้องคือ configuration OK จากนั้นรีสตาร์ตบริการ
sudo systemctl restart docker
หมายเหตุ: การรีสตาร์ต Docker ทำให้ Container ทั้งหมดบนเครื่องหยุดและเริ่มใหม่ (ยกเว้นเปิด
live-restoreไว้) เว็บไซต์จะหยุดให้บริการชั่วครู่ ควรทำในช่วงที่มีผู้ใช้น้อย ถ้า Docker เริ่มไม่ขึ้นหลังรีสตาร์ต ให้ดูสาเหตุด้วยsudo journalctl -u docker -n 50ซึ่งส่วนใหญ่เป็น JSON ผิดรูปแบบ
ขั้นตอนที่ 5: สร้าง Container ใหม่ให้ใช้ค่าใหม่
ค่าใน daemon.json ใช้กับ Container ที่ สร้างใหม่ เท่านั้น Container เดิมยังใช้ค่าตอนที่ถูกสร้าง แม้จะรีสตาร์ตแล้วก็ตาม ต้องสร้างใหม่
สำหรับโปรเจกต์ Docker Compose
cd /opt/myapp
sudo docker compose up -d --force-recreate
สำหรับ Container ที่สร้างด้วย docker run ต้องสั่ง docker rm -f แล้วรันคำสั่งเดิมอีกครั้ง ข้อมูลใน Volume ยังอยู่ แต่ไฟล์ที่เขียนไว้ใน Container นอก Volume จะหาย ตรวจด้วย docker inspect ก่อนว่าข้อมูลสำคัญอยู่ใน Volume แล้ว
ทางเลือก: กำหนดรายโปรเจกต์ใน compose.yaml
ถ้าไม่ต้องการเปลี่ยนค่าทั้งเครื่อง หรือต้องการให้บาง Service เก็บ Log มากกว่าตัวอื่น กำหนดใน Compose ได้ ค่าที่นี่จะแทนค่าจาก daemon.json
x-logging: &default-logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
services:
web:
image: nginx:1.27
logging: *default-logging
app:
image: myapp:1.0
logging:
driver: json-file
options:
max-size: "50m"
max-file: "5"
ส่วน x-logging กับ &default-logging เป็น YAML Anchor ช่วยให้ไม่ต้องพิมพ์ค่าซ้ำทุก Service จากนั้นสั่ง sudo docker compose up -d Compose จะสร้าง Container ที่ค่าเปลี่ยนใหม่ให้เอง สำหรับ docker run ใช้ตัวเลือก --log-opt max-size=10m --log-opt max-file=3
ตรวจสอบผลลัพธ์
docker inspect --format '{{.HostConfig.LogConfig}}' web
ต้องได้ {json-file map[max-file:3 max-size:10m]} (หรือ {local map[]} ถ้าใช้ Driver local) หลังจากใช้งานไปสักพัก ตรวจว่ามีไฟล์หมุนเวียนเกิดขึ้น
sudo sh -c 'ls -lh /var/lib/docker/containers/*/*-json.log*'
จะเห็นไฟล์ -json.log, -json.log.1 และ -json.log.2 ขนาดไม่เกิน 10 MB ต่อไฟล์
ปัญหาที่พบบ่อย
Docker ไม่ยอมเริ่มหลังแก้ daemon.json
JSON ผิดรูปแบบ เช่น ลืมเครื่องหมายจุลภาค มีจุลภาคเกินท้ายรายการ หรือเขียนตัวเลขไม่มีเครื่องหมายคำพูด ใช้ dockerd --validate หรือ python3 -m json.tool /etc/docker/daemon.json หาบรรทัดที่ผิด
ตั้งค่าแล้วแต่ไฟล์ Log ยังโตเกินกำหนด
Container ยังไม่ได้ถูกสร้างใหม่ ตรวจด้วย docker inspect ตามหัวข้อตรวจสอบผลลัพธ์ แล้วสร้างใหม่ตามขั้นตอนที่ 5
docker logs แสดง Log ย้อนหลังได้ไม่มาก
เป็นผลปกติของการจำกัดขนาด ถ้าต้องการเก็บ Log นานขึ้นเพื่อการตรวจสอบ ให้เพิ่ม max-file หรือส่ง Log ไปยังระบบรวม Log ภายนอก แทนการปล่อยไฟล์โตไม่จำกัด
Log ของแอปที่เขียนลงไฟล์ภายใน Container ยังโต
การตั้งค่านี้ควบคุมเฉพาะ stdout และ stderr ถ้าแอปเขียน Log ลงไฟล์ใน Volume หรือ Bind Mount เอง ต้องใช้ logrotate บนเครื่อง ดู ตั้งค่า logrotate ไม่ให้ไฟล์ Log เต็มดิสก์
หากดิสก์ยังเต็มจากสาเหตุอื่น ดูต่อที่ คืนพื้นที่ดิสก์ที่ Docker ใช้ด้วย docker system prune หรือติดต่อทีมงาน THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/
- Categories:
- Cloud
- Tags:
- Cloud
- Cloud Server
Related Posts
หมวดหมู่ที่น่าสนใจ
- Account Settings
- AD Server
- AI
- Alibaba Cloud
- Anti-Spam Gateway
- AWS Amazon Web Services
- Campaign
- CentOS/AlmaLinux
- Cloud
- Cloud Backup
- Cloud Communication
- Cloud Migration
- Cloud Security
- Cloud Server Management
- Cloud Solution
- Cloud Solution for Government
- Cloud Solutions by Industry
- Cloud Storage
- Cloud VPS App Plus +
- Cloud VPS DirectAdmin
- Cloud VPS Plesk
- CSR
- Cyber Security
- Cybersecurity
- Data Sovereignty
- Database Server
- DDoS
- Digital Tranformation
- Digital Transformation
- Direct Mail
- Directadmin
- Domainname
- Ecommerce
- ERP
- Generative AI
- Getting Started
- Google Cloud
- Google G Suite
- Huawei Cloud
- IT News
- Linux Server
- Managed Cloud Services
- Managed Service Provider
- Manual
- Microsoft
- Microsoft 365
- Microsoft Azure
- News
- On-premise
- Private Mail Server
- Promotion
- Recommend Solution (Enterprise)
- Server
- Sovereign Cloud
- THAI DATA CLOUD Platform
- Ubuntu
- Ubuntu
- Uncategorized
- VMware
- VPS Server
- Web Design
- Web Hosting
- Web Hosting (DirectAdmin)
- Web Hosting (Plesk)
- Web Technologies
- Windows Server
- Wordpress
- Zimbra
- เรื่องราวความประทับใจ
- โซลูชันสำหรับธุรกิจการผลิตและยานยนต์
- โซลูชันสำหรับธุรกิจการศึกษา
- โซลูชันสำหรับธุรกิจการเงิน
- โซลูชันสำหรับธุรกิจขนส่งและกระจายสินค้า
- โซลูชันสำหรับธุรกิจค้าปลีก
- โซลูชันสำหรับธุรกิจท่องเที่ยว
- โซลูชันสำหรับธุรกิจบริการสุขภาพและโรงพยาบาล
- โซลูชันสำหรับธุรกิจประกันภัย
- โซลูชันสำหรับธุรกิจพลังงานและสาธารณูปโภค
- โซลูชันสำหรับธุรกิจสื่อสารมวลชนและเอ็นเตอร์เทนเมนท์
- โซลูชันสำหรับธุรกิจอสังหาริมทรัพย์
- โซลูชันสำหรับธุรกิจเทคโนโลยี


