Bỏ qua đến nội dung chính
DockercontainerDevOpsbackenddeployment

Docker Cơ Bản Cho Dev Backend: Hướng Dẫn Từ 0

Docker cơ bản cho dev backend: image, container, volume, network. Code Dockerfile thực tế cho Node.js + Postgres. Đủ để deploy production.

Xuất bản 8 phút đọc

Docker cơ bản là kỹ năng nền cho backend dev hiện đại. Bài này đi từ "container là gì" đến viết Dockerfile chạy được Node.js + Postgres — kèm volume, network, multi-stage build.

Container là gì? Khác VM ra sao?

Virtual machine ảo hoá toàn bộ OS — mỗi VM có kernel riêng, init system riêng, ~1-2GB RAM. Container share kernel với host, chỉ ảo hoá process namespace + filesystem layer. Kết quả: container start trong giây, tốn ít RAM, mỗi server chạy được hàng trăm container.

Image vs Container

  • Image: blueprint read-only. Layer cached, share giữa container.
  • Container: instance chạy của image. Có ID, có state, có thể stop/start/remove.
  • Registry: kho chứa image. Docker Hub mặc định, hoặc tự host (Harbor, GitHub Container Registry).

Dockerfile cho Node.js app

# Dockerfile — Node.js production
FROM node:22-slim AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev

FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
USER node
CMD ["node", "server.js"]

3 chi tiết quan trọng:

  • Multi-stage: deps stage build dependency, stage cuối chỉ copy node_modules — image production không có git, gcc...
  • USER node: chạy với non-root user. Nếu container bị compromise, attacker không có root.
  • COPY package*.json trước: tận dụng layer cache. Khi anh sửa code (không sửa package.json), Docker dùng layer npm ci đã cache — build nhanh.

.dockerignore — bắt buộc

node_modules
.git
.env
*.log
.next
.DS_Store
__tests__
*.md

Không có file này, COPY . . sẽ copy node_modules cũ vào image — chậm build, image phình to, có thể leak secret từ .env.

Build và run

# Build image
docker build -t alodev-api:latest .

# List image
docker images

# Run container
docker run -d --name api -p 3000:3000 \
  -e DATABASE_URL=postgres://localhost/app \
  alodev-api:latest

# Xem log
docker logs -f api

# Vào shell container
docker exec -it api sh

# Stop / remove
docker stop api && docker rm api

Volume — persist data

Container ephemeral — restart = mất state internal. Database data phải mount ra ngoài:

# Named volume (Docker quản lý)
docker run -d --name pg \
  -e POSTGRES_PASSWORD=secret \
  -v pg-data:/var/lib/postgresql/data \
  postgres:16

# Bind mount (host directory)
docker run -d --name pg \
  -e POSTGRES_PASSWORD=secret \
  -v /host/pg:/var/lib/postgresql/data \
  postgres:16

Named volume an toàn hơn bind mount — Docker quản lý, không lệ thuộc absolute path. Bind mount tốt cho dev (mount source code).

Network — container nói chuyện với nhau

# Tạo network
docker network create app-net

# Run database trong network
docker run -d --name pg --network app-net \
  -e POSTGRES_PASSWORD=secret postgres:16

# Run app cùng network — connect "pg" hostname
docker run -d --name api --network app-net \
  -e DATABASE_URL=postgres://postgres:secret@pg:5432/app \
  -p 3000:3000 alodev-api:latest

Trong cùng network, container resolve nhau bằng tên (pg, api). Không cần biết IP. Đây là service discovery built-in.

Tối ưu image size

Base imageSizeKhi dùng
node:22~1GBDev, debug
node:22-slim~250MBProduction phổ biến
node:22-alpine~150MBPure JS, không native module
gcr.io/distroless/nodejs22~120MBBảo mật cao, không shell

Kết luận

Docker cơ bản gói gọn trong: image (read-only) → container (running) → volume (persist) → network (connect). Master 4 khái niệm này, anh deploy được app vào bất cứ server nào. Bước tiếp: học Dockerfile best practicesDocker Compose cho dev environment.

Zalo