OCI image, layers và container lifecycle
Image là tập nội dung và metadata bất biến theo content-addressing; container dùng image làm nền rồi thêm runtime configuration, process và writable layer riêng. Hiểu lifecycle giúp phân biệt rõ “image nào được chạy”, “container đang ở state nào”, dữ liệu nào sẽ mất và cần nhìn đâu khi sự cố xảy ra.
1. Image model
Một OCI image có thể gồm image index (tuỳ chọn), image manifest, image configuration và các filesystem layer. Image index có thể tham chiếu nhiều manifest khác nhau; registry/runtime chọn manifest phù hợp platform như OS và architecture. Manifest tham chiếu config cùng danh sách layer theo descriptor/digest; config chứa metadata phục vụ runtime như command/arguments, environment và lịch sử tạo layer.
Các layer là filesystem changeset được đóng gói và định danh bằng digest. Digest là content address: nội dung thay đổi thì digest thay đổi. Ngược lại, tag là tên mutable có thể được cập nhật để trỏ sang manifest khác, vì vậy production cần phân biệt rõ “deploy theo tag” với “pin theo digest”.
linux/amd64, linux/arm64, v.v.2. Container states
docker create tạo container object từ image/config và chuẩn bị root filesystem nhưng chưa chạy application process. docker start khởi động main process. docker run về mặt mental model là create + start. Khi container đang chạy, PID 1 của container là process quyết định lifetime chính của container.
| Action | Điều gì xảy ra | Điểm cần nhớ |
|---|---|---|
pause | Trên Linux, Docker dùng freezer cgroup để suspend các process trong container. | Pause không phải graceful shutdown; application không có cơ hội “kết thúc công việc”. |
stop | Main process nhận stop signal (mặc định thường là SIGTERM), rồi SIGKILL sau grace period nếu vẫn chưa thoát. | Stop signal và timeout có thể cấu hình; shutdown handler cần hoàn tất trong failure window này. |
restart | Dừng rồi khởi động process mới trên cùng container object và writable layer hiện có. | Restart không biến container thành “container mới sạch”; file đã ghi trong writable layer vẫn còn. |
remove | Xóa container object và writable layer của container. | Dữ liệu chỉ nằm ở writable layer sẽ mất; volume/bind mount có lifecycle riêng. |
3. Copy-on-write và writable layer
Các image layer là read-only và có thể được chia sẻ giữa nhiều container dùng cùng image. Mỗi container có writable layer riêng ở trên cùng. Với copy-on-write, file ở lower layer được dùng trực tiếp khi chỉ đọc; lần đầu cần sửa, storage implementation copy file lên writable layer rồi mới thay đổi.
Writable layer phù hợp với ephemeral writes, nhưng không phải nơi tốt cho large mutable data, database files hoặc log cần retention lâu dài: dữ liệu mất khi container bị remove, khó backup/di chuyển hơn, và một số workload ghi nhiều chịu overhead của storage driver/snapshotter. Process, memory và network namespace của từng container vẫn tách riêng dù image layers được chia sẻ.
| Loại dữ liệu | Nên đặt ở đâu | Lý do |
|---|---|---|
| Scratch/cache tạm, file có thể tái tạo | Writable layer hoặc tmpfs khi phù hợp | Không cần sống lâu hơn container. |
| Database / dữ liệu business cần persist | Volume hoặc storage bên ngoài container | Tách lifecycle dữ liệu khỏi lifecycle container, giảm rủi ro mất state. |
| Log cần lưu giữ/phân tích | Logging pipeline hoặc mount/storage được quản lý | Không phụ thuộc việc container còn tồn tại để điều tra sự cố. |
Về capacity/operations, cần theo dõi disk usage của image store, container writable layers, volume và logging. Disk pressure có thể khiến pull/build/start/write thất bại dù CPU/memory còn dư; dọn dẹp image/container phải theo policy để tránh xóa nhầm artifact còn cần cho rollback.
4. Inspect and debug
Khi container lỗi, bắt đầu từ state chứ không chỉ nhìn dòng log cuối. Dùng docker inspect để xem low-level state/config, exit code và metadata; docker logs để xem output của container; docker events để correlate create/start/die/oom/stop; dùng image history/digest để xác nhận chính xác artifact nào đang chạy.
# State, exit code và OOM flag
docker inspect --format '{{json .State}}' <container>
# Log của container
docker logs --tail 200 <container>
# Event gần thời điểm lỗi
docker events --since 30m --filter container=<container>
# Xác nhận image/digest
docker inspect --format '{{.Image}}' <container>
docker image inspect <image>
“Container exited” thường chỉ có nghĩa main process/PID 1 đã kết thúc; điều đó không tự động chứng minh Docker daemon bị lỗi. Exit code 137 thường liên quan process bị SIGKILL (128 + signal 9) và có thể do OOM killer, nhưng không nên kết luận chỉ từ con số: cần kiểm tra .State.OOMKilled, Docker events và bằng chứng phía host/kernel.
5. Production guardrails: security, recovery và rollback
- Image provenance: ưu tiên image từ registry tin cậy, pin digest cho release cần reproducibility và lưu mapping release → digest để rollback.
- Runtime least privilege: tránh chạy root nếu không cần, giới hạn capability/permission, mount secret theo cơ chế phù hợp và cân nhắc read-only root filesystem khi application cho phép.
- Persistent state: backup/restore phải nhắm vào volume/database/object store, không dựa vào container writable layer.
- Recovery: restart policy giúp process quay lại nhưng không thay thế health check, dependency recovery, idempotency hay data reconciliation.
- Rollback: rollback application nên tạo container từ image digest trước đó; không “sửa tay” container đang chạy rồi kỳ vọng trạng thái đó tái tạo được.
6. Checklist ôn nhanh
- Phân biệt tag mutable với digest content-addressed.
- Biết
docker runlà create + start trong mental model. - Biết restart dùng lại container object/writable layer, còn remove xóa writable layer.
- Không đặt persistent/write-heavy data vào writable layer nếu có lựa chọn storage phù hợp hơn.
- Khi exited: kiểm tra PID 1/state/exit code/events/logs trước khi kết luận daemon lỗi.
- Exit 137 chỉ là tín hiệu điều tra; xác nhận OOM bằng state/event/host evidence.