优化 Docker 开发启动流程

This commit is contained in:
yml2213
2026-07-31 16:27:51 +08:00
parent 30362f14bd
commit a091806283
5 changed files with 86 additions and 45 deletions
+5
View File
@@ -4,8 +4,13 @@ DATA_ENCRYPTION_KEY=your_32_plus_char_data_encryption_key_change_me
POSTGRES_USER=affiliate
POSTGRES_PASSWORD=affiliate_dev_password
POSTGRES_DB=affiliate_dash
POSTGRES_PORT=5432
COMPOSE_PROJECT_NAME=affiliate_dash
POSTGRES_DATA_VOLUME=affiliate_dash_postgres_data
TZ=Asia/Shanghai
DATABASE_URL="postgres://affiliate:affiliate_dev_password@127.0.0.1:5432/affiliate_dash?sslmode=disable&TimeZone=Asia/Shanghai"
# Docker 后端容器内连接串通常不需要改;需要外部数据库时再覆盖。
# DOCKER_DATABASE_URL="postgres://affiliate:affiliate_dev_password@postgres:5432/affiliate_dash?sslmode=disable&TimeZone=Asia/Shanghai"
GIN_MODE=release
OPEN_API_KEY=sk_source_dev_key_change_me
OPEN_API_SECRET=sk_source_dev_secret_change_me
+9 -1
View File
@@ -3,7 +3,7 @@
# admin off
}
skin.khhao.com {
(app_routes) {
encode gzip zstd
# /api-debug 是前端 SPA 路由,不要代理到后端
@@ -25,3 +25,11 @@ skin.khhao.com {
file_server
}
}
:80 {
import app_routes
}
skin.khhao.com {
import app_routes
}
+11 -3
View File
@@ -18,7 +18,7 @@
- Go 1.26+
- Node.js 22+
- Docker(用于自动启动 PostgreSQL 开发容器
- Docker / Docker Compose(用于自动启动 PostgreSQL 开发服务
### 快速启动
@@ -33,6 +33,8 @@ make dev
./start.sh
```
`make dev` 会通过 Docker Compose 启动 `affiliate_dash/postgres`,后端和前端仍在宿主机运行,方便热更新。首次从旧版 `affiliate_dash_postgres_dev` 开发容器迁移时,脚本会停止旧容器并优先复用旧数据卷。
启动后:
- 前端:`http://localhost:5173`
- 后端:`http://localhost:8080`
@@ -61,10 +63,11 @@ cp .env.example .env
# JWT_SECRET — 生产环境务必修改
# OPEN_API_KEY — 皮肤源头对接 API Key
# OPEN_API_SECRET — 签名密钥
# DATABASE_URL — PostgreSQL 连接,容器内主机名为 postgres
# POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB — PostgreSQL 初始化配置
```
> 国内服务器可在 `.env` 中取消 `GOPROXY`、`ALPINE_MIRROR`、`NPM_REGISTRY` 等镜像加速源的注释。
> Docker 后端容器默认使用 `postgres` 作为数据库主机;只有连接外部数据库时才需要设置 `DOCKER_DATABASE_URL`。
### 启动服务
@@ -78,6 +81,7 @@ docker compose up -d --build
服务端口:
- `:80` — 前端页面 + API(Caddy 统一入口)
- `:8080` — 后端 API(直接访问,调试用)
- `:5432` — PostgreSQL(本地开发/调试用,可通过 `POSTGRES_PORT` 调整)
### 常用命令
@@ -89,7 +93,7 @@ make docker-down # 停止并移除
### 自定义域名
修改 `Caddyfile` 中的域名 `skin.khhao.com` 为你的域名,重新构建即可。
`Caddyfile` 默认同时支持本地 `:80` 和示例域名 `skin.khhao.com`。生产部署时把 `skin.khhao.com`为你的域名,重新构建即可。
## 环境变量
@@ -98,6 +102,10 @@ make docker-down # 停止并移除
| `PORT` | 后端端口 | `8080` |
| `JWT_SECRET` | JWT 签名密钥 | 开发默认值 |
| `DATABASE_URL` | PostgreSQL 连接串 | 本地开发默认值 |
| `DOCKER_DATABASE_URL` | Docker 后端容器内 PostgreSQL 连接串,通常无需设置 | Compose 内置默认值 |
| `POSTGRES_PORT` | PostgreSQL 映射到宿主机的端口 | `5432` |
| `COMPOSE_PROJECT_NAME` | Docker Compose 项目名 | `affiliate_dash` |
| `POSTGRES_DATA_VOLUME` | PostgreSQL 数据卷名 | `affiliate_dash_postgres_data` |
| `GIN_MODE` | Gin 运行模式 | `debug` |
| `OPEN_API_KEY` | 开放接口 ApiKey | 需修改 |
| `OPEN_API_SECRET` | 开放接口签名密钥 | 需修改 |
+6 -1
View File
@@ -1,3 +1,5 @@
name: ${COMPOSE_PROJECT_NAME:-affiliate_dash}
services:
postgres:
image: ${POSTGRES_IMAGE:-docker.m.daocloud.io/library/postgres:16-alpine}
@@ -8,6 +10,8 @@ services:
- TZ=${TZ:-Asia/Shanghai}
- PGTZ=${TZ:-Asia/Shanghai}
command: ["postgres", "-c", "timezone=${TZ:-Asia/Shanghai}"]
ports:
- "${POSTGRES_PORT:-5432}:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
restart: unless-stopped
@@ -34,7 +38,7 @@ services:
- PORT=8080
- TZ=${TZ:-Asia/Shanghai}
- JWT_SECRET=${JWT_SECRET}
- "DATABASE_URL=postgres://${POSTGRES_USER:-affiliate}:${POSTGRES_PASSWORD:-affiliate_dev_password}@postgres:5432/${POSTGRES_DB:-affiliate_dash}?sslmode=disable&TimeZone=${TZ:-Asia/Shanghai}"
- "DATABASE_URL=${DOCKER_DATABASE_URL:-postgres://${POSTGRES_USER:-affiliate}:${POSTGRES_PASSWORD:-affiliate_dev_password}@postgres:5432/${POSTGRES_DB:-affiliate_dash}?sslmode=disable&TimeZone=${TZ:-Asia/Shanghai}}"
- GIN_MODE=${GIN_MODE:-release}
- OPEN_API_KEY=${OPEN_API_KEY}
- OPEN_API_SECRET=${OPEN_API_SECRET}
@@ -79,6 +83,7 @@ services:
volumes:
postgres-data:
name: ${POSTGRES_DATA_VOLUME:-affiliate_dash_postgres_data}
backend-data:
caddy-data:
caddy-config:
+55 -40
View File
@@ -25,11 +25,15 @@ POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-affiliate_dev_password}"
POSTGRES_DB="${POSTGRES_DB:-affiliate_dash}"
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
POSTGRES_IMAGE="${POSTGRES_IMAGE:-docker.m.daocloud.io/library/postgres:16-alpine}"
DEV_DB_CONTAINER="${DEV_DB_CONTAINER:-affiliate_dash_postgres_dev}"
COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-affiliate_dash}"
POSTGRES_DATA_VOLUME="${POSTGRES_DATA_VOLUME:-affiliate_dash_postgres_data}"
LEGACY_DEV_DB_CONTAINER="${DEV_DB_CONTAINER:-affiliate_dash_postgres_dev}"
TZ="${TZ:-Asia/Shanghai}"
DATABASE_URL="${DATABASE_URL:-postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:${POSTGRES_PORT}/${POSTGRES_DB}?sslmode=disable&TimeZone=${TZ}}"
export DATABASE_URL
export TZ
export COMPOSE_PROJECT_NAME
export POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DB POSTGRES_PORT POSTGRES_IMAGE POSTGRES_DATA_VOLUME
# 结束指定端口上的进程(避免残留占用)
free_port() {
@@ -49,64 +53,75 @@ free_port() {
fi
}
postgres_container_exists() {
docker ps -a --format '{{.Names}}' | grep -qx "$DEV_DB_CONTAINER"
docker_compose_available() {
command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1
}
postgres_container_running() {
docker ps --format '{{.Names}}' | grep -qx "$DEV_DB_CONTAINER"
postgres_port_reachable() {
(echo >"/dev/tcp/127.0.0.1/${POSTGRES_PORT}") >/dev/null 2>&1
}
postgres_container_timezone_ready() {
local env cmd
env="$(docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' "$DEV_DB_CONTAINER" 2>/dev/null || true)"
cmd="$(docker inspect -f '{{json .Config.Cmd}}' "$DEV_DB_CONTAINER" 2>/dev/null || true)"
grep -qx "TZ=${TZ}" <<<"$env" && grep -qx "PGTZ=${TZ}" <<<"$env" && [[ "$cmd" == *"timezone=${TZ}"* ]]
legacy_postgres_container_exists() {
docker ps -a --format '{{.Names}}' | grep -qx "$LEGACY_DEV_DB_CONTAINER"
}
legacy_postgres_container_running() {
docker ps --format '{{.Names}}' | grep -qx "$LEGACY_DEV_DB_CONTAINER"
}
compose_postgres_running() {
docker compose ps --services --status running 2>/dev/null | grep -qx "postgres"
}
prepare_postgres_volume() {
local legacy_volume="${LEGACY_DEV_DB_CONTAINER}-data"
if [[ "${POSTGRES_DATA_VOLUME}" == "affiliate_dash_postgres_data" ]] && docker volume inspect "$legacy_volume" >/dev/null 2>&1; then
POSTGRES_DATA_VOLUME="$legacy_volume"
export POSTGRES_DATA_VOLUME
log "检测到旧开发库数据卷,Compose 将继续复用: ${POSTGRES_DATA_VOLUME}"
fi
}
stop_legacy_postgres_container() {
if legacy_postgres_container_exists; then
if legacy_postgres_container_running; then
log "检测到旧 PostgreSQL 开发容器,停止后交由 Docker Compose 管理: ${LEGACY_DEV_DB_CONTAINER}"
docker stop "$LEGACY_DEV_DB_CONTAINER" >/dev/null
else
log "检测到旧 PostgreSQL 开发容器已停止,保留容器和数据卷: ${LEGACY_DEV_DB_CONTAINER}"
fi
fi
}
ensure_postgres() {
if command -v docker >/dev/null 2>&1 && postgres_container_exists; then
if ! postgres_container_timezone_ready; then
log "检测到旧 PostgreSQL 开发容器缺少时区配置,重建容器并保留数据卷: ${DEV_DB_CONTAINER}"
docker rm -f "$DEV_DB_CONTAINER" >/dev/null
fi
elif (echo >"/dev/tcp/127.0.0.1/${POSTGRES_PORT}") >/dev/null 2>&1; then
log "检测到本机 PostgreSQL 端口已可访问: ${POSTGRES_PORT}"
if ! docker_compose_available; then
log "未找到 Docker Compose,请确认本机 PostgreSQL 已可通过 DATABASE_URL 访问"
return 0
fi
if ! command -v docker >/dev/null 2>&1; then
log "未找到 Docker,请确认本机 PostgreSQL 已可通过 DATABASE_URL 访问"
return 0
fi
if postgres_container_running; then
log "PostgreSQL 开发容器已运行: ${DEV_DB_CONTAINER}"
elif postgres_container_exists; then
log "启动 PostgreSQL 开发容器: ${DEV_DB_CONTAINER}"
docker start "$DEV_DB_CONTAINER" >/dev/null
prepare_postgres_volume
stop_legacy_postgres_container
if compose_postgres_running; then
log "PostgreSQL Compose 服务已运行: ${COMPOSE_PROJECT_NAME}/postgres"
else
log "创建 PostgreSQL 开发容器: ${DEV_DB_CONTAINER}"
docker run -d \
--name "$DEV_DB_CONTAINER" \
-p "${POSTGRES_PORT}:5432" \
-e POSTGRES_USER="$POSTGRES_USER" \
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
-e POSTGRES_DB="$POSTGRES_DB" \
-e TZ="$TZ" \
-e PGTZ="$TZ" \
-v "${DEV_DB_CONTAINER}-data:/var/lib/postgresql/data" \
"$POSTGRES_IMAGE" \
-c timezone="$TZ" >/dev/null
if postgres_port_reachable; then
log "检测到本机 PostgreSQL 端口已可访问: ${POSTGRES_PORT},跳过 Compose 数据库启动"
return 0
fi
log "启动 PostgreSQL Compose 服务: ${COMPOSE_PROJECT_NAME}/postgres"
docker compose up -d postgres >/dev/null
fi
for i in $(seq 1 40); do
if docker exec "$DEV_DB_CONTAINER" pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then
if docker compose exec -T postgres pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then
log "PostgreSQL 已就绪"
return 0
fi
sleep 0.5
done
echo "错误: PostgreSQL 启动超时"
docker logs "$DEV_DB_CONTAINER" 2>/dev/null || true
docker compose logs postgres 2>/dev/null || true
exit 1
}