Phân biệt Docker Image và Container: Cấu trúc Layer hoạt động thế nào?
Giải thích Docker Image vs Container, cấu trúc layer, OverlayFS và Copy-on-Write, build cache, writable layer, volume, digest cùng các lỗi bảo mật và tối ưu thường gặp.
ShanverseUpdated 13 min read— viewsLoading views
Docker
Deployment
Nếu xem Image như một class thì Container gần giống object được tạo từ class đó. Tuy nhiên, phép so sánh chính xác hơn trong Docker là:
Hiểu mô hình này giúp bạn trả lời các câu hỏi quan trọng:
Tại sao một Image có thể tạo nhiều Container?
Vì sao sửa file trong Container không làm thay đổi Image?
Tại sao xóa secret ở layer sau vẫn chưa an toàn?
Docker build cache hoạt động thế nào?
Khi nào cần Volume thay vì writable layer?
Docker Image là gì?
Docker Image là artifact bất biến dùng để tạo Container. Nó thường chứa:
Application code.
Runtime như Node.js, Python hoặc Java.
Comments
System libraries.
Default configuration.
Entrypoint và command.
Environment metadata.
Một chuỗi filesystem layers.
Ví dụ:
Image không phải process đang chạy. Pull Image về máy không có nghĩa application đã được start.
Tag và Digest
Tag là tên có thể thay đổi:
Digest là định danh nội dung:
Một tag có thể được trỏ sang Image mới; digest biểu diễn nội dung cụ thể. Production cần khả năng tái hiện thường pin version hoặc digest theo policy.
Docker Container là gì?
Container là runtime instance được tạo từ Image.
Container có:
Process đang chạy.
Writable layer riêng.
Network namespace và IP/port mapping.
Environment variables tại runtime.
Resource limits.
Mounts và Volumes.
Trạng thái lifecycle: created, running, paused, stopped hoặc removed.
Dừng Container không xóa Image:
Image vẫn có thể tạo Container mới.
Image vs Container: bảng so sánh
Docker Layer là gì?
Layer là một tập thay đổi filesystem so với layer trước. Khi build Image, các instruction như RUN, COPY và ADD thường tạo filesystem diff mới.
Có thể hình dung:
Không phải mọi Dockerfile instruction đều tạo một filesystem layer chứa file mới. Một số instruction chủ yếu thay đổi Image configuration hoặc history. Kết quả cụ thể còn phụ thuộc builder và BuildKit.
Image được ghép từ Layers như thế nào?
Mermaid
Loading diagram…
Từ bên trong Container, bạn thấy một filesystem thống nhất:
Nhưng storage driver ghép nội dung từ nhiều layer phía dưới. Trên Linux, OverlayFS là lựa chọn phổ biến; các platform/runtime khác có thể dùng cơ chế tương đương.
Content-addressable storage
Image layers được nhận diện bằng digest dựa trên nội dung. Nếu hai Image dùng cùng một layer, Docker có thể lưu và truyền layer đó một lần.
Ví dụ:
Lợi ích:
Giảm dung lượng disk thực tế.
Pull nhanh hơn khi layer đã tồn tại.
Build cache có thể tái sử dụng.
Nhiều Container dùng chung layer chỉ đọc.
Vì có shared layers, tổng số trong docker image ls không luôn phản ánh chính xác disk tăng thêm cho từng Image.
Kiểm tra chi tiết:
Container writable layer
Khi Docker tạo Container, runtime đặt một writable layer mỏng lên trên các Image layers:
Mermaid
Loading diagram…
Mọi file được tạo/sửa/xóa trong filesystem Container thường được ghi nhận ở writable layer này.
Ví dụ:
Bên trong:
File chỉ thuộc writable layer của Container demo. Container khác từ cùng Image không thấy file đó.
Copy-on-Write hoạt động thế nào?
Các Image layers chỉ đọc. Khi Container sửa một file nằm trong layer phía dưới:
Runtime tìm file ở read-only layer.
File được copy lên writable layer của Container.
Thay đổi áp dụng lên bản copy.
Container nhìn thấy phiên bản mới ở layer trên cùng.
Đây là Copy-on-Write (CoW).
Image gốc và Container khác vẫn dùng version A.
Tác động hiệu năng
CoW rất hiệu quả cho workload đọc nhiều và ghi ít. Nhưng ghi nhiều file lớn vào writable layer có thể kém phù hợp hơn Volume/storage chuyên dụng.
Database production không nên dựa vào writable layer như nơi lưu dữ liệu bền vững.
Xóa file trong layer nghĩa là gì?
Filesystem union dùng cơ chế marker/whiteout để che file nằm ở layer thấp hơn. Nếu layer mới “xóa” file cũ, file không còn hiện trong final view, nhưng bytes ở layer cũ có thể vẫn tồn tại.
Secret biến mất khỏi filesystem cuối, nhưng có thể còn trong layer được tạo bởi COPY.
Dùng:
.dockerignore.
BuildKit secret mounts.
Multi-stage build.
Secret manager tại runtime.
Ví dụ secret mount ở build:
Build:
Kiểm tra quy trình thực tế để đảm bảo tool không copy secret vào artifact hoặc log.
Build Cache hoạt động theo Layer
Docker/BuildKit có thể tái sử dụng kết quả instruction nếu input liên quan không đổi.
Dockerfile tối ưu cho Node.js:
Khi chỉ sửa source code:
COPY package*.json vẫn cache hit.
RUN npm ci được tái sử dụng.
COPY . . và bước sau được chạy lại.
Nếu viết:
Mọi thay đổi source có thể làm cache của dependency installation mất hiệu lực.
Cache invalidation lan truyền
Khi một layer phải build lại, các instruction phía sau thường cũng cần được đánh giá/build lại.
Do đó:
Đặt OS package installation ổn định lên trước.
Copy lockfile trước source.
Dùng .dockerignore để giảm build context.
Không đặt timestamp ngẫu nhiên vào layer sớm.
Pin dependency/base image theo policy.
.dockerignore ảnh hưởng Layer và Cache
Lợi ích:
Build context nhỏ hơn.
Không làm cache invalid vì file không cần thiết.
Tránh gửi secret vào builder.
Không copy node_modules từ host vào Image.
Kiểm tra file thật sự cần cho build trước khi ignore quá rộng.
Multi-stage Build và Layers
Multi-stage build cho phép build artifact trong stage lớn, rồi chỉ copy output cần thiết sang runtime Image.
Final Image không chứa toàn bộ build tools và source của stage trước, trừ khi bạn copy chúng sang.
Lợi ích:
Image nhỏ hơn.
Attack surface giảm.
Build dependency tách khỏi runtime.
Layer runtime dễ audit hơn.
Nhiều Container dùng chung một Image
Cả ba dùng chung read-only Image layers, nhưng mỗi Container có:
Writable layer riêng.
Process state riêng.
Network state riêng.
Log và runtime metadata riêng.
Đây là lý do scale nhiều Container không cần copy toàn bộ Image ba lần.
Volume khác writable layer thế nào?
Volume được mount vào Container và quản lý độc lập với lifecycle của Container.
Volume không thay thế backup. Database vẫn cần backup, restore test và replication phù hợp.
Xem Layers của Image
docker history
Hiển thị instruction/history và kích thước liên quan. Một số dòng có thể là metadata hoặc hiển thị size 0B.
docker image inspect
Xem:
RepoTags/RepoDigests.
RootFS layers.
Config.
Architecture/OS.
Entrypoint/Cmd.
Xem disk usage
Công cụ phân tích
Các công cụ như dive có thể giúp xem file thay đổi theo layer và lượng dữ liệu lãng phí. Chỉ cài từ nguồn tin cậy.
Image Manifest và Multi-platform Image
Một tên Image có thể trỏ tới image index/manifest list chứa biến thể theo platform:
Khi pull, runtime chọn biến thể phù hợp với platform.
Kiểm tra:
Layers của amd64 và arm64 không nhất thiết giống nhau dù dùng cùng tag.
Container thay đổi Image được không?
Không trực tiếp. Container chỉ viết vào writable layer riêng.
Lệnh sau tạo Image mới từ trạng thái Container:
Nhưng docker commit không phải workflow build khuyến nghị vì:
Không có Dockerfile rõ ràng.
Khó review và tái hiện.
Có thể vô tình giữ secret/temp file.
Pipeline không biết cách tái build.
Ưu tiên sửa Dockerfile/source rồi build Image mới.
Lifecycle đúng của Image và Container
Mermaid
Loading diagram…
Không nên SSH/exec vào Container production để sửa lâu dài. Thay đổi đó biến mất khi redeploy và tạo configuration drift.
Tag mới không tạo Layer mới
Command này chỉ tạo tham chiếu/tag mới tới cùng Image; không duplicate filesystem layers.
Xác minh:
Hai tag có thể trỏ cùng Image ID.
Xóa Image và shared layers
Docker chỉ giải phóng layer khi không còn Image/Container nào tham chiếu. Nếu Container đang dùng Image hoặc tag khác cùng trỏ tới content, dữ liệu có thể vẫn tồn tại.
Dọn tài nguyên không dùng:
Luôn preview/đọc danh sách và hiểu volume không được xóa mặc định trong mọi trường hợp. Không dùng prune phá hủy trên máy production tùy tiện.
Tối ưu Dockerfile theo Layer
Dùng base Image phù hợp
Image nhỏ giúp pull nhanh hơn, nhưng Image cực tối giản có thể thiếu shell, CA certificates hoặc debugging tools. Chọn theo security và operational needs.
Gộp package install và cleanup cùng layer
Với package manager tạo cache, cleanup trong cùng RUN để bytes không nằm ở layer trước.
Tránh copy toàn repository quá sớm
Pin dependency và base
Lockfile và digest/version rõ giúp build tái hiện, nhưng vẫn cần quy trình cập nhật security patches.
Chạy non-root
Layer nhỏ không đồng nghĩa Image an toàn. Quyền runtime mới là yếu tố quan trọng.
Những hiểu lầm phổ biến
“Mỗi Dockerfile instruction luôn tạo một layer file”
Một số instruction thay đổi metadata/config; builder hiện đại có cách ghi history và layer khác nhau. Hãy kiểm tra Image thật bằng history và inspect.
“Xóa file ở layer sau làm Image nhỏ lại”
Bytes ở layer trước vẫn có thể tồn tại. Tránh đưa file vào Image hoặc tạo/xóa trong cùng layer phù hợp.
“Mỗi Container copy toàn bộ Image”
Nhiều Container chia sẻ read-only layers; chỉ writable layer là riêng.
“Writable layer là database storage”
Nó gắn với lifecycle Container và không phải chiến lược durability.
“Tag là bản Image bất biến”
Tag có thể di chuyển. Digest là định danh content cụ thể hơn.
“Layer là security boundary”
Layer là cơ chế storage/distribution, không phải sandbox bảo mật giữa file.
Demo nhanh: hai Container, một Image
File /message chỉ tồn tại trong writable layer của c1.
Checklist build Image tốt
Có .dockerignore.
Không có secret trong build context/layers.
Dependency manifest được copy trước source để tận dụng cache.
Dùng multi-stage build khi có build tools.
Runtime Image chỉ chứa artifact cần thiết.
Base Image được pin và cập nhật định kỳ.
Process chạy non-root.
Dữ liệu persistent nằm ngoài writable layer.
Image được scan vulnerability.
docker history và disk usage đã được kiểm tra.
Tag/version/digest strategy rõ ràng.
Image có thể build lại từ source, không dựa vào docker commit.
Tổng kết
Image là artifact bất biến gồm config và các read-only layers.
Container là runtime instance của Image, có process state và writable layer riêng.
Copy-on-Write copy file lên layer trên khi Container cần sửa.
Nhiều Container dùng chung Image layers để tiết kiệm disk và tăng tốc startup.
Volume dành cho dữ liệu cần sống lâu hơn Container.
Layer ordering quyết định hiệu quả build cache và kích thước Image.
Xóa secret/file ở layer sau không loại bỏ bytes khỏi layer cũ.
Table of contents(43)
Codeplain text
1Image = filesystem layers chỉ đọc + metadata2Container = Image + writable layer + process/network/runtime state
1# Pull một Image2dockerpullalpine:3.2034# Tạo Container thứ nhất và ghi file5dockerrun--namec1alpine:3.20sh-c'echo c1 > /message && cat /message'67# Tạo Container thứ hai và kiểm tra8dockerrun--namec2alpine:3.20sh-c'test ! -f /message && echo isolated'910# Xem writable size11dockerps-a--size1213# Dọn demo14dockerrmc1c2
Related posts
More articles with related topics and technologies.
Hướng dẫn tự động deploy ứng dụng Docker lên VPS Ubuntu và cloud providers bằng GitHub Actions: AWS ECS/App Runner/EC2, Vercel, Render, secrets, healthcheck, rollback và zero-downtime strategy.
Hướng dẫn Docker Networks toàn diện: bridge, host, none, overlay, service discovery, port publishing, Compose network segmentation, internal networks, bảo mật và debug kết nối.