Trending
6 phút đọc15 tháng 6, 2026334

Docker là gì và tại sao bạn không thể bỏ qua nó nữa

Từ 'works on my machine' đến production smooth như butter Docker giải quyết bài toán này thế nào, và tại sao mình nghĩ đây là tool bắt buộc phải biết.

N

Nguyễn Nhật Long

@nguyennhatlong1303

Docker là gì và tại sao bạn không thể bỏ qua nó nữa

Nếu bạn đã làm dev được một thời gian, chắc chắn đã ít nhất một lần nghe câu này: "Trên máy mình chạy ngon mà". Và người deploy lên server thì nhìn bạn với ánh mắt không mấy thiện cảm. Đây không phải lỗi của bạn, cũng không phải lỗi của server đây là bài toán môi trường, và Docker sinh ra để giải quyết đúng cái đó.

Mình bắt đầu dùng Docker từ khoảng năm 2019, hồi đó team mình có 4 người mà setup môi trường dev mất cả buổi mỗi khi có người mới join. Node version khác nhau, Python path lộn xộn, PostgreSQL config mỗi máy một kiểu. Sau khi chuyển sang Docker, onboarding rút xuống còn docker compose up và xong. Đó là lúc mình thực sự hiểu Docker không chỉ là một tool cool nó giải quyết pain point thật sự.

Container không phải VM thu nhỏ

Nhiều người mới tiếp cận Docker hay nghĩ container giống như VM nhỏ hơn. Không phải vậy. Về mặt kiến trúc, hai thứ này khác nhau khá căn bản.

VM chạy một hệ điều hành khách hoàn chỉnh (guest OS) bên trên hypervisor. Nghĩa là bạn có một Linux kernel riêng, toàn bộ system libraries, drivers tất cả chạy song song với host OS. Boot một VM mất cỡ 30 giây đến vài phút, và mỗi VM thường ngốn 1-10GB disk.

Container thì khác. Nó chia sẻ kernel của host OS, chỉ cô lập ở tầng process, filesystem và network. Không có guest OS nào hết. Kết quả là container boot trong vài mili giây và một image chỉ khoảng 50-100MB (thậm chí ít hơn nếu dùng alpine base).

Theo kinh nghiệm của mình, VM vẫn có chỗ đứng đặc biệt khi bạn cần chạy Windows app trên Linux host, hoặc cần security isolation cực cao. Nhưng với 90% bài toán dev/deploy hàng ngày, container là lựa chọn hợp lý hơn nhiều.

ContainerVirtual Machine
Boot timeMili giây30s - vài phút
Disk size50-500MB1-10GB
KernelDùng chung host kernelKernel riêng
IsolationProcess/FS/NetworkFull OS isolation
OverheadGần như không cóRAM + CPU đáng kể
Use caseApp packaging, microservicesFull OS simulation, legacy apps

Bên trong Docker Engine có gì

Khi bạn cài Docker và gõ lệnh, có khá nhiều thứ chạy ngầm mà bạn không thấy.

Docker Daemon (dockerd) là background process thực sự làm việc nó quản lý images, containers, networks, volumes. Daemon lắng nghe trên Unix socket hoặc TCP port.

Docker CLI là thứ bạn tương tác hàng ngày. Khi bạn gõ docker run nginx, CLI gửi request đến daemon qua REST API, daemon xử lý và trả kết quả về.

Docker Hub là public registry mặc định kho chứa hàng triệu images. Từ nginx, node, python, postgres, redis cho đến các images của từng công ty, từng project open source. Bạn cũng có thể self-host registry riêng với Docker Registry hoặc dùng các managed service như AWS ECR, Google Artifact Registry.

Về Docker Desktop nếu bạn dùng macOS hoặc Windows, đây là cách đơn giản nhất để cài Docker. Nó bundle sẵn daemon, CLI, và một GUI nhỏ để quản lý containers. Trên Linux thì bạn cài Docker Engine trực tiếp, không cần Desktop.

Workflow thực tế trông như thế nào

Mình hay giải thích Docker theo flow này cho người mới:

  1. Bạn viết Dockerfile file mô tả cách build image của app
  2. Chạy docker build → Docker tạo ra image
  3. Chạy docker run → Docker tạo container từ image đó và chạy app
  4. Push image lên registry (Hub hoặc private)
  5. Trên server, pull image về và run đảm bảo chạy y hệt như trên máy local

Cái hay ở đây là image đã đóng gói toàn bộ: code, runtime, dependencies, config. Không cần quan tâm server đang chạy Ubuntu 20 hay 22, đang có sẵn Node version nào container mang theo môi trường của nó.

Tags và images trên Docker Hub

Khi bạn pull một image, bạn thường thấy các tag như node:18, node:18-alpine, node:18-slim. Anh em lưu ý cái này vì nó ảnh hưởng trực tiếp đến size của image:

  • latest: version mới nhất, thường dùng Debian base đầy đủ tools nhưng nặng
  • alpine: dùng Alpine Linux làm base, cực nhẹ (thường chỉ 5-10MB base), nhưng thiếu một số tools và dùng musl thay vì glibc đôi khi gây issue với một số native modules
  • slim: bản Debian đã bỏ bớt packages không cần thiết, cân bằng giữa size và compatibility

Mình thường recommend dùng alpine cho production nếu app không có gì đặc biệt, và slim nếu gặp vấn đề với alpine. Tránh dùng latest trong production vì nó sẽ thay đổi theo thời gian pin cụ thể version đi.

Tại sao CI/CD không thể thiếu Docker

Đây là use case mình thấy Docker tỏa sáng nhất. Một pipeline CI/CD điển hình:

YAML
1# Ví dụ GitHub Actions
2jobs:
3 build-and-deploy:
4 runs-on: ubuntu-latest
5 steps:
6 - name: Build Docker image
7 run: docker build -t myapp:${{ github.sha }} .
8
9 - name: Run tests
10 run: docker run myapp:${{ github.sha }} npm test
11
12 - name: Push to registry
13 run: docker push myapp:${{ github.sha }}
14
15 - name: Deploy
16 run: ssh server "docker pull myapp:${{ github.sha }} && docker run -d myapp:${{ github.sha }}"

Mỗi bước đều dùng cùng một image. Test pass trên CI với image đó thì deploy image đó lên production không có bước nào rebuild lại, không có khả năng môi trường khác nhau. Đây là thứ mà trước Docker, mình phải viết rất nhiều shell script và vẫn không đảm bảo được hoàn toàn.

Microservices và Docker là cặp đôi tự nhiên

Khi bạn break một monolith ra thành nhiều service nhỏ, câu hỏi đặt ra là: làm sao deploy và manage từng service đó? Docker cho phép mỗi service chạy trong container riêng với dependencies riêng service A dùng Node 18, service B dùng Python 3.11, service C dùng Go 1.21, không conflict nhau.

Và khi cần scale, thay vì phải provision thêm server và setup môi trường từ đầu, bạn chỉ cần spin up thêm container trong vài giây. Trên Kubernetes hay Docker Swarm, việc này có thể tự động dựa trên load.

Mình thấy cái này hay ở chỗ: bạn có thể scale từng service độc lập. API gateway đang bị bottleneck? Scale container đó lên, không cần đụng vào auth service hay database service.

Bước tiếp theo

Nếu bạn chưa từng dùng Docker, bước đơn giản nhất là cài Docker Desktop và thử pull một image về chạy:

Terminal
1# Chạy nginx và map port 8080 trên host vào port 80 trong container
2docker run -p 8080:80 nginx
3
4# Mở browser vào localhost:8080 bạn sẽ thấy nginx welcome page

Không cần cài nginx trên máy, không cần config gì Docker lo hết. Đó là cái mà mình muốn bạn cảm nhận trước khi đi sâu vào Dockerfile hay Docker Compose.

Bài tiếp theo trong series này mình sẽ đi vào viết Dockerfile thực tế từ một app Node.js đơn giản, optimize dần để image nhỏ hơn và build nhanh hơn bằng multi-stage builds. Anh em theo dõi nhé.

NN

Nguyễn Nhật Long

@nguyennhatlong1303

Nguyễn Nhật Long is a Senior Frontend Engineer and Frontend Team Leader with 7 years of experience building real-time fintech platforms. Specializing in React, Next.js, TypeScript, and React Native, shipping 10+ products across Web, Mobile, Telegram Mini-Apps, and Web3.

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

Docker là gì và tại sao bạn không thể bỏ qua nó nữa — Stacklog