Docker là gì? Docker là nền tảng giúp đóng gói ứng dụng cùng toàn bộ thư viện, cấu hình và môi trường cần thiết vào một đơn vị gọi là container. Nhờ vậy ứng dụng chạy giống nhau trên máy lập trình viên, máy kiểm thử và máy chủ thật, giải quyết tình huống quen thuộc “máy em chạy được mà”. Bài viết giải thích các khái niệm image, container, Dockerfile, Docker Compose và hướng dẫn chạy ứng dụng đầu tiên.
Vì sao cần Docker?
Trước khi có container, việc cài một ứng dụng lên server thường gồm nhiều bước thủ công: cài đúng phiên bản ngôn ngữ, cài thư viện hệ thống, cấu hình biến môi trường, cài database… Chỉ cần lệch một phiên bản là ứng dụng có thể lỗi. Docker giải quyết các vấn đề sau:
- Môi trường nhất quán: mọi thứ ứng dụng cần được mô tả trong một file và đóng gói cùng nhau.
- Cài đặt nhanh: người mới vào dự án chỉ cần vài lệnh để chạy toàn bộ hệ thống.
- Cô lập: nhiều ứng dụng dùng các phiên bản khác nhau (ví dụ Node 18 và Node 22) vẫn chạy song song trên cùng một máy.
- Dễ triển khai và mở rộng: container là nền tảng của các hệ thống như Kubernetes và các dịch vụ cloud hiện đại.
Docker khác máy ảo (VM) như thế nào?
Máy ảo giả lập toàn bộ một máy tính, bao gồm cả hệ điều hành riêng. Container thì dùng chung nhân (kernel) hệ điều hành của máy chủ và chỉ đóng gói phần ứng dụng cần.
| Tiêu chí | Máy ảo (VM) | Container (Docker) |
|---|---|---|
| Hệ điều hành | Mỗi VM có một hệ điều hành đầy đủ | Dùng chung kernel của máy chủ |
| Kích thước | Thường hàng GB | Thường nhỏ hơn nhiều, có thể chỉ vài chục MB |
| Thời gian khởi động | Tính bằng phút | Thường chỉ vài giây |
| Mức độ cô lập | Rất cao | Cao, nhưng thấp hơn VM |
| Dùng khi | Cần hệ điều hành khác hẳn, cô lập tuyệt đối | Đóng gói và triển khai ứng dụng |
Trong thực tế, hai công nghệ thường dùng cùng nhau: các máy chủ cloud là máy ảo, và trên đó chạy nhiều container.
Các khái niệm cốt lõi
Image
Image là “bản mẫu” chỉ đọc chứa hệ điều hành tối giản, runtime, thư viện và mã nguồn ứng dụng. Image được xây dựng theo từng lớp (layer); lớp nào không đổi sẽ được dùng lại từ cache giúp build nhanh hơn.
Container
Container là một phiên bản đang chạy của image. Từ một image bạn có thể chạy nhiều container. Có thể hình dung image giống như class, còn container giống như object trong lập trình.
Dockerfile
Dockerfile là file văn bản mô tả từng bước tạo image: dùng image gốc nào, copy file gì, cài thư viện nào, chạy lệnh gì khi khởi động.
Registry và Docker Hub
Registry là nơi lưu trữ và chia sẻ image. Docker Hub là registry công khai phổ biến nhất, chứa image chính thức của nhiều phần mềm như Node.js, Python, MySQL, Nginx.
Volume và network
Dữ liệu bên trong container sẽ mất khi container bị xoá. Volume giúp lưu dữ liệu bền vững (ví dụ dữ liệu database). Network cho phép các container giao tiếp với nhau bằng tên dịch vụ.
Cài đặt Docker
- Windows và macOS: cài Docker Desktop từ trang chính thức docker.com. Trên Windows nên bật WSL 2.
- Linux: cài Docker Engine theo hướng dẫn trong tài liệu chính thức cho từng bản phân phối.
Kiểm tra cài đặt bằng lệnh:
docker --version
docker run hello-world
Ví dụ: đóng gói ứng dụng Node.js
Giả sử bạn có một ứng dụng Express với file package.json và index.js. Tạo file Dockerfile:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
Build và chạy:
docker build -t my-app .
docker run -d -p 3000:3000 --name my-app my-app
Truy cập http://localhost:3000 để xem kết quả. Lệnh -p 3000:3000 ánh xạ cổng 3000 của máy bạn vào cổng 3000 của container.
Nên tạo thêm file .dockerignore để loại bỏ node_modules, .git và file .env khỏi image, giúp image nhỏ hơn và không lộ thông tin bí mật.
Docker Compose là gì?
Ứng dụng thực tế thường gồm nhiều thành phần: backend, database, cache. Docker Compose cho phép mô tả tất cả trong một file compose.yaml và khởi động chỉ bằng một lệnh.
services:
app:
build: .
ports:
- "3000:3000"
environment:
DB_HOST: db
depends_on:
- db
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: example
MYSQL_DATABASE: app
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
docker compose up -d
docker compose logs -f app
docker compose down
Trong ví dụ trên, ứng dụng kết nối tới database bằng tên dịch vụ db thay vì địa chỉ IP. Mật khẩu chỉ dùng để thử nghiệm; trong dự án thật hãy dùng file .env hoặc cơ chế quản lý secret.
Các lệnh Docker hay dùng
| Lệnh | Tác dụng |
|---|---|
docker ps / docker ps -a | Liệt kê container đang chạy / tất cả |
docker images | Liệt kê image |
docker logs -f <tên> | Xem log của container |
docker exec -it <tên> sh | Mở shell bên trong container |
docker stop / docker rm | Dừng / xoá container |
docker rmi | Xoá image |
docker system prune | Dọn tài nguyên không dùng (cẩn thận khi chạy) |
Best practice khi viết Dockerfile
- Dùng image gốc chính thức và nhỏ gọn (ví dụ bản
alpinehoặcslim), ghi rõ phiên bản thay vìlatest. - Copy file khai báo thư viện trước, cài thư viện, sau đó mới copy mã nguồn để tận dụng cache.
- Dùng multi-stage build để tách bước build và bước chạy, giúp image cuối nhỏ hơn.
- Không chạy ứng dụng bằng user root khi không cần thiết.
- Không đưa mật khẩu, API key vào Dockerfile hay image.
Sau Docker nên học gì?
Khi đã quen Docker, bước tiếp theo thường là học cách vận hành nhiều container trên nhiều máy với Kubernetes, tự động build và deploy với CI/CD, và giám sát hệ thống. Toàn bộ con đường này được trình bày trong bài lộ trình học DevOps. Nếu bạn là lập trình viên web, Docker cũng là một phần của giai đoạn deploy trong lộ trình học lập trình web.
Multi-stage build: image nhỏ và an toàn hơn
Với ứng dụng cần bước build (React, Next.js, TypeScript, Go, Java), multi-stage build cho phép dùng một image đầy đủ công cụ để build, rồi chỉ copy kết quả sang một image gọn để chạy:
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
Image cuối chỉ chứa Nginx và file tĩnh đã build, không có mã nguồn, node_modules hay công cụ build. Kết quả là image nhẹ hơn, deploy nhanh hơn và bề mặt tấn công nhỏ hơn.
Debug container khi có lỗi
Khi container không chạy như mong đợi, hãy kiểm tra theo thứ tự:
- Xem log:
docker logs <tên>, đa số lỗi (thiếu biến môi trường, sai cổng, không kết nối được database) hiện ngay ở đây. - Kiểm tra trạng thái:
docker ps -ađể xem container có bị thoát (Exited) và mã thoát là gì. - Vào bên trong:
docker exec -it <tên> shđể kiểm tra file, biến môi trường, thử gọi dịch vụ khác. - Kiểm tra cấu hình:
docker inspect <tên>để xem cổng, volume, network thực tế. - Kiểm tra mạng: trong Compose, các dịch vụ gọi nhau bằng tên dịch vụ, không phải
localhost. Đây là lỗi rất phổ biến của người mới.
Câu hỏi thường gặp
Docker có miễn phí không?
Docker Engine là mã nguồn mở và miễn phí. Docker Desktop miễn phí cho cá nhân, giáo dục và doanh nghiệp nhỏ; doanh nghiệp lớn cần xem điều khoản giấy phép trên trang chính thức.
Docker có chạy được trên Windows không?
Có, thông qua Docker Desktop kết hợp WSL 2. Phần lớn container phổ biến là container Linux.
Docker và Kubernetes khác nhau thế nào?
Docker dùng để tạo và chạy container. Kubernetes dùng để điều phối nhiều container trên nhiều máy: tự khởi động lại khi lỗi, mở rộng số lượng, cân bằng tải.
Lập trình viên frontend có cần học Docker không?
Không bắt buộc, nhưng biết Docker cơ bản giúp bạn chạy backend và database của dự án dễ dàng mà không phải cài thủ công.
Dữ liệu trong container có bị mất không?
Dữ liệu ghi bên trong container sẽ mất khi xoá container. Hãy dùng volume cho dữ liệu cần lưu lâu dài như database.
Kết luận
Docker giúp đóng gói ứng dụng thành container chạy nhất quán ở mọi nơi và đã trở thành kỹ năng cơ bản của lập trình viên backend lẫn DevOps. Hãy bắt đầu bằng việc đóng gói một ứng dụng nhỏ của chính bạn, sau đó thử Docker Compose với database. Nếu muốn học bài bản, tham khảo khoá học Docker: container hoá ứng dụng và tiếp theo là khoá học Kubernetes.