- Add rm -rf node_modules/.tmp before npm run build - Without this, tsc -b reads stale .tsbuildinfo from Docker volume and skips recompiling changed files, causing old JS to be served
161 lines
5.1 KiB
YAML
161 lines
5.1 KiB
YAML
# ==================================================
|
||
# OCDP Docker Compose (complete local stack)
|
||
# ==================================================
|
||
# 使用方式:
|
||
# docker compose up --build
|
||
#
|
||
# 说明:
|
||
# - 本文件是本地部署主入口,包含 PostgreSQL、Backend、前端构建和 Nginx。
|
||
# - 默认使用高位宿主端口,避免和本机其他项目冲突。
|
||
# - Nginx 统一监听容器内 80/443(默认映射 WEB_HTTP_PORT=18080、WEB_HTTPS_PORT=18443),
|
||
# 根据路径转发:/api/* → backend,其他路径 → 前端静态文件。
|
||
# ==================================================
|
||
|
||
services:
|
||
# --------------------------------------------------
|
||
# PostgreSQL 数据库
|
||
# --------------------------------------------------
|
||
postgres:
|
||
image: postgres:17-alpine
|
||
container_name: ocdp-postgres
|
||
restart: unless-stopped
|
||
environment:
|
||
POSTGRES_DB: ${POSTGRES_DB:-ocdp}
|
||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=C --lc-ctype=C"
|
||
ports:
|
||
- "${POSTGRES_PORT:-15432}:5432"
|
||
volumes:
|
||
- postgres_data:/var/lib/postgresql/data
|
||
- ./backend/scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init.sql:ro
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-ocdp}"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 30
|
||
start_period: 60s
|
||
networks:
|
||
- ocdp-network
|
||
|
||
# --------------------------------------------------
|
||
# Backend API
|
||
# --------------------------------------------------
|
||
backend:
|
||
build:
|
||
context: ./backend
|
||
dockerfile: Dockerfile
|
||
args:
|
||
GOPROXY: ${GOPROXY:-https://goproxy.cn,direct}
|
||
GOSUMDB: ${GOSUMDB:-sum.golang.google.cn}
|
||
image: ocdp-backend:latest
|
||
container_name: ocdp-backend
|
||
restart: unless-stopped
|
||
env_file:
|
||
- path: ./.env
|
||
required: false
|
||
format: raw
|
||
environment:
|
||
ADAPTER_MODE: ${ADAPTER_MODE:-production}
|
||
PORT: 8080
|
||
JWT_SECRET: ${JWT_SECRET:-change-me-in-production}
|
||
ENCRYPTION_KEY: ${ENCRYPTION_KEY:-change-me-32-bytes-long-key-here}
|
||
DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-ocdp}?sslmode=disable
|
||
ports:
|
||
- "${BACKEND_PORT:-18081}:8080"
|
||
volumes:
|
||
- ./config:/app/config:ro
|
||
- ./data:/app/data
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 5
|
||
start_period: 30s
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
networks:
|
||
- ocdp-network
|
||
|
||
# --------------------------------------------------
|
||
# 构建前端静态资源 (一次性 Job)
|
||
# --------------------------------------------------
|
||
frontend-build:
|
||
image: node:20-alpine
|
||
container_name: ocdp-frontend-build
|
||
init: true
|
||
working_dir: /app
|
||
restart: "no"
|
||
environment:
|
||
NODE_ENV: production
|
||
NPM_CONFIG_PRODUCTION: "false" # ensure devDependencies (tsc, vite) are installed for build
|
||
# 默认通过 Nginx 代理到 backend -> /api/v1
|
||
VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api/v1}
|
||
FILE_OWNER_UID: ${FILE_OWNER_UID:-1000}
|
||
FILE_OWNER_GID: ${FILE_OWNER_GID:-1000}
|
||
command: >
|
||
sh -c "
|
||
set -eux;
|
||
npm ci;
|
||
rm -rf node_modules/.tmp;
|
||
npm run build;
|
||
mkdir -p /build;
|
||
rm -rf /build/*;
|
||
cp -R dist/. /build/;
|
||
if [ -d dist ]; then chown -R "$$FILE_OWNER_UID:$$FILE_OWNER_GID" dist; fi;
|
||
if [ -d /build ]; then chown -R "$$FILE_OWNER_UID:$$FILE_OWNER_GID" /build; fi
|
||
"
|
||
volumes:
|
||
- ./frontend:/app
|
||
- frontend_node_modules:/app/node_modules
|
||
- frontend_dist:/build
|
||
networks:
|
||
- ocdp-network
|
||
|
||
# --------------------------------------------------
|
||
# Nginx - 静态文件 + /api 反向代理统一入口
|
||
# --------------------------------------------------
|
||
nginx:
|
||
image: nginx:1.27-alpine
|
||
container_name: ocdp-nginx
|
||
restart: unless-stopped
|
||
depends_on:
|
||
frontend-build:
|
||
condition: service_completed_successfully
|
||
backend:
|
||
condition: service_healthy
|
||
ports:
|
||
- "${WEB_HTTP_PORT:-18080}:80"
|
||
- "${WEB_HTTPS_PORT:-18443}:443"
|
||
volumes:
|
||
- frontend_dist:/usr/share/nginx/html:ro
|
||
- ./infra/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||
- ./infra/nginx/certs:/etc/nginx/certs:ro
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/healthz || exit 1"]
|
||
interval: 30s
|
||
timeout: 5s
|
||
retries: 5
|
||
networks:
|
||
- ocdp-network
|
||
|
||
# ==================================================
|
||
# Networks
|
||
# ==================================================
|
||
networks:
|
||
ocdp-network:
|
||
driver: bridge
|
||
name: ocdp-network
|
||
|
||
# ==================================================
|
||
# Volumes
|
||
# ==================================================
|
||
volumes:
|
||
postgres_data:
|
||
name: ocdp-postgres-data
|
||
frontend_dist:
|
||
driver: local
|
||
frontend_node_modules:
|
||
driver: local
|