Skip to content

Docker Compose 部署(Docker Hub 镜像)

更新时间:2026-02-27

若你尚未确定部署方式,建议先阅读 部署总览与选型建议

1. 镜像对应关系

  • API:dujiaonext/api:tagname
  • User(用户前台):dujiaonext/user:tagname
  • Admin(后台):dujiaonext/admin:tagname

2. 准备部署目录

bash
mkdir -p /opt/dujiao-next/{config,data/db,data/uploads,data/logs,data/redis,data/postgres}
cd /opt/dujiao-next

# 关键:避免日志/数据库目录权限不足(api 容器默认非 root 用户)
chmod -R 0777 ./data/logs ./data/db ./data/uploads ./data/redis ./data/postgres

目录说明:

  • config/:API 配置文件(config.yml
  • data/db:SQLite 数据目录(仅 SQLite 方案使用)
  • data/uploads:上传文件目录
  • data/logs:API 日志目录
  • data/redis:Redis 数据目录
  • data/postgres:PostgreSQL 数据目录(仅 PostgreSQL 方案使用)

3. 准备 API 配置文件

API 容器默认读取 /app/config.yml,先下载模板:

bash
curl -L https://raw.githubusercontent.com/dujiao-next/dujiao-next/main/config.yml.example -o ./config/config.yml

你需要在 ./config/config.yml 里按方案修改数据库与 Redis 配置。

⚠️ 重要安全提醒:上线前必须修改 JWT 密钥。

  • jwt.secret(后台管理员登录 Token)
  • user_jwt.secret(前台用户登录 Token)

请务必使用高强度随机字符串(建议至少 32 位),严禁使用模板默认值。否则会导致 Token 可伪造,存在严重安全风险。

3.1 方案 A:SQLite + Redis(推荐轻量部署)

yaml
database:
  driver: sqlite
  dsn: /app/db/dujiao.db

redis:
  enabled: true
  host: redis
  port: 6379
  password: your-strong-redis-password
  db: 0
  prefix: "dj"

queue:
  enabled: true
  host: redis
  port: 6379
  password: your-strong-redis-password
  db: 1
  concurrency: 10
  queues:
    default: 10
    critical: 5

3.2 方案 B:PostgreSQL + Redis(推荐生产)

yaml
database:
  driver: postgres
  dsn: host=postgres user=dujiao password=dujiao_pass dbname=dujiao_next port=5432 sslmode=disable TimeZone=Asia/Shanghai

redis:
  enabled: true
  host: redis
  port: 6379
  password: your-strong-redis-password
  db: 0
  prefix: "dj"

queue:
  enabled: true
  host: redis
  port: 6379
  password: your-strong-redis-password
  db: 1
  concurrency: 10
  queues:
    default: 10
    critical: 5

4. 编写 .env

/opt/dujiao-next/.env 新建:

env
TAG=latest
TZ=Asia/Shanghai

API_PORT=8080
USER_PORT=8081
ADMIN_PORT=8082

# 默认管理员(仅首次初始化时生效)
DJ_DEFAULT_ADMIN_USERNAME=admin
DJ_DEFAULT_ADMIN_PASSWORD=admin123

# Redis
REDIS_PASSWORD=your-strong-redis-password

# PostgreSQL(PostgreSQL 方案需要)
POSTGRES_DB=dujiao_next
POSTGRES_USER=dujiao
POSTGRES_PASSWORD=dujiao_pass

🔒 安全提示(务必阅读):Docker 会绕过主机防火墙

Docker 通过直接写入 iptables 的 DOCKER 链来实现端口映射,完全绕过 ufw / firewalld 等主机防火墙规则。若在 compose 中写 ports: - "6379:6379",即使你用 ufw 只放行了 80/443,Redis / PostgreSQL 等端口依然会暴露到公网,极易被扫描爆破。

因此本文档遵循两条原则:

  1. Redis / PostgreSQL 不导出任何端口,仅通过内部 dujiao-net 网络供 api 容器访问。
  2. API / User / Admin 端口绑定 127.0.0.1,仅允许本机 Nginx 反代,不对公网开放。

如需临时从宿主机调试 Redis/PostgreSQL,可用 docker exec 进入容器,或为对应服务临时添加 ports: - "127.0.0.1:6379:6379"(同样仅绑定本机回环)。

5. 编写 Compose 文件

5.1 方案 A(SQLite + Redis):docker-compose.sqlite.yml

yaml
services:
  redis:
    image: redis:7-alpine
    container_name: dujiaonext-redis
    restart: unless-stopped
    environment:
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
    volumes:
      - ./data/redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - dujiao-net

  api:
    image: dujiaonext/api:${TAG}
    container_name: dujiaonext-api
    restart: unless-stopped
    environment:
      TZ: ${TZ}
      DJ_DEFAULT_ADMIN_USERNAME: ${DJ_DEFAULT_ADMIN_USERNAME}
      DJ_DEFAULT_ADMIN_PASSWORD: ${DJ_DEFAULT_ADMIN_PASSWORD}
    ports:
      - "127.0.0.1:${API_PORT}:8080"
    volumes:
      - ./config/config.yml:/app/config.yml:ro
      - ./data/db:/app/db
      - ./data/uploads:/app/uploads
      - ./data/logs:/app/logs
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - dujiao-net

  user:
    image: dujiaonext/user:${TAG}
    container_name: dujiaonext-user
    restart: unless-stopped
    environment:
      TZ: ${TZ}
    ports:
      - "127.0.0.1:${USER_PORT}:80"
    depends_on:
      api:
        condition: service_healthy
    networks:
      - dujiao-net

  admin:
    image: dujiaonext/admin:${TAG}
    container_name: dujiaonext-admin
    restart: unless-stopped
    environment:
      TZ: ${TZ}
    ports:
      - "127.0.0.1:${ADMIN_PORT}:80"
    depends_on:
      api:
        condition: service_healthy
    networks:
      - dujiao-net

networks:
  dujiao-net:
    driver: bridge

5.2 方案 B(PostgreSQL + Redis):docker-compose.postgres.yml

yaml
services:
  redis:
    image: redis:7-alpine
    container_name: dujiaonext-redis
    restart: unless-stopped
    environment:
      REDIS_PASSWORD: ${REDIS_PASSWORD}
    command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
    volumes:
      - ./data/redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - dujiao-net

  postgres:
    image: postgres:16-alpine
    container_name: dujiaonext-postgres
    restart: unless-stopped
    environment:
      TZ: ${TZ}
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - dujiao-net

  api:
    image: dujiaonext/api:${TAG}
    container_name: dujiaonext-api
    restart: unless-stopped
    environment:
      TZ: ${TZ}
      DJ_DEFAULT_ADMIN_USERNAME: ${DJ_DEFAULT_ADMIN_USERNAME}
      DJ_DEFAULT_ADMIN_PASSWORD: ${DJ_DEFAULT_ADMIN_PASSWORD}
    ports:
      - "127.0.0.1:${API_PORT}:8080"
    volumes:
      - ./config/config.yml:/app/config.yml:ro
      - ./data/uploads:/app/uploads
      - ./data/logs:/app/logs
    depends_on:
      redis:
        condition: service_healthy
      postgres:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - dujiao-net

  user:
    image: dujiaonext/user:${TAG}
    container_name: dujiaonext-user
    restart: unless-stopped
    environment:
      TZ: ${TZ}
    ports:
      - "127.0.0.1:${USER_PORT}:80"
    depends_on:
      api:
        condition: service_healthy
    networks:
      - dujiao-net

  admin:
    image: dujiaonext/admin:${TAG}
    container_name: dujiaonext-admin
    restart: unless-stopped
    environment:
      TZ: ${TZ}
    ports:
      - "127.0.0.1:${ADMIN_PORT}:80"
    depends_on:
      api:
        condition: service_healthy
    networks:
      - dujiao-net

networks:
  dujiao-net:
    driver: bridge

6. 外层 Nginx 反向代理(必需)

useradmin 分别通过各自域名的 /api/uploads 路径访问后端,因此你需要在最外层网关(Nginx/Ingress)配置反向代理。

下方示例使用默认端口:

  • API: 127.0.0.1:8080
  • User: 127.0.0.1:8081
  • Admin: 127.0.0.1:8082

如果你在 .env 修改了端口,请同步替换。

6.1 分域名部署示例

nginx
# 前台 User
server {
    listen 80;
    server_name user.example.com;

    location / {
        proxy_pass http://127.0.0.1:8081;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8080/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /uploads/ {
        proxy_pass http://127.0.0.1:8080/uploads/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# 后台 Admin
server {
    listen 80;
    server_name admin.example.com;

    location / {
        proxy_pass http://127.0.0.1:8082;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8080/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /uploads/ {
        proxy_pass http://127.0.0.1:8080/uploads/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

7. 启动与运维命令

7.1 启动(SQLite + Redis)

bash
docker compose --env-file .env -f docker-compose.sqlite.yml up -d

7.2 启动(PostgreSQL + Redis)

bash
docker compose --env-file .env -f docker-compose.postgres.yml up -d

7.3 常用命令

bash
docker compose --env-file .env -f docker-compose.sqlite.yml ps
docker compose --env-file .env -f docker-compose.sqlite.yml logs -f api
docker compose --env-file .env -f docker-compose.sqlite.yml down

若使用 PostgreSQL 方案,将文件名替换为 docker-compose.postgres.yml 即可。

7.4 默认后台管理员账号(首次初始化)

当数据库中 admins 表为空,且 API 首次启动时,会使用以下默认管理员:

  • 默认账号:admin
  • 默认密码:admin123

强烈建议:首次登录后台后立即修改密码。

若你希望部署时就使用自定义管理员,请在 .env 中改写:

  • DJ_DEFAULT_ADMIN_USERNAME
  • DJ_DEFAULT_ADMIN_PASSWORD

并保持 compose 中 api 服务已注入上述环境变量。

8. 升级与回滚

升级:

  1. 修改 .envTAG 为目标版本(例如 v1.0.0
  2. 执行 docker compose --env-file .env -f <你的方案文件> pull
  3. 执行 docker compose --env-file .env -f <你的方案文件> up -d

回滚:

  1. TAG 改回历史版本
  2. 执行 docker compose --env-file .env -f <你的方案文件> up -d

9. 访问与联通性检查

由于容器端口已绑定到 127.0.0.1,请在服务器本机检查:

  • API:http://127.0.0.1:${API_PORT}/health
  • User:http://127.0.0.1:${USER_PORT}
  • Admin:http://127.0.0.1:${ADMIN_PORT}

外部用户应通过配置好的域名(经 Nginx 反代)访问。

如页面可打开但接口异常,优先检查:

  1. config.yml 中数据库与 Redis 地址是否与容器名一致(postgres / redis
  2. 外层网关是否已配置 /api/uploads 反向代理
  3. API 与 Redis/PostgreSQL 健康状态(docker compose ps

Released under the MIT License.