KDIGI CMS
Kỹ thuật & Tự host

Docker là gì? Hướng dẫn Docker cho người làm website

Đăng 10 phút đọc

Docker là nền tảng đóng gói ứng dụng cùng mọi thứ nó cần (runtime, thư viện, cấu hình) thành một "container" chạy giống nhau trên laptop, VPS hay máy chủ khác. Với người làm website, Docker giúp dựng CMS và cơ sở dữ liệu bằng vài lệnh thay vì cài tay từng phần.

Tóm tắt nhanh

  • Image là bản đóng gói chỉ đọc; container là một tiến trình đang chạy được tạo từ image.
  • Dockerfile mô tả cách build image; Docker Compose chạy nhiều container (ví dụ web và database) từ một file YAML.
  • Dữ liệu phải nằm trong volume, nếu không sẽ mất khi container bị xóa.
  • Bốn lệnh dùng hằng ngày: docker compose up -d, docker compose logs -f, docker compose ps, docker compose down.
  • KDIGI CMS có sẵn Dockerfile và docker-compose.yml: một lệnh docker compose up --build là chạy được cả CMS lẫn PostgreSQL.

Docker là gì? Giải thích cho người làm website

Hãy hình dung cài một website WordPress hay CMS bằng tay: bạn cài đúng phiên bản Node.js hoặc PHP, cài cơ sở dữ liệu, sửa file cấu hình, rồi hy vọng máy chủ giống máy bạn. Lỗi "chạy được trên máy tôi" xuất phát từ đây.

Docker giải quyết bằng cách đóng gói ứng dụng và môi trường của nó vào một đơn vị chuẩn. Theo tài liệu chính thức của Docker, container là các tiến trình được cô lập, chạy trên nhân của máy chủ chứ không mang theo cả một hệ điều hành đầy đủ, nên nhẹ hơn máy ảo.

Với một dự án web, lợi ích thực tế là:

  1. Môi trường nhất quán giữa máy lập trình, máy thử nghiệm và máy chủ thật.
  2. Dựng nhanh: cài Docker một lần, mỗi dự án chỉ cần một file mô tả.
  3. Cách ly: mỗi dự án có phiên bản phần mềm riêng, không đụng nhau.
  4. Nâng cấp và quay lại đơn giản hơn: đổi tag của image.

Nhược điểm: bạn phải học thêm khái niệm mới, quản lý volume cẩn thận, và việc build image tốn bộ nhớ (với KDIGI CMS, tài liệu triển khai khuyến nghị tối thiểu 2 GB RAM).

Image và container khác nhau thế nào?

Khái niệm Ý nghĩa Ví dụ
Image Bản đóng gói chỉ đọc gồm ứng dụng, thư viện, cấu hình khởi động postgres:16-alpine
Container Một thể hiện đang chạy (hoặc đã dừng) của image Container db đang chạy PostgreSQL
Dockerfile File văn bản các bước để build image Dockerfile ở gốc repo
Registry Nơi lưu và tải image Docker Hub
Volume Vùng lưu dữ liệu tồn tại ngoài vòng đời container postgres_data
Compose Công cụ chạy nhiều container theo một file YAML docker-compose.yml

Phép so sánh dễ nhớ: image giống file cài đặt, container giống chương trình đang chạy. Từ một image bạn tạo ra được nhiều container.

Cài Docker và chạy lệnh đầu tiên

Trên máy chủ Linux, làm theo hướng dẫn cài Docker Engine cho bản phân phối của bạn. Trên Windows hoặc macOS, dùng Docker Desktop. Sau khi cài, kiểm tra:

docker --version
docker compose version
docker run hello-world

Lệnh cuối tải image hello-world, chạy một container in thông báo rồi thoát. Nếu thấy thông báo chào mừng, Docker đã hoạt động.

Các lệnh Docker thường dùng

# tải image về máy
docker pull nginx:alpine

# chạy container nền, ánh xạ cổng 8080 của máy vào cổng 80 trong container
docker run -d --name web -p 8080:80 nginx:alpine

# xem container đang chạy (thêm -a để xem cả container đã dừng)
docker ps

# xem log theo thời gian thực
docker logs -f web

# mở shell bên trong container
docker exec -it web sh

# dừng và xóa container
docker stop web
docker rm web

# xem và xóa image không dùng
docker images
docker image prune

Bạn mở http://localhost:8080 sẽ thấy trang chào của Nginx sau lệnh docker run. Tham số -p 8080:80 đọc là "cổng máy chủ : cổng trong container".

Dockerfile: cách tạo image của riêng bạn

Dockerfile là chuỗi chỉ thị, mỗi chỉ thị thêm một lớp (layer) vào image. Một ví dụ tối giản cho ứng dụng Node.js:

FROM node:22-alpine
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm run build
EXPOSE 3000
CMD ["node_modules/.bin/next", "start"]

Build và chạy:

docker build -t myapp:1.0 .
docker run -d -p 3000:3000 myapp:1.0

Thứ tự chỉ thị có ý nghĩa: Docker cache theo lớp, nên copy file khai báo gói trước rồi mới copy mã nguồn giúp những lần build sau không phải cài lại toàn bộ gói. Dự án thực tế thường dùng multi-stage build (nhiều FROM) để image cuối chỉ chứa thứ cần thiết cho chạy thật. Dockerfile của KDIGI CMS làm đúng như vậy với các giai đoạn base, deps, builder và runner trên Node 22 Alpine, chạy bằng người dùng node thay vì root.

Docker Compose: chạy web và database cùng nhau

Một website thật hiếm khi chỉ có một container. Compose cho bạn khai báo cả hệ thống trong docker-compose.yml. Dưới đây là ví dụ rút gọn theo cấu trúc của KDIGI CMS:

services:
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: kdigi
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-kdigi}
      POSTGRES_DB: kdigi
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U kdigi -d kdigi']
      interval: 5s
      retries: 10
    restart: unless-stopped

  app:
    build: .
    depends_on:
      db:
        condition: service_healthy
    environment:
      DATABASE_URI: postgres://kdigi:${POSTGRES_PASSWORD:-kdigi}@db:5432/kdigi
      PAYLOAD_PUBLIC_SERVER_URL: ${PAYLOAD_PUBLIC_SERVER_URL:-http://localhost:3000}
    ports:
      - '3000:3000'
    volumes:
      - media_data:/app/media
    restart: unless-stopped

volumes:
  postgres_data:
  media_data:

Mấy điểm cần hiểu:

  • ${POSTGRES_PASSWORD:-kdigi} nghĩa là lấy biến môi trường, nếu trống thì dùng kdigi. Giá trị mặc định này chỉ dành cho máy cá nhân.
  • depends_on với condition: service_healthy bắt app chờ database sẵn sàng (healthcheck pg_isready báo ổn).
  • Trong mạng Compose, app gọi database bằng tên dịch vụ db, không phải localhost. Đây là lỗi kết nối database phổ biến nhất khi mới dùng Compose.
  • volumes giữ dữ liệu database và file media qua những lần khởi động lại.

Các lệnh Compose bạn dùng hằng ngày:

docker compose up -d --build   # build (nếu cần) và chạy nền
docker compose ps              # trạng thái các dịch vụ
docker compose logs -f app     # xem log của dịch vụ app
docker compose exec db psql -U kdigi -d kdigi   # mở psql trong container db
docker compose down            # dừng và xóa container, GIỮ volume
docker compose down -v         # dừng, xóa container VÀ XÓA volume (mất dữ liệu)

Hãy nhớ phân biệt down và down -v: lệnh thứ hai xóa dữ liệu.

Chạy KDIGI CMS bằng Docker

Repo mã nguồn mở của KDIGI CMS đã có sẵn Dockerfile, docker-compose.yml và script khởi động. Để chạy thử trên máy:

git clone https://github.com/kdigivn/kdigi-cms-open.git
cd kdigi-cms-open
docker compose up --build

Theo tài liệu của dự án, bạn không cần cấu hình thêm: stack tự dựng PostgreSQL, tự sinh PAYLOAD_SECRET trong lần chạy đầu và lưu trong volume app_data. Mở http://localhost:3000/admin và tạo người dùng đầu tiên. Muốn có sẵn website mẫu để xem thử, thêm SEED_DEMO=true phía trước lệnh. Migration cơ sở dữ liệu chạy tự động mỗi lần app khởi động qua docker/entrypoint.sh.

Dữ liệu nằm trong ba volume có tên là postgres_data, media_data và app_data, tồn tại sau docker compose down và bị xóa khi dùng down -v.

Đưa lên VPS

Để chạy production, bạn cần máy chủ Linux có Docker và Compose, tối thiểu 2 GB RAM theo tài liệu triển khai, cùng một tên miền trỏ về máy chủ. Các bước tóm tắt:

git clone https://github.com/kdigivn/kdigi-cms-open.git
cd kdigi-cms-open
cat > .env <<'EOF'
POSTGRES_PASSWORD=dat-mat-khau-dai-ngau-nhien
PAYLOAD_SECRET=chuoi-ngau-nhien-it-nhat-32-ky-tu
PAYLOAD_PUBLIC_SERVER_URL=https://cms.example.com
ENABLE_JOBS_AUTORUN=true
EOF
docker compose up -d --build

Sau đó đặt một reverse proxy có TLS (ví dụ Caddy hoặc nginx) phía trước cổng 3000. Cập nhật về sau bằng git pull && docker compose up -d --build. Tài liệu cũng cảnh báo hai điều: không dùng SEED_DEMO=true trên hệ thống thật, và hãy mở trang admin tạo người dùng đầu tiên ngay sau khi triển khai vì người đầu tiên trở thành super-admin. Toàn bộ quy trình, gồm cả Coolify và chạy không Docker, nằm ở trang tự host KDIGI CMS.

Sao lưu khi dùng Docker

Dữ liệu của bạn là volume, nên sao lưu là việc của bạn. Với database đi kèm:

docker compose exec -T db pg_dump -U kdigi --format=custom kdigi > kdigi-$(date +%F).dump

Media trên ổ đĩa cục bộ cũng cần sao lưu riêng, và nên thử khôi phục trên máy khác trước khi cần dùng thật. Chi tiết xem sao lưu và nâng cấp.

Lỗi thường gặp khi dùng Docker

Triệu chứng Nguyên nhân thường gặp Cách xử lý
port is already allocated Cổng máy chủ đang bị chương trình khác dùng Đổi cổng trái trong -p hoặc dừng chương trình đó
App không kết nối được database Dùng localhost thay vì tên dịch vụ db Đặt host là db trong chuỗi kết nối
Ảnh tải lên mất sau khi deploy lại Thư mục media không nằm trên volume Gắn volume cho /app/media
Build bị kill giữa chừng Thiếu RAM Build trên máy lớn hơn hoặc thêm swap
Đăng nhập admin bị lặp, lỗi 403 URL công khai cấu hình sai Đặt PAYLOAD_PUBLIC_SERVER_URL đúng origin trên trình duyệt
Mất dữ liệu sau khi dọn dẹp Chạy docker compose down -v Luôn sao lưu trước, chỉ dùng -v khi cố ý

Khi gặp lỗi lạ, thói quen tốt là chạy docker compose ps để xem trạng thái, rồi docker compose logs -f app để đọc log trước khi đoán nguyên nhân.

Câu hỏi thường gặp

Docker là gì?

Docker là nền tảng đóng gói ứng dụng và môi trường chạy của nó thành container. Container chạy nhất quán trên nhiều máy khác nhau, nhẹ hơn máy ảo vì dùng chung nhân hệ điều hành. Người làm website dùng Docker để dựng CMS, database và công cụ nhanh, tránh khác biệt giữa máy phát triển và máy chủ.

Docker Compose là gì?

Docker Compose là công cụ chạy nhiều container bằng một file YAML. Bạn khai báo các dịch vụ như web và database, mạng, volume và biến môi trường, rồi dùng docker compose up -d để khởi động tất cả cùng lúc. Lệnh docker compose down dừng và gỡ chúng.

Docker có miễn phí không?

Docker Engine là phần mềm mã nguồn mở và cài trên Linux không mất phí. Docker Desktop và một số dịch vụ của hãng có điều khoản cấp phép và gói trả phí tùy quy mô tổ chức, nên hãy xem điều khoản hiện hành trên trang chính thức trước khi dùng trong công ty.

Docker khác máy ảo ở điểm nào?

Máy ảo mang theo cả hệ điều hành khách và cần hypervisor, nên nặng và khởi động chậm hơn. Container chia sẻ nhân của máy chủ và chỉ đóng gói ứng dụng cùng thư viện, vì vậy nhẹ và khởi động nhanh hơn, đổi lại mức cách ly yếu hơn máy ảo.

Chạy Docker cần cấu hình máy bao nhiêu?

Bản thân Docker nhẹ, nhưng yêu cầu tùy ứng dụng. Với KDIGI CMS, tài liệu triển khai khuyến nghị tối thiểu 2 GB RAM, vì bước build image tốn nhiều bộ nhớ. Nếu build bị kill, hãy build trên máy mạnh hơn hoặc thêm swap.

Bước tiếp theo

Nếu bạn muốn thử ngay, chạy docker compose up --build trong repo KDIGI CMS rồi đọc trang tự host để đưa lên máy chủ thật. Chưa rõ CMS headless là gì? Xem Headless CMS là gì, và nếu bạn viết nội dung bằng Markdown, đọc bài Markdown là gì.

Nguồn

Bài viết liên quan

Chính sách biên tập: bài viết do đội ngũ KDIGI biên soạn, thông tin sản phẩm đối chiếu với mã nguồn và tài liệu chính thức, thông tin về sản phẩm khác kèm nguồn dẫn. Xem thêm giới thiệu KDIGI.