Document này ghi lại quy trình chuẩn để build và chạy toàn bộ hệ thống timelapse.
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
# 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
git clone <repo-url> /opt/timelapse
cd /opt/timelapse
.envcp .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.
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
# 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, healthypostgres — Up, healthyredis — Up, healthyweb-dashboard — Upworker — Up (hiện là stub)sudo docker compose down
# Thêm -v để xóa volumes:
sudo docker compose down -v
Repo gốc dùng pnpm với workspace:* protocol. Docker build cần 2 thay đổi:
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
Vì npm (Alpine) không hiểu workspace:* protocol — chỉ pnpm mới hỗ trợ.
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
FATAL: database "timelapse" does not existKiể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
Chờ postgres khởi động xong (~10s). Kiểm tra:
sudo docker exec timelapse-postgres-1 pg_isready -U timelapse
Worker hiện chỉ là stub. Kiểm tra logs:
sudo docker compose logs worker --tail=20
sudo docker compose down
sudo docker builder prune -f
sudo docker compose up -d --build
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
Điền GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET trong .env và restart:
sudo docker compose restart api-server