DOCKER-SETUP.md 4.6 KB

Construction Timelapse — Docker Setup Guide

Document này ghi lại quy trình chuẩn để build và chạy toàn bộ hệ thống timelapse.

Cấu trúc hệ thống

timelapse-2/
├── apps/
│   ├── api-server/      # NestJS API (port 3001)
│   ├── web-dashboard/   # Next.js frontend (port 3000)
│   ├── worker/          # Background worker
│   └── device-agent/    # Device agent (Python)
├── packages/
│   ├── shared-types/    # Shared TypeScript types
│   └── config/          # Shared tsconfig templates
├── docker-compose.yml
├── .env                  # Secrets (KHÔNG commit)
└── .env.example          # Template cho .env

Các bước thiết lập

1. Prerequisites

# Docker Engine (cần API version tương thích với docker compose plugin)
docker --version          # >= 24.0
docker compose version    # >= 2.20

# Nếu dùng Raspberry Pi / Debian cũ (docker.io package)
# Cần nâng cấp lên Docker CE:
curl -fsSL https://download.docker.com/linux/debian/gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=arm64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/debian bullseye stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt-get install -y docker-ce

2. Clone repo

git clone <repo-url> /opt/timelapse
cd /opt/timelapse

3. Tạo file .env

cp .env.example .env
# Hoặc tạo mới với nội dung:
cat > .env << 'EOF'
GOGS_TOKEN=<your-gogs-token>
DATABASE_URL=postgres://timelapse:timelapse_dev_password@postgres:5432/timelapse_dev
REDIS_URL=redis://redis:6379
JWT_SECRET=<generate-a-long-random-string>
REFRESH_TOKEN_SECRET=<generate-another-long-random-string>
CORS_ORIGIN=http://localhost:3000
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_CALLBACK_URL=http://localhost:3001/v1/auth/google/callback
NODE_ENV=development
EOF

Lưu ý: .env đã được gitignore. KHÔNG bao giờ commit file này.

4. Build và chạy

cd /opt/timelapse

# Build tất cả images (lần đầu mất ~5-10 phút)
sudo docker compose up -d --build

# Kiểm tra trạng thái
sudo docker compose ps

# Xem logs
sudo docker compose logs --tail=30

5. Kiểm tra services

# API health check
curl http://localhost:3001/v1/auth/health

# Web dashboard
curl http://localhost:3000/ | head -5

Kết quả mong đợi:

  • api-server — Up, healthy
  • postgres — Up, healthy
  • redis — Up, healthy
  • web-dashboard — Up
  • worker — Up (hiện là stub)

6. Dừng hệ thống

sudo docker compose down
# Thêm -v để xóa volumes:
sudo docker compose down -v

Dockerfiles — Tại sao khác biệt so với repo gốc

Repo gốc dùng pnpm với workspace:* protocol. Docker build cần 2 thay đổi:

Thay đổi 1: sed convert workspace protocol

# Trong mỗi Dockerfile (api-server, worker, web-dashboard):
RUN sed -i 's|"@shared/types": "workspace:\*"|"@shared/types": "file:../../packages/shared-types"|g' \
  apps/api-server/package.json \
  apps/web-dashboard/package.json \
  apps/worker/package.json

npm (Alpine) không hiểu workspace:* protocol — chỉ pnpm mới hỗ trợ.

Thay đổi 2: npm thay vì pnpm

FROM node:20-alpine
RUN apk add --no-cache npm
WORKDIR /app
...
RUN npm install
RUN cd packages/shared-types && npm run build
RUN cd apps/<app> && npm run build

Troubleshooting

FATAL: database "timelapse" does not exist

Kiểm tra biến môi trường trong container:

sudo docker exec timelapse-api-server-1 sh -c 'echo $DATABASE_URL'
# Phải trỏ đến timelapse_dev KHÔNG phải timelapse
# Đúng: postgres://timelapse:...@postgres:5432/timelapse_dev

PostgreSQL health check fail liên tục

Chờ postgres khởi động xong (~10s). Kiểm tra:

sudo docker exec timelapse-postgres-1 pg_isready -U timelapse

Worker restart loop

Worker hiện chỉ là stub. Kiểm tra logs:

sudo docker compose logs worker --tail=20

Muốn rebuild sạch

sudo docker compose down
sudo docker builder prune -f
sudo docker compose up -d --build

Cấu hình thêm

Redis memory overcommit warning

Thêm vào /etc/sysctl.conf (cần reboot):

vm.overcommit_memory = 1

Hoặc chạy ngay:

sudo sysctl vm.overcommit_memory=1

Google OAuth (tuỳ chọn)

Điền GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET trong .env và restart:

sudo docker compose restart api-server