Quay lại
Backend
6 phút đọc25 tháng 3, 20265

Docker cho người mới: Hiểu đúng, dùng đúng từ ngày đầu

Tất cả những gì bạn cần biết về Docker để bắt đầu — không lý thuyết suông, có ví dụ thực tế và góc nhìn từ người đã dùng Docker hàng ngày.

N

Nguyen Nhat Long

@longnn

Sơ đồ luồng hoạt động của Docker

Bạn đã bao giờ nghe câu "Ở máy tao chạy ngon mà" chưa? Mình cá là ai làm dev cũng từng nghe ít nhất một lần. Đó chính xác là vấn đề mà Docker sinh ra để giải quyết. Và nếu bạn đang bắt đầu tìm hiểu Docker, thì đây là bài viết mình ước mình có từ hồi mới học.

Mình đã dùng Docker gần như mỗi ngày trong suốt 4 năm qua — từ side project nhỏ đến hệ thống production phục vụ hàng triệu request. Điều mình nhận ra là: Docker không khó, nhưng nhiều người hiểu sai ngay từ đầu rồi loay hoay mãi. Bài này mình sẽ đi thẳng vào những thứ thực sự quan trọng.

Vấn đề thực tế Docker giải quyết

Hình dung thế này: bạn code một app bằng Node.js 18, dùng PostgreSQL 15, cần Redis, cần cài thêm vài thư viện hệ thống. Mọi thứ chạy ngon trên máy bạn. Rồi đến lúc deploy lên server, hoặc đơn giản hơn — đồng nghiệp mới vào team clone repo về.

Chuyện gì xảy ra? Máy người ta dùng Node 16. PostgreSQL thì version khác. Redis chưa cài. Thư viện hệ thống thiếu. Mất nửa ngày chỉ để setup môi trường.

Docker giải quyết chuyện này bằng cách đóng gói toàn bộ application cùng với môi trường của nó vào một cái gọi là container. Container này chạy giống hệt nhau trên mọi máy — laptop của bạn, máy đồng nghiệp, hay server production.

Minh họa so sánh cách deploy truyền thống và deploy bằng Docker
Minh họa so sánh cách deploy truyền thống và deploy bằng Docker

Docker khác máy ảo (VM) ở chỗ nào?

Nhiều người mới hay nhầm Docker với máy ảo. Khác biệt lớn nhất: VM ảo hóa cả hệ điều hành, còn Docker chỉ ảo hóa ở tầng application. VM cần vài phút để boot, tốn vài GB RAM. Container Docker start trong vài giây, tốn vài chục MB.

Theo kinh nghiệm của mình, đây là lý do Docker thắng trong hầu hết use case phát triển phần mềm hiện đại. Bạn có thể chạy 10-20 container trên một laptop bình thường, trong khi chạy 10 VM thì máy đã muốn nổ rồi.

So sánh kiến trúc VM và Docker container
So sánh kiến trúc VM và Docker container

Những khái niệm cốt lõi bạn cần nắm

Docker có khá nhiều thuật ngữ, nhưng bạn chỉ cần hiểu rõ 4 thứ này trước:

Image

Image là bản "blueprint" — một template chứa mọi thứ cần thiết để chạy application: code, runtime, thư viện, biến môi trường. Image là read-only, không thay đổi được.

Container

Container là một instance đang chạy của image. Một image có thể tạo ra nhiều container. Nghĩ đơn giản: image là class, container là object.

Dockerfile

Đây là file config để Docker biết cách build ra image. Mình sẽ nói kỹ hơn ở phần dưới.

Docker Hub / Registry

Nơi lưu trữ và chia sẻ image. Docker Hub là registry công khai lớn nhất — giống GitHub nhưng cho Docker image. Bạn cũng có thể dùng registry riêng trên AWS ECR, Google Container Registry, hay tự host.

Sơ đồ luồng hoạt động của Docker
Sơ đồ luồng hoạt động của Docker

Dockerfile — Trái tim của mọi thứ

Điều mình thấy hay là Dockerfile cực kỳ dễ đọc, gần như đọc là hiểu. Đây là ví dụ thực tế:

Dockerfile
1FROM golang:1.11 AS builder
2WORKDIR /go/src/docker-demo/
3COPY . .
4RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o docker-demo .
5
6FROM alpine:latest
7WORKDIR /root/
8COPY --from=builder /go/src/docker-demo .
9CMD ["./docker-demo"]

Đây là một multi-stage build — kỹ thuật mà mình khuyên bạn nên dùng từ đầu. Stage đầu dùng image golang nặng để build binary. Stage sau chỉ dùng alpine (siêu nhẹ, ~5MB) để chạy binary đó. Kết quả: image cuối cùng nhỏ gọn hơn rất nhiều.

Những instruction quan trọng nhất:

  • FROM — image gốc để bắt đầu (bắt buộc, luôn là dòng đầu tiên)
  • WORKDIR — set thư mục làm việc trong container
  • COPY / ADD — copy file từ máy host vào container
  • RUN — chạy lệnh khi build image (cài package, compile code...)
  • CMD — lệnh mặc định khi container start
  • EXPOSE — khai báo port container lắng nghe
  • ENV — set biến môi trường

Một tip từ kinh nghiệm thực tế: thứ tự các instruction rất quan trọng. Docker cache từng layer, nên bạn nên đặt những thứ ít thay đổi (như COPY package.jsonRUN npm install) lên trước, còn source code hay thay đổi thì COPY sau. Build sẽ nhanh hơn đáng kể.

Các lệnh Docker bạn sẽ dùng hàng ngày

Không cần nhớ hết, nhưng đây là những lệnh mình dùng nhiều nhất:

Terminal
1# Build image từ Dockerfile
2docker build -t my-app .
3
4# Chạy container
5docker run -d -p 8080:8080 --name my-app my-app
6
7# Xem container đang chạy
8docker ps
9
10# Xem log
11docker logs my-app
12
13# Dừng và xóa container
14docker stop my-app
15docker rm my-app
16
17# Xóa tất cả container đã dừng
18docker container prune
19
20# Xóa tất cả image không dùng
21docker image prune -a

Mẹo: lệnh docker container prunedocker system prune là bạn thân của bạn. Mình đã từng bị đầy ổ cứng vì quên dọn image và container cũ — đừng lặp lại sai lầm đó.

Docker Compose — Khi app cần nhiều service

Thực tế hiếm khi app chỉ chạy một container. Bạn cần database, cache, message queue... Docker Compose cho phép bạn define tất cả trong một file docker-compose.yml:

YAML
1version: '3.8'
2services:
3 app:
4 build: .
5 ports:
6 - "8080:8080"
7 depends_on:
8 - db
9 - redis
10 db:
11 image: postgres:15
12 environment:
13 POSTGRES_PASSWORD: secret
14 redis:
15 image: redis:7-alpine

Một lệnh docker compose up là toàn bộ stack chạy. Đồng nghiệp mới vào team? Clone repo, chạy docker compose up, xong. Không cần cài PostgreSQL, không cần cài Redis, không cần đọc wiki setup dài 3 trang.

Minh họa Docker Compose orchestrate nhiều container
Minh họa Docker Compose orchestrate nhiều container

Những điều mình học được sau nhiều năm dùng Docker

Đừng chạy container với quyền root. Thêm USER instruction trong Dockerfile để chạy với user không có quyền root. Đây là security basic nhưng nhiều người bỏ qua.

Dùng .dockerignore. Giống .gitignore, file này giúp bạn loại bỏ node_modules, .git, file log... khỏi build context. Image nhẹ hơn, build nhanh hơn.

Không lưu data quan trọng trong container. Container là ephemeral — nó có thể bị xóa bất cứ lúc nào. Dùng Docker Volume để persist data, đặc biệt là database.

Pin version cụ thể cho base image. Đừng dùng FROM node:latest. Dùng FROM node:18.19-alpine. "Latest" hôm nay khác "latest" ngày mai, và bạn sẽ không muốn production build bị break vì chuyện này.

Checklist best practices khi dùng Docker
Checklist best practices khi dùng Docker

Bắt đầu từ đâu?

Nếu bạn đọc đến đây và chưa từng dùng Docker, đây là lộ trình mình gợi ý:

  1. Cài Docker Desktop (Windows/Mac) hoặc Docker Engine (Linux)
  2. Chạy docker run hello-world để verify
  3. Viết Dockerfile cho project hiện tại của bạn
  4. Thêm docker-compose.yml nếu project cần database
  5. Thử deploy container lên một VPS nhỏ

Đừng cố học hết Docker Swarm, Kubernetes, hay orchestration phức tạp ngay. Nắm vững Dockerfile và Docker Compose trước đã — hai thứ đó cover 90% nhu cầu hàng ngày của một developer.

Docker không phải silver bullet, nhưng nó là một trong những công cụ có ROI cao nhất mà mình từng học. Đầu tư vài ngày để hiểu rõ, và bạn sẽ tiết kiệm được hàng trăm giờ về sau. Chúc bạn setup ngon lành từ lần đầu tiên — hoặc ít nhất là từ lần thứ hai. 😄

NN

Nguyen Nhat Long

@longnn

Thấy hay? Chia sẻ cho bạn bè!

Bài viết liên quan

Có thể bạn cũng thích

Xem tất cả