Tại sao SvelteKit cần một quy trình Dockerize chuẩn?
SvelteKit hiện là framework cực kỳ mạnh mẽ cho các ứng dụng web hiện đại. Tuy nhiên, khác với các ứng dụng React hay Vue thuần (SPA) chỉ cần host file tĩnh, SvelteKit mặc định chạy ở chế độ Server-Side Rendering (SSR). Điều này đồng nghĩa với việc bạn cần một môi trường Node.js thực thụ để vận hành code phía server.
Sai lầm phổ biến nhất của anh em là sử dụng một Dockerfile “ngây thơ”. Chỉ cần FROM node rồi npm install, bạn sẽ nhận về một Image nặng hơn 1GB. Image quá khổ làm chậm quá trình CI/CD, tốn bộ nhớ Registry và khiến container khởi động chậm chạp.
Thực tế, mình từng chứng kiến nhiều dự án bị lỗi xung đột thư viện giữa Windows và Linux chỉ vì copy cả folder node_modules vào Docker. Hoặc tệ hơn, dùng adapter-auto khiến container không biết phải chạy ứng dụng bằng lệnh nào khi deploy. Dưới đây là cách mình xử lý những “hố vôi” này.
Bước 1: Chuyển sang Adapter-Node
Mặc định, SvelteKit dùng @sveltejs/adapter-auto. Để chạy ổn định trên Docker hoặc VPS, hãy chuyển sang @sveltejs/adapter-node. Nó sẽ build ứng dụng thành một server Node.js thuần túy, dễ kiểm soát hơn nhiều.
Cài đặt adapter ngay:
npm install -D @sveltejs/adapter-node
Tiếp theo, hãy cập nhật file svelte.config.js:
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter({ out: 'build' })
}
};
export default config;
Bước 2: Dọn dẹp với .dockerignore
Đừng để Docker lãng phí thời gian quét hàng nghìn file rác. Việc bỏ qua node_modules giúp giảm thời gian build từ vài phút xuống còn vài giây. Hãy tạo file .dockerignore tại thư mục gốc:
node_modules
.svelte-kit
build
.env
.env.*
!.env.example
npm-debug.log
.git
.DS_Store
Bước 3: Viết Dockerfile tối ưu (Multi-stage Build)
Kỹ thuật Multi-stage Build giống như việc bạn dùng đủ loại dao thớt để nấu ăn trong bếp, nhưng cuối cùng chỉ mang món ăn sạch sẽ lên bàn tiệc. Chúng ta dùng một Image đầy đủ để build, sau đó chỉ lấy kết quả (artifact) bỏ vào một Image alpine siêu nhẹ.
# Stage 1: Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Tận dụng Docker layer cache bằng cách copy package files trước
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Run stage
FROM node:20-alpine AS runner
WORKDIR /app
# Chỉ lấy những thứ thực sự cần thiết
COPY --from=builder /app/build ./build
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/package-lock.json ./package-lock.json
# Chỉ cài dependencies cho production, bỏ qua devDependencies
RUN npm ci --prod
ENV NODE_ENV=production
ENV PORT=3000
EXPOSE 3000
CMD ["node", "build"]
Kết quả? Image của bạn sẽ giảm từ 1GB xuống còn khoảng 120-150MB. Việc sử dụng npm ci --prod giúp loại bỏ các thư viện cồng kềnh như Vite hay Svelte-check khỏi môi trường chạy thực tế.
Bước 4: Nginx – Lớp bảo vệ cần thiết
Dù Node.js tự chạy được, nhưng đặt Nginx phía trước là lựa chọn khôn ngoan. Nginx xử lý nén Gzip hiệu quả hơn và giúp bạn cấu hình SSL dễ dàng. Tạo file nginx/default.conf:
server {
listen 80;
server_name localhost;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
location / {
proxy_pass http://sveltekit_app:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Bước 5: Triển khai với Docker Compose
Để kết nối ứng dụng và Nginx, hãy dùng Docker Compose. Đây là cách đơn giản nhất để quản lý các container cùng lúc.
services:
sveltekit_app:
build: .
container_name: sveltekit_container
restart: always
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- sveltekit_app
restart: always
Vận hành và Kiểm tra
Kích hoạt hệ thống bằng lệnh: docker-compose up -d --build. Sau khi container chạy, hãy thử gõ docker stats. Bạn sẽ thấy một bất ngờ nhỏ: Một ứng dụng SvelteKit tiêu chuẩn thường chỉ tiêu thụ khoảng 50-70MB RAM. Con số này cực kỳ ấn tượng so với các framework nặng nề khác.
Kinh nghiệm xương máu: Khi deploy lên các VPS rẻ tiền (như gói 5$ của DigitalOcean), hãy luôn giới hạn RAM cho container. Điều này ngăn chặn tình trạng một container bị rò rỉ bộ nhớ (memory leak) làm sập toàn bộ server. Chúc anh em Dockerize thành công!

