Tại sao bạn nên Dockerize Strapi ngay hôm nay?
Strapi là một Headless CMS tuyệt vời, nhưng việc setup thủ công từng phiên bản Node.js hay PostgreSQL mỗi khi deploy là một cực hình. Mình từng mất cả buổi sáng chỉ để fix lỗi lệch version thư viện giữa máy local và server Ubuntu. Docker sinh ra để giải quyết triệt để nỗi lo “chạy máy em ngon mà”.
Kinh nghiệm thực tế cho thấy Strapi khá ngốn tài nguyên. Trên một con VPS 2GB RAM, nếu chạy không khéo, tiến trình build có thể làm treo cả hệ thống. Bằng cách sử dụng Multi-stage build, mình đã giảm dung lượng Image từ 1.2GB xuống còn khoảng 450MB. Điều này không chỉ giúp tiết kiệm băng thông mà còn đẩy nhanh tốc độ CI/CD lên gấp 3 lần.
Khởi tạo cấu trúc dự án chuẩn
Đầu tiên, hãy tạo một dự án Strapi mới. Mình luôn ưu tiên PostgreSQL cho các dự án thực tế vì khả năng chịu tải và tính toàn vẹn dữ liệu tốt hơn hẳn SQLite.
npx create-strapi-app@latest my-project --quickstart --no-run
Cấu trúc thư mục tối ưu sẽ trông như thế này:
.
├── strapi-app/
│ ├── Dockerfile
│ ├── .dockerignore
│ └── ... (source code)
├── docker-compose.yml
└── .env
Xây dựng Dockerfile tối ưu (Multi-stage build)
Trái tim của quy trình này nằm ở Dockerfile. Thay vì đóng gói tất cả công cụ build vào image cuối cùng, chúng ta sẽ chia làm hai giai đoạn: Build và Runtime. Kỹ thuật này giúp loại bỏ các dependencies dư thừa, giữ cho môi trường production luôn sạch và nhẹ.
Hãy tạo file Dockerfile trong thư mục strapi-app/:
# Stage 1: Build
FROM node:18-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production
WORKDIR /opt/app
COPY . .
RUN npm run build
# Stage 2: Runtime
FROM node:18-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
EXPOSE 1337
CMD ["npm", "run", "start"]
Lưu ý quan trọng: Đừng quên file .dockerignore. Nếu bạn vô tình copy thư mục node_modules từ máy local vào container, các thư viện native như sharp sẽ bị lỗi kiến trúc hệ điều hành ngay lập tức.
Kết nối Strapi và PostgreSQL qua Docker Compose
Strapi có một “tật xấu” là thường xuyên crash nếu database chưa sẵn sàng khởi động xong. Để khắc phục, chúng ta sẽ sử dụng cơ chế healthcheck. Docker Compose sẽ đợi cho đến khi PostgreSQL thực sự sẵn sàng mới bắt đầu kích hoạt container Strapi.
Nội dung file docker-compose.yml ở thư mục gốc:
version: '3.8'
services:
strapi-db:
image: postgres:15-alpine
container_name: strapi-db
env_file: .env
volumes:
- strapi-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${DATABASE_USERNAME} -d $${DATABASE_NAME}"]
interval: 10s
timeout: 5s
retries: 5
strapi-app:
container_name: strapi-app
build:
context: ./strapi-app
depends_on:
strapi-db:
condition: service_healthy
env_file: .env
ports:
- "1337:1337"
volumes:
- ./strapi-app/uploads:/opt/app/public/uploads
volumes:
strapi-data:
Mẹo thực chiến để vận hành ổn định
1. Bảo vệ dữ liệu người dùng
Mọi dữ liệu trong container sẽ biến mất khi bạn cập nhật image mới. Với Strapi, thư mục uploads chứa toàn bộ ảnh và tài liệu của bạn. Hãy luôn map thư mục này ra Volume ngoài như cách mình làm trong file Compose để tránh mất dữ liệu đáng tiếc.
2. Tối ưu RAM cho server yếu
Nếu bạn deploy lên các gói VPS giá rẻ (như DigitalOcean $6/mo hoặc Linode 1GB), hãy giới hạn RAM cho Node.js. Thêm biến môi trường NODE_OPTIONS=--max-old-space-size=1024 để tránh tình trạng Strapi chiếm dụng toàn bộ bộ nhớ và gây sập server.
3. Workflow cho môi trường Development
Khi code ở local, bạn cần tính năng hot-reload. Thay vì dùng Dockerfile cho production, hãy mount trực tiếp code vào container và chạy lệnh npm run develop. Việc này giúp bạn thấy thay đổi ngay lập tức mà không cần rebuild lại image mất thời gian.
Triển khai hệ thống
Mọi thứ đã sẵn sàng. Bây giờ bạn chỉ cần thực hiện một lệnh duy nhất để khởi động toàn bộ hệ thống:
docker-compose up -d --build
Chờ khoảng 2 phút để Docker tải image và build source code. Sau đó, hãy truy cập http://localhost:1337/admin để tạo tài khoản quản trị đầu tiên. Chúc mừng bạn, hệ thống CMS của bạn hiện đã nằm gọn trong một môi trường cô lập, an toàn và cực kỳ dễ scale.

