Docker từ A-Z (Phần 2): Khám phá các mảnh ghép cốt lõi

Chào anh em! Ở phần 1, chúng ta đã cùng nhau giải ngố Docker là gì và tại sao nó lại là chân ái cho anh em lập trình viên rồi đúng không? Chúng ta đã thấy Docker giúp giải quyết những nỗi đau rất thật về môi trường code không nhất quán, setup phức tạp hay xung đột thư viện như thế nào.
Bây giờ, khi đã hiểu được “Why”, hãy cùng đi vào tìm hiểu “What” và “How” nhé. Trong phần 2 này, chúng ta sẽ cùng mổ xẻ những thành phần cốt lõi, những mảnh ghép tạo nên Docker. Hiểu rõ những khái niệm này giống như việc bạn cần biết về gạch, vữa, sắt thép trước khi xây nhà, hay biết về bột, trứng, đường trước khi làm bánh vậy. Nắm vững chúng rồi thì việc thực hành ở các phần sau sẽ dễ dàng hơn rất nhiều!
(Bạn nào lỡ bỏ qua hoặc muốn xem lại bức tranh toàn cảnh về lý do Docker ra đời thì có thể đọc lại Phần 1 tại đây nhé.)
Image – Khuôn Mẫu Bất Biến
Image là gì?
Hãy tưởng tượng Image như một cái khuôn đúc bánh, một bản thiết kế chi tiết đã hoàn chỉnh, hoặc gần gũi hơn là một file ISO để cài đặt Windows/Linux. Nó là một template chỉ đọc (read-only), chứa tất cả những gì cần thiết để chạy ứng dụng của bạn.
Bên trong Image có gì?
Một Image thường bao gồm:
- Một lớp hệ điều hành cơ bản rất nhẹ (ví dụ: Alpine Linux, Ubuntu tối giản).
- Runtime cần thiết (ví dụ: Node.js, Python, JRE).
- Code ứng dụng của bạn.
- Tất cả các thư viện, dependencies mà code của bạn cần.
- Các file cấu hình, biến môi trường…
Layers
Image được xây dựng theo từng lớp (layer). Mỗi chỉ dẫn trong Dockerfile (chúng ta sẽ tìm hiểu ngay sau đây) thường tạo ra một lớp mới. Các lớp này xếp chồng lên nhau. Điều này giống như các layer trong Photoshop hay các commit trong Git vậy đó. Lợi ích là gì? Tái sử dụng và tiết kiệm dung lượng! Nếu nhiều image dùng chung các lớp cơ bản (như lớp OS, lớp runtime), Docker chỉ cần lưu trữ lớp đó một lần thôi. Khi bạn build lại image, Docker cũng chỉ cần build lại những lớp nào có thay đổi thôi, rất hiệu quả!
Image từ đâu mà có?
Bạn có thể tự build một image từ Dockerfile, hoặc kéo (pull) các image có sẵn từ một nơi gọi là Registry (như Docker Hub).

Container – Thực Thể Sống Động
Container là gì?
Nếu Image là cái khuôn bánh, thì Container chính là cái bánh được đúc ra từ khuôn đó. Nếu Image là file ISO cài Win, thì Container là một máy tính Windows cụ thể đã được cài đặt và đang chạy từ file ISO đó. Tóm lại, Container là một thực thể chạy (running instance) được tạo ra từ một Image.
Đặc điểm chính:
- Cô lập (Isolated): Đây là sức mạnh cốt lõi! Mỗi container chạy trong một môi trường riêng, có hệ thống file, network, process riêng, gần như tách biệt hoàn toàn với máy chủ và các container khác.
- Tạm thời (Ephemeral – Mặc định): Khi một container bị xóa đi, mọi thay đổi bạn thực hiện bên trong nó (ví dụ ghi file mới) cũng sẽ mất theo, trừ khi bạn sử dụng một cơ chế lưu trữ đặc biệt gọi là Volume (sẽ tìm hiểu ở phần sau). Điều này đảm bảo container luôn khởi động từ trạng thái sạch sẽ của Image.
- Có thể quản lý: Bạn có thể dễ dàng
start
,stop
,restart
,delete
container. - Có lớp ghi (Writable Layer): Mặc dù dựa trên Image (read-only), mỗi container có một lớp mỏng ở trên cùng cho phép bạn ghi/thay đổi dữ liệu trong quá trình nó chạy.
Mối quan hệ với Image:
Từ một Image duy nhất, bạn có thể tạo ra và chạy nhiều Container giống hệt nhau. Ví dụ, bạn có thể chạy 5 container web server từ cùng một image để cân bằng tải.
Dockerfile – Bản Thiết Kế Image Tự Động
Dockerfile là gì?
Đây là một file văn bản đơn giản (plain text), không có đuôi mở rộng đặc biệt (thường chỉ đặt tên là Dockerfile
). Bên trong nó chứa một loạt các chỉ dẫn (instructions) theo thứ tự, giống như một công thức nấu ăn chi tiết từng bước hay một bản thiết kế nhà. Docker Engine sẽ đọc file này để tự động build ra một Docker Image.
Tại sao cần Dockerfile?
Tự động hóa: Thay vì tạo image thủ công (rất phức tạp và dễ lỗi), bạn viết các bước vào Dockerfile, Docker sẽ làm thay bạn.
Tái sử dụng & Nhất quán: Ai có Dockerfile này cũng có thể build ra image y hệt nhau.
Dễ quản lý phiên bản: Bạn có thể đưa Dockerfile vào Git để quản lý phiên bản cùng với code của mình.
Ví dụ:
FROM ubuntu:latest
: Bắt đầu từ image nền nào (ở đây là Ubuntu mới nhất).WORKDIR /app
: Đặt thư mục làm việc mặc định bên trong container là/app
.COPY . /app
: Sao chép toàn bộ nội dung từ thư mục hiện tại (chứa Dockerfile) vào thư mục/app
trong image.RUN apt-get update && apt-get install -y nodejs
: Chạy một lệnh nào đó trong quá trình build image (ví dụ: cài đặt Node.js).EXPOSE 8080
: Khai báo rằng container sẽ lắng nghe ở port 8080 (chỉ mang tính thông báo, chưa thực sự mở port ra ngoài).CMD ["node", "app.js"]
: Chỉ định lệnh mặc định sẽ chạy khi container khởi động.
(Đừng lo lắng nếu chưa hiểu hết, chúng ta sẽ đi sâu vào từng lệnh này khi thực hành ở Phần 3 nhé!)
Docker Engine – Trái Tim Hoạt Động
Docker Engine là gì?
Đây chính là “trái tim”, là phần cốt lõi của Docker chạy trên máy tính của bạn (hoặc server). Nó là một ứng dụng client-server chịu trách nhiệm thực hiện toàn bộ công việc build và chạy container.
Thành phần chính:
- Docker Daemon (Server): Một tiến trình chạy nền (background process) lắng nghe các yêu cầu từ Docker Client và quản lý các đối tượng Docker như images, containers, networks, volumes.
- Docker CLI (Client): Công cụ dòng lệnh mà chúng ta hay dùng (
docker build
,docker run
,docker ps
…). Nó gửi yêu cầu đến Docker Daemon thông qua API. - REST API: Giao diện để Docker Client và Docker Daemon “nói chuyện” với nhau.
Analogy
Tưởng tượng Docker Engine như một chiếc xe. Docker Daemon là cái động cơ mạnh mẽ chạy bên trong, còn Docker CLI là cái vô lăng, chân ga, chân phanh để bạn điều khiển chiếc xe đó.
Docker Hub / Registry (Kho Chứa Image)
Docker Hub là gì?
Nếu Image là các “bản thiết kế” hay “khuôn mẫu”, thì Registry là nơi để bạn lưu trữ và chia sẻ những khuôn mẫu đó.
Analogy
Giống GitHub cho code, hay App Store/Google Play cho ứng dụng di động.
Docker Hub
Là Registry public lớn nhất và phổ biến nhất do chính Docker cung cấp. Bạn có thể tìm thấy hàng ngàn image có sẵn cho đủ loại công nghệ (Node, Python, Java, Ubuntu, MySQL, Nginx…). Bạn cũng có thể tạo tài khoản miễn phí để lưu trữ image public của mình.
Private Registry
Các công ty lớn hoặc khi cần bảo mật cao hơn, người ta thường tự host một Registry riêng (private) để chỉ lưu trữ image nội bộ.
Lệnh chính
docker pull <image_name>
: Tải một image từ Registry về máy bạn.docker push <image_name>
: Đẩy image từ máy bạn lên Registry (cần đăng nhập).
Chúng hết hợp với nhau như thế nào?
Tóm lại, quy trình phổ biến khi làm việc với Docker thường là:
- Bạn viết các chỉ dẫn vào file
Dockerfile
. - Bạn dùng
docker build
(Docker CLI) yêu cầu Docker Engine đọcDockerfile
và tạo ra mộtImage
. - Image này được lưu trữ trên máy bạn. Bạn có thể tùy chọn
docker push
nó lên mộtRegistry
(như Docker Hub) để chia sẻ hoặc lưu trữ. - Khi muốn chạy ứng dụng, bạn dùng lệnh
docker run
(Docker CLI) yêu cầu Docker Engine tạo và khởi động mộtContainer
từImage
đó (nếu image chưa có trên máy, Docker Engine sẽ tự độngpull
từ Registry về trước).

Lý thuyết cơ bản vậy là khá đủ rồi đó! Ở Phần 3, chúng ta sẽ không nói suông nữa mà bắt tay vào thực hành: Viết Dockerfile đầu tiên để “Docker hóa” một ứng dụng Node.js đơn giản. Sẽ rất thú vị đấy!
Lời kết
Hy vọng qua phần này, anh em đã nắm vững được các khái niệm cốt lõi: Image là khuôn mẫu, Container là thực thể chạy từ khuôn mẫu đó, Dockerfile là bản thiết kế để tạo Image, Docker Engine là trái tim thực thi, và Registry là kho lưu trữ. Đây là nền tảng vững chắc để chúng ta tự tin khám phá sâu hơn về Docker trong các phần tới. Hẹn gặp lại anh em!
SiuCode – Vừa code vừa siuuuu🚀