1. Docker là gì?
Docker là nền tảng giúp đóng gói và chạy ứng dụng trong các môi trường được gọi là container.
Một ứng dụng Backend thường phụ thuộc vào nhiều thành phần:
- Ngôn ngữ lập trình và runtime như Go, PHP hoặc Node.js.
- Thư viện và package.
- Database như PostgreSQL hoặc MySQL.
- Cache như Redis.
- Biến môi trường và cấu hình.
- Các công cụ hệ thống cần thiết để ứng dụng hoạt động.
Nếu mỗi developer tự cài đặt những thành phần này theo cách khác nhau, môi trường trên máy cá nhân có thể khác môi trường staging hoặc production. Điều đó dẫn đến những lỗi kiểu “máy tôi chạy được nhưng lên server lại lỗi”. Docker giúp chuẩn hóa môi trường chạy ứng dụng bằng cách đóng gói ứng dụng và các dependency cần thiết thành một image, sau đó tạo container từ image đó.
Docker giải quyết vấn đề gì?
Nhất quán môi trường: Các thành viên trong nhóm có thể chạy cùng image và cấu hình tương tự nhau.
Cô lập ứng dụng: Mỗi container có môi trường tiến trình và filesystem riêng theo cấu hình, giảm xung đột giữa các ứng dụng.
Triển khai thuận tiện: Image có thể được build một lần, lưu trong registry rồi triển khai trên các môi trường tương thích.
Khởi tạo nhanh: Container thường khởi động nhanh hơn máy ảo đầy đủ vì container chia sẻ kernel của hệ điều hành host.
Hỗ trợ CI/CD: Pipeline có thể build image, chạy test trong container và triển khai artifact nhất quán hơn.
2. Container là gì?
Container là một môi trường thực thi tiến trình được cô lập bằng các tính năng của hệ điều hành.
Một container thường có:
- Một hoặc nhiều tiến trình.
- Filesystem riêng theo image và các lớp ghi.
- Cấu hình mạng.
- Giới hạn tài nguyên nếu được thiết lập.
- Các biến môi trường và cấu hình runtime.
Điểm quan trọng là container không phải một máy ảo đầy đủ. Container Linux thông thường sử dụng kernel Linux của host, trong khi máy ảo có hệ điều hành khách với kernel riêng.
3. Image là gì?
Docker Image là một template bất biến dùng để tạo container. Image được tổ chức thành các lớp filesystem và metadata.
Ví dụ:
docker pull nginx:alpine
Lệnh này tải image Nginx với tag alpine.
Sau đó có thể tạo container:
docker run -d --name web -p 8080:80 nginx:alpine
Ứng dụng Nginx chạy bên trong container và cổng 80 của container được ánh xạ ra cổng 8080 trên host.
Image và Container khác nhau thế nào?
Có thể hình dung:
- Image: Bản mẫu để tạo ứng dụng.
- Container: Một instance đang hoặc đã chạy từ image.
Một image có thể được dùng để tạo nhiều container.
Ví dụ, cùng image của một API có thể tạo ra nhiều instance chạy độc lập. Mỗi instance có trạng thái runtime riêng, mặc dù chúng có thể cùng sử dụng một volume hoặc một database bên ngoài.
4. Docker Engine và Docker Architecture
Docker thường được sử dụng theo mô hình client-server.
Các thành phần chính gồm:
Docker Client: Công cụ người dùng tương tác, thường là lệnh docker.
Docker Daemon (dockerd): Thành phần quản lý các đối tượng Docker như image, container, network và volume.
Docker API: Giao diện để client giao tiếp với daemon.
Registry: Nơi lưu trữ và phân phối image, chẳng hạn Docker Hub hoặc private registry.
Luồng thông thường:
- Developer chạy
docker build. - Docker xử lý Dockerfile và build context để tạo image.
- Image có thể được đẩy lên registry.
- Môi trường triển khai lấy image từ registry.
- Docker tạo và chạy container từ image.
Trên Linux, Docker Engine thường chạy trực tiếp trên kernel Linux. Trên macOS và Windows, các giải pháp Docker Desktop thường sử dụng một môi trường Linux VM hoặc cơ chế tương đương để chạy Linux container.
5. Dockerfile là gì?
Dockerfile là file mô tả cách build một Docker image.
Ví dụ Dockerfile cho ứng dụng Go:
FROM golang:1.25 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux \
go build -o /out/api ./cmd/api
FROM scratch
COPY --from=builder /out/api /api
ENTRYPOINT ["/api"]
Ví dụ này minh họa multi-stage build: dùng image Go để biên dịch, sau đó chỉ đưa binary vào image cuối.
6. Build context và .dockerignore
Khi chạy:
docker build -t my-api:dev .
Dấu . là build context. Docker sử dụng các file trong context theo cách phù hợp với builder và Dockerfile.
Nếu context chứa toàn bộ repository, thư mục build output, file log, .git, hoặc các file không cần thiết, quá trình build có thể chậm và vô tình đưa dữ liệu nhạy cảm vào context.
Tạo file .dockerignore:
.git
.env
.env.*
!.env.example
node_modules
vendor
tmp
coverage
*.log
Đây chỉ là ví dụ. Hãy điều chỉnh theo công nghệ và Dockerfile thực tế.
Nếu ứng dụng cần vendor hoặc node_modules được tạo sẵn trong quá trình build, không nên sao chép chúng từ host một cách thiếu kiểm soát. Thông thường nên cài dependency bên trong quá trình build để bảo đảm tính nhất quán.
7. Multi-stage Build
Multi-stage build cho phép sử dụng nhiều stage trong một Dockerfile để tách môi trường build và môi trường runtime.
Ví dụ:
FROM golang:1.25 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux \
go build -o /out/api ./cmd/api
FROM debian:bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /out/api ./api
CMD ["./api"]
Stage đầu chứa compiler và dependency phục vụ build. Stage cuối chỉ chứa runtime cần thiết cùng binary đã biên dịch.
Lợi ích:
- Giảm kích thước image cuối trong nhiều trường hợp.
- Hạn chế công cụ build không cần thiết trong production.
- Tách dependency build khỏi dependency runtime.
- Giảm bề mặt tấn công khi image runtime chứa ít thành phần hơn.
Tuy nhiên, image nhỏ không phải mục tiêu duy nhất. Cần chọn base image tương thích, cập nhật bảo mật và bảo đảm ứng dụng thực sự chạy được.
8. Docker Networking
Container thường cần giao tiếp với nhau và với các hệ thống bên ngoài. Docker networking cung cấp các cơ chế kết nối cho mục đích đó.
Port Mapping
Ví dụ:
docker run -d \
--name web \
-p 8080:80 \
nginx:alpine
Cú pháp -p 8080:80 ánh xạ cổng 8080 của host đến cổng 80 của container.
Nếu không publish cổng, dịch vụ trong container vẫn có thể truy cập được từ các container khác trên network phù hợp, nhưng không mặc nhiên được publish ra host.
Bridge Network
Bridge network thường được dùng cho các container trên cùng một Docker host.
Docker Compose thường tự tạo network cho project để các service có thể giao tiếp bằng tên service.
Có thể tạo network riêng:
docker network create app-network
Sau đó gắn các container vào network phù hợp.
9. Docker Compose là gì?
Docker Compose là công cụ giúp định nghĩa và quản lý ứng dụng gồm nhiều service thông qua file YAML.
Một Backend điển hình có thể gồm:
- API.
- PostgreSQL.
- Redis.
- Worker.
- Message broker.
Thay vì chạy từng lệnh docker run thủ công, ta mô tả các service trong một file Compose.
Healthcheck và Dependency Readiness
Container chạy không có nghĩa ứng dụng bên trong đã sẵn sàng.
Ví dụ, PostgreSQL container có thể đã được tạo nhưng database vẫn đang khởi tạo. Nếu API kết nối quá sớm, ứng dụng có thể nhận lỗi kết nối.
Healthcheck giúp Docker xác định trạng thái sức khỏe theo một lệnh kiểm tra. Với Compose, depends_on kết hợp condition: service_healthy có thể giúp trì hoãn khởi động service phụ thuộc cho đến khi dependency được đánh giá là healthy.
10. Kết luận
Docker giúp chuẩn hóa cách đóng gói, chạy và phân phối ứng dụng. Để sử dụng hiệu quả, cần hiểu rõ mối quan hệ giữa image, container, Dockerfile, networking, volumes và Docker Compose.
Với Backend Developer, những kỹ năng quan trọng nhất không chỉ là biết build image mà còn phải:
- Tạo image có thể tái lập và dễ bảo trì.
- Hiểu cách các container giao tiếp với nhau.
- Bảo đảm dữ liệu được lưu trữ bền vững.
- Quản lý cấu hình và secret an toàn.
- Xử lý startup, shutdown và dependency readiness.
- Tích hợp Docker với testing và CI/CD.
- Phân biệt công cụ chạy container với nền tảng điều phối container.








Khoá học lập trình game con rắn cho trẻ em




