|
|
@@ -0,0 +1,189 @@
|
|
|
+# 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
|
|
|
+
|
|
|
+```bash
|
|
|
+# 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
|
|
|
+
|
|
|
+```bash
|
|
|
+git clone <repo-url> /opt/timelapse
|
|
|
+cd /opt/timelapse
|
|
|
+```
|
|
|
+
|
|
|
+### 3. Tạo file `.env`
|
|
|
+
|
|
|
+```bash
|
|
|
+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
|
|
|
+
|
|
|
+```bash
|
|
|
+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
|
|
|
+
|
|
|
+```bash
|
|
|
+# 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
|
|
|
+
|
|
|
+```bash
|
|
|
+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
|
|
|
+
|
|
|
+```dockerfile
|
|
|
+# 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ợ.
|
|
|
+
|
|
|
+### Thay đổi 2: npm thay vì pnpm
|
|
|
+
|
|
|
+```dockerfile
|
|
|
+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:
|
|
|
+```bash
|
|
|
+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:
|
|
|
+```bash
|
|
|
+sudo docker exec timelapse-postgres-1 pg_isready -U timelapse
|
|
|
+```
|
|
|
+
|
|
|
+### Worker restart loop
|
|
|
+
|
|
|
+Worker hiện chỉ là stub. Kiểm tra logs:
|
|
|
+```bash
|
|
|
+sudo docker compose logs worker --tail=20
|
|
|
+```
|
|
|
+
|
|
|
+### Muốn rebuild sạch
|
|
|
+
|
|
|
+```bash
|
|
|
+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:
|
|
|
+```bash
|
|
|
+sudo sysctl vm.overcommit_memory=1
|
|
|
+```
|
|
|
+
|
|
|
+### Google OAuth (tuỳ chọn)
|
|
|
+
|
|
|
+Điền `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` trong `.env` và restart:
|
|
|
+```bash
|
|
|
+sudo docker compose restart api-server
|
|
|
+```
|