mcpField
D
dokploy-docker-compose

dokploy-docker-compose

github.com/trfi云与 DevOps195 次安装3 天前更新
代码仓库

关于 dokploy-docker-compose

Dokploy Docker Compose Deployment Skill 提供在 Dokploy 上部署 Docker Compose 和 Docker Stack 服务的指导,面向配置部署、持久化文件、网络、域名、环境变量及健康检查的运维人员。

主要功能

  1. 01选择 Compose、Stack 或 Git 部署
  2. 02选择持久化卷和文件挂载方式
  3. 03配置环境变量加载
  4. 04设置域名和 Traefik 路由
  5. 05排查服务网络与健康检查问题
  6. 06参考部署及 init container 模式

适用场景

  1. 01将多服务 Compose 配置适配到 Dokploy
  2. 02在重新部署后保留应用数据
  3. 03通过域名路由已部署服务
  4. 04诊断 DNS、配置或健康检查故障

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trfi/skills --skill dokploy-docker-compose

安装后在 Claude Code 中输入/dokploy-docker-compose确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
healthchecks.md
init-container-patterns.md
librechat-example.md
signoz-example.md
sop-compose-deployment.md
sop-git-deployment.md

详细介绍

Dokploy Docker Compose 部署技能

概述

Dokploy 是一个可自托管的部署平台,可在 VPS 上管理 Docker 容器。它支持两种 Compose 模式(Docker Compose 和 Docker Stack),并且需要遵循特定模式才能可靠运行。

快速决策树:

  • 单仓库应用,带有 Dockerfile?→ 使用 Application (Git) 部署
  • 预构建镜像或多服务栈?→ 使用 Compose 部署
  • 需要公共 HTTPS 域名?→ 使用 Domains tab(Dokploy 会自动注入 Traefik 标签)
  • 需要为每个应用隔离网络?→ 在 UI 中启用 Isolated Deployments
  • 无需 SSH 即可提供配置文件?→ 在 Advanced → Mounts 中使用 File Mounts
  • 需要生成配置文件并下载二进制文件的复杂服务栈?→ 使用 Init Containers 模式

第 1 部分:服务类型

Compose(Docker Compose 模式)

适用于:使用预构建镜像的多服务栈。行为与标准的 docker compose up 相同。

与本地运行相比的主要限制:

  • 每次通过 AutoDeploy 部署都会执行 git clone,这会清空仓库目录——首次推送后,任何相对路径(如 ./config.yaml)都将为空或缺失
  • 服务中绝不要使用 container_name:——它会破坏 Dokploy 的日志、指标和监控功能
  • 相对绑定挂载(./data)仅在首次部署时有效;请改用 ../files/ 或命名卷
Stack(Docker Swarm 模式)

用于编排部署的 Docker Stack 模式。与 Compose 模式的主要区别:

  • 不支持 build: 指令——必须使用来自镜像仓库的预构建镜像
  • Traefik 标签必须放在 deploy.labels 下,而不能直接放在 labels 下
  • 使用副本和私有镜像仓库时,在 Advanced → Command 中添加 --with-registry-auth 标志
Application(Git)部署

适用于:通过 Dockerfile 构建的源代码。

步骤:创建 Service → Application → Source: Git → Build Type: Dockerfile → 在 Advanced 中配置 Volumes 和 Ports。


第 2 部分:卷策略

⚠️ Dokploy 关键规则:绝对主机路径(例如 /opt/myapp/)会在部署期间被清理。绝不要使用它们。请改用 ../files/ 文件夹或命名卷。

命名卷(最适合数据库和大型数据)
services:
  db:
    image: postgres:16
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

这些卷由 Docker 管理。支持通过 Dokploy 的 Volume Backups 功能进行自动备份。最适合数据库和大型数据集。

../files/ 绑定挂载(最适合配置文件和小型数据)

Dokploy 提供一个持久化的 ../files/ 文件夹,部署后仍会保留:

volumes:
  - ../files/my-config:/etc/myapp/config    ✅ persists across deploys
  - ../files/my-database:/var/lib/mysql     ✅ persists across deploys
  - ./config.yaml:/app/config.yaml          ❌ wiped on each AutoDeploy (git clone)
  - /opt/myapp/data:/app/data               ❌ absolute paths are cleaned up by Dokploy

无需直接访问主机文件。最适合配置文件和小型数据集。不支持备份。

VPS 上的主机路径:../files/ 会映射到主机上 Dokploy 项目目录内的 files/ 文件夹。首次部署后,要查找确切路径,请通过 SSH 登录并运行:

# Step 1: find your container name (Dokploy names them <stack>-<service>-1)
docker ps --format "table {{.Names}}\t{{.Image}}" | grep <service-keyword>

# Step 2: inspect that container to see where ../files/ maps on the host
docker inspect <container-name> | grep -A2 '"Source"'

或者查看 Dokploy UI 中的 Docker tab——其中会直接列出容器名称。

File Mounts(Dokploy UI — 用于直接粘贴配置内容)

在 Advanced → Mounts → Add Mount → File Mount 中:

  • Content:粘贴文件文本
  • File Path:仅填写文件名(例如 config.yaml)
  • Mount Path:完整的容器路径(例如 /app/config/config.yaml)

✅ 最适合:完全通过 Dokploy UI 管理的配置文件 ❌ 不适用于:二进制文件、需要在运行时生成的文件、大小超过几 KB 的文件

Init Container 模式(适用于需要生成配置文件的复杂服务栈)

如果服务栈需要在运行时写入多个配置文件,或下载二进制文件,请使用 alpine 初始化容器,在主服务启动前将文件写入共享命名卷:

services:
  my-conf:
    image: alpine:3.20
    command:
      - /bin/sh
      - -lc
      - |
        cat > /config/app.yaml <<'YAML'
        key: value
        YAML
        apk add --no-cache wget && wget -O /scripts/tool "https://..."
    volumes:
      - app-config:/config
      - app-scripts:/scripts
    restart: "no"   # MUST exit after running

  app:
    depends_on:
      my-conf:
        condition: service_completed_successfully
    volumes:
      - app-config:/etc/app/
      - app-scripts:/usr/local/scripts/

**Shell 转义:**在 Compose heredoc 中使用 $$——写作 $$(uname -s),而不是 $(uname -s)。

完整示例请参阅 references/init-container-patterns.md。

选择合适的卷方式
需求方法
数据库数据命名卷
自动备份到 S3命名卷(唯一选项)
配置文件 — 在 UI 中管理文件挂载
配置文件 — 较大或较复杂../files/ 绑定挂载
生成的配置 + 二进制文件Init 容器 → 命名卷
❌ 不要使用绝对主机路径、./ 相对路径

第 3 部分:环境变量

Dokploy 如何处理环境变量

在 Environment 选项卡中设置的变量会写入与 docker-compose.yml 相同目录下的 .env 文件。它们不会自动注入容器。你必须在 Compose YAML 中使用以下两种方式之一显式加载这些变量:

选项 A — 加载所有变量(适用于变量较多的情况):

services:
  app:
    env_file:
      - .env        # loads every variable from Dokploy's Environment tab

选项 B — 选择特定变量:

services:
  app:
    environment:
      - JWT_SECRET=${JWT_SECRET}
      - DATABASE_URL=${DATABASE_URL}
      - PORT=3000                   # hardcoded values also work

⚠️ 如果使用 environment: 并显式指定变量,则只会传递列出的变量。 任何在 UI 中设置但未在此处列出的变量都会被静默忽略。

建议: 对于包含许多机密信息的堆栈(LibreChat 等),在每个需要这些变量的服务中使用 env_file: - .env。对于各服务需要不同变量子集的堆栈,则使用显式的 ${VAR} 引用。

生成安全值
openssl rand -hex 32    # 64-char hex string (for keys like CREDS_KEY)
openssl rand -hex 16    # 32-char hex string (for IVs like CREDS_IV)

第 4 部分:域名与 Traefik 路由

Dokploy 使用 Traefik 作为反向代理。通过域名公开服务有两种方式。

方法 1:Dokploy 域名 UI(推荐 — 自 v0.7.0 起)

进入你的服务 → Domains 选项卡 → Add Domain。Dokploy 会在部署时自动注入正确的 Traefik 标签到你的 compose 文件中。你无需手动处理这些标签。

⚠️ 先部署,再添加域名。 Domains 选项卡需要服务处于运行状态 — 首次部署前无法添加域名。

  • 通过域名路由时,在 compose YAML 中使用 expose:(而不是 ports:)
  • 使用 Preview Compose 按钮查看自动注入标签后的最终 compose 文件
  • HTTPS:直接使用 DNS(A 记录 → VPS)时启用;使用 Cloudflare 代理时禁用(将 Cloudflare SSL/TLS 设为 Full)
services:
  app:
    image: myapp:latest
    expose:
      - 3000    # container-only; Traefik routes via domain, no host port needed
方法 2:手动添加 Traefik 标签(高级)

如需精细控制,可直接在 compose 文件中添加标签。需要连接到 dokploy-network(共享的 Traefik 网络):

services:
  frontend:
    image: myapp:latest
    expose:
      - 3000
    networks:
      - dokploy-network
    labels:
      - traefik.enable=true
      - traefik.http.routers.my-unique-name.rule=Host(`app.yourdomain.com`)
      - traefik.http.routers.my-unique-name.entrypoints=websecure
      - traefik.http.routers.my-unique-name.tls.certResolver=letsencrypt
      - traefik.http.services.my-unique-name.loadbalancer.server.port=3000

networks:
  dokploy-network:
    external: true

对于 Docker Stack — 标签需放在 deploy.labels 下:

services:
  frontend:
    image: myapp:latest
    deploy:
      labels:
        - traefik.enable=true
        - traefik.http.routers.my-app.rule=Host(`app.yourdomain.com`)
        - traefik.http.services.my-app.loadbalancer.server.port=3000
    networks:
      - dokploy-network
隔离部署

在 Dokploy UI 中启用此功能(在 Compose 服务页面上切换开关),即可为堆栈创建自己的专用网络,而非共享 dokploy-network。此功能:

  • 运行同一应用的多个实例时必需(例如,两个 WordPress 站点)
  • 更安全 — 其他堆栈中的服务无法访问这些服务
  • 自动完成 — Dokploy 会处理所有网络创建和 Traefik 配置

启用隔离部署后,无需手动添加 dokploy-network。 Dokploy 附带的所有开源模板默认都启用了此功能。

⚠️ 如果未启用隔离部署,则只有指定域名的服务会自动添加 dokploy-network。 除非手动添加,否则堆栈中的其他服务不会加入该网络。


第 5 部分:网络与 DNS(EAI_AGAIN 修复)

最常见的多服务错误:

getaddrinfo EAI_AGAIN mongodb

容器无法解析另一个服务的主机名。原因:竞争条件或 DNS 混淆。

修复方法 1 — 健康检查 + 正确的 depends_on(防止竞争条件):

services:
  api:
    depends_on:
      mongodb:
        condition: service_healthy    # waits until healthy, not just started
  mongodb:
    healthcheck:
      test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
      interval: 10s
      retries: 5
      start_period: 10s

修复方法 2 — 显式自定义网络(确保服务之间的 DNS 解析正常):

networks:
  app-net:
    driver: bridge

services:
  api:
    networks: [app-net]
  mongodb:
    networks: [app-net]

⚠️ 避免将 container_name: 用作 DNS 变通方案 — 这会破坏 Dokploy 的监控功能。 容器间通信请改用服务名称。


第 6 部分:健康检查

为每个依赖服务(数据库、缓存、队列)添加 healthcheck。对于需要这些依赖的服务,配合使用 depends_on: condition: service_healthy — 这可以防止服务在依赖项就绪前启动所导致的竞争条件。

示例:

services:
  postgres:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
  app:
    depends_on:
      postgres:
        condition: service_healthy

第 7 部分:更新已部署的服务

手动更新(你不拥有的公共仓库)
  1. 前往 Deployments 选项卡 → 点击 Deploy
  2. 如果 Docker 缓存已过期:查找“Redeploy without Cache”,或在 System Settings 中清除 Build Cache
通过 Webhook 自动更新
  1. 从 Deployments 选项卡复制 Webhook URL
  2. 将其添加到 GitHub/GitLab/Gitea 仓库的 Settings → Webhooks
  3. 每次向该分支推送都会触发自动部署

第 8 部分:常见错误与修复方法

错误原因修复方法
getaddrinfo EAI_AGAIN <hostname>竞态条件 / DNS添加 healthcheck + condition: service_healthy;使用自定义网络
重新部署后配置文件为空./ 相对路径被 git clone 清除使用 ../files/ 绑定挂载或 UI 中的 File Mount
JwtStrategy requires a secret or key未注入 JWT 环境变量添加 env_file: - .env 或显式设置 - JWT_SECRET=${JWT_SECRET};Redeploy(不要用 Restart)
ENOENT: no such file or directory配置文件未挂载在 Advanced → Mounts 中使用 File Mount,或使用 ../files/ 绑定挂载
卷上的 permission denied旧卷属于其他用户重命名卷(例如 data-v2),以强制重新创建
容器 is unhealthy镜像的 healthcheck 配置错误根据镜像类型调整 healthcheck 命令;参见第 6 部分
Dokploy 中缺少日志/指标服务设置了 container_name:移除 container_name: —— 它会导致 Dokploy 监控失效
添加域名后服务无法互相发现不在同一网络上使用 Isolated Deployments,或手动将 dokploy-network 添加到所有服务

第 9 部分:参考文件

  • references/sop-compose-deployment.md — 适用于任何多服务 Compose 堆栈的分步 SOP
  • references/sop-git-deployment.md — 使用 Dockerfile 从 Git 部署
  • references/librechat-example.md — LibreChat:JWT 密钥、MongoDB DNS、librechat.yaml 挂载
  • references/signoz-example.md — SigNoz:初始化容器、ClickHouse、Zookeeper 迁移
  • references/init-container-patterns.md — 使用 heredocs 和二进制文件下载的初始化容器模式
  • references/healthchecks.md — 常见服务的 healthcheck 片段

快速检查清单:调整任意 docker-compose.yml 以适配 Dokploy

  • 移除所有 container_name: —— 会导致 Dokploy 日志和指标失效
  • 将 ./ 相对绑定挂载替换为 ../files/ 或命名卷
  • 不要使用绝对主机路径(/opt/...)—— 部署时会被清理
  • 移除 user: "${UID}:${GID}" —— 会在 Dokploy 中导致权限错误
  • 移除 env_file: - ./.env —— 文件将不存在;使用 env_file: - .env(不带 ./)或 ${VAR} 语法
  • 添加 env_file: - .env,或为每个密钥显式引用 ${VAR} —— 环境变量不会自动注入
  • 为所有数据库/依赖服务添加 healthcheck
  • 更新 depends_on,使用 condition: service_healthy,而不只是服务名称
  • 对于域名:除非需要自定义 Traefik 配置,否则使用 Dokploy 的 Domains 选项卡(方法 1)
  • 对通过 Traefik 域名路由的服务使用 expose:(而不是 ports:)
  • 在文件底部声明所有命名卷

评论

支持 Markdown