Brave
@47c132035ed7a1105a867946b99d67af 开源软件研究 公开
讨论 从入门到精通:Dockge 使用进阶指南

从入门到精通:Dockge 使用进阶指南

Dockge 作为知名正常运行时间监控工具 Uptime Kuma 作者的又一力作,凭借其清爽的界面和以 compose.yaml 为核心的管理理念,迅速在自托管(Self-Hosted)和 Docker 爱好者社区中流行起来。它的基础功能——创建、编辑、启动和停止堆栈(Stack)——非常直观,但要真正发挥其全部潜力,我们需要深入探索其进阶功能。

与 Portainer 等传统工具相比,Dockge 最大的哲学差异在于:它不会将配置"绑架"到自己的数据库中。Dockge 直接在磁盘上读取和管理 compose.yaml 文件夹——如果你卸载 Dockge,所有容器和配置文件依然保留在原处,整洁有序。这种"文件即配置"的透明设计,是它赢得众多用户青睐的核心原因之一。

本文将带你超越基础操作,探讨如何通过高级配置、网络管理、数据备份和多服务器部署,将你的 Dockge 使用体验提升到一个新的水平。


1. 🛠️ 优化 compose.yaml:更高效的堆栈管理

Dockge 的核心是其交互式 compose.yaml 编辑器。Dockge 采用混合编辑模式:左侧是原始 YAML 代码,右侧是可视化字段(端口、卷、环境变量等),让你既能享受可视化编辑的便利,又能保持对底层配置的完全掌控。 除了基础的服务定义,掌握一些高级特性可以让你的堆栈配置更灵活、更易于维护。

1.1 📝 关于 version 字段的重要说明

⚠️ 重要更新如果你在编写 compose.yaml 文件时仍在使用 version: '3.8' 这样的版本声明,现在是时候移除它了。

根据 Docker 官方文档,自 Docker Compose V2(2022 年正式发布)起,version 顶级元素已被完全忽略。 现代 Docker Compose 完全依赖 Compose Specification 来解析文件,无需版本声明。

如果你保留 version 字段,运行时会看到如下警告:

WARN[0000] /.../docker-compose.yml: the attribute 'version' is obsolete,
it will be ignored, please remove it to avoid potential confusion

建议做法:直接删除 version 行,让你的配置文件更简洁,避免不必要的困惑。Dockge 基于 Compose V2 构建,完全兼容 Compose Specification。

1.2 🔐 善用 .env 文件管理环境变量

硬编码配置信息(如密码、API 密钥或域名)到 compose.yaml 文件中是一个坏习惯。Dockge 优雅地集成了对 .env 文件的支持,让你能够将配置与代码分离。

在 Dockge 的堆栈编辑界面,compose.yaml 编辑器下方就是 .env 文件的编辑区域。

进阶实践:

实践说明示例
🔑 分离敏感信息将数据库密码、API 密钥等敏感数据存储在 .env 文件中,通过 ${VARIABLE_NAME} 语法引用.env: DB_PASSWORD=mysecret123
compose.yaml: - DB_PASSWORD=${DB_PASSWORD}
🌐 环境特定配置为开发和生产环境准备不同的 .env 文件(如 .env.dev.env.prod),根据需要加载开发环境使用本地数据库,生产环境使用远程数据库
📁 全局变量定义通用路径或参数,在多个服务中复用DOCKER_DATA_PATH=/opt/docker-data
然后在 volumes 中:${DOCKER_DATA_PATH}/mysql:/var/lib/mysql

🔒 安全警告

虽然 .env 文件很方便,但它仍然是明文存储。切勿将包含 .env 文件的项目提交到公共 Git 仓库。

根据 Docker 安全最佳实践,对于更高级别的安全性需求,你应该考虑以下方案:

方案适用场景安全级别
Docker SecretsDocker Swarm 集群环境⭐⭐⭐⭐
HashiCorp Vault企业级密钥管理⭐⭐⭐⭐⭐
外部密钥管理服务云环境(AWS Secrets Manager, Azure Key Vault 等)⭐⭐⭐⭐⭐

关于 Docker Secrets 的重要提示:Docker Secrets 在独立容器模式下无法使用,仅支持 Docker Swarm 或 Kubernetes 环境。在 Docker Compose 中使用的 secrets 本质上是将明文文件挂载到 /run/secrets/ 目录,并非真正加密,因此在选择安全方案时需要充分了解其局限性。

1.3 ⏱️ 使用 depends_on 与健康检查控制启动顺序

在复杂的应用中,某些服务(如数据库)需要先于其他应用(如后端 API)启动。你可以在 compose.yaml 中使用 depends_on 来定义这种依赖关系。

但仅使用 depends_on 是不够的! 根据 Docker 官方文档,默认的 depends_on 只确保依赖容器已启动,而不保证服务已准备就绪。 例如,数据库容器可能已启动,但数据库进程尚未完成初始化,此时连接会失败。

✅ 推荐做法:结合 healthcheckcondition: service_healthy

services:
  backend:
    image: my-backend-app
    depends_on:
      database:
        condition: service_healthy  # 等待数据库健康检查通过
        restart: true               # 当依赖服务重启时,本服务也重启
    environment:
      - DB_HOST=database

  database:
    image: postgres:16
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: myapp
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myuser -d myapp"]
      interval: 10s      # 每 10 秒检查一次
      timeout: 5s        # 检查命令超时时间
      retries: 5         # 连续 5 次失败才判定为不健康
      start_period: 30s  # 容器启动后的宽限期

depends_on 支持的三种条件:

条件说明使用场景
service_started默认值,仅检查容器是否已启动对启动顺序要求不严格的服务
service_healthy等待健康检查通过后才启动依赖它的服务数据库、消息队列等需要初始化时间的服务
service_completed_successfully等待服务成功完成并退出一次性初始化任务、数据库迁移脚本

常见服务的健康检查示例:

# PostgreSQL
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
  interval: 10s
  retries: 5

# MySQL / MariaDB
healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 10s
  retries: 5

# Redis
healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 10s
  retries: 5

# MongoDB
healthcheck:
  test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
  interval: 10s
  retries: 5

2. 🌐 高级网络管理:隔离与互联

Docker 默认为容器提供一个 bridge 网络,但这不利于环境隔离。通过在 Dockge 中定义和使用自定义网络,可以实现更安全、更有序的容器通信。

2.1 🔗 创建自定义网络

compose.yaml 文件的末尾,你可以声明一个或多个自定义网络。这允许你将一组相关的服务隔离在同一个网络中,只有同网络内的容器才能通过服务名直接通信。

services:
  webapp:
    image: nginx
    networks:
      - my-app-network

  database:
    image: mariadb
    networks:
      - my-app-network

networks:
  my-app-network:
    driver: bridge

为什么需要自定义网络?

特性默认 bridge 网络自定义网络
DNS 解析不支持容器名解析✅ 支持通过服务名直接访问
隔离性所有容器共享✅ 仅同网络内容器可通信
安全性较低✅ 减少攻击面
管理性难以追踪✅ 清晰的网络拓扑

2.2 🔀 实战:集成反向代理网络

一个常见的进阶用法是创建一个全局的反向代理网络(例如,由 Traefik 或 Nginx Proxy Manager 管理),然后让需要暴露到外网的服务加入这个网络。

步骤一:在反向代理的 compose.yaml 中定义网络

# 在 Traefik 或 NPM 的 compose.yaml 中
services:
  traefik:
    image: traefik:v3.0
    # ... 其他配置
    networks:
      - proxy-network

networks:
  proxy-network:
    name: proxy-network  # 指定一个固定的网络名称,便于其他堆栈引用

步骤二:让其他应用加入此网络

services:
  my-app-service:
    image: my-app-image
    networks:
      - default        # 应用内部网络(与数据库通信)
      - proxy-network  # 加入代理网络(被反向代理访问)
    # Traefik 标签配置示例
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`myapp.example.com`)"

  database:
    image: postgres:16
    networks:
      - default        # 仅在内部网络,无法从外部访问

networks:
  default:
    # 应用内部网络,无需额外配置
  proxy-network:
    external: true     # 声明为外部网络,引用已存在的网络

通过这种方式,只有被明确加入 proxy-network 的服务才能被反向代理访问,数据库等敏感服务保持隔离,增强了整体安全性。

网络架构示意图:

┌─────────────────────────────────────────────────────────┐
│                    外部网络 (Internet)                    │
└────────────────────────┬────────────────────────────────┘
                         │
                         ▼
              ┌──────────────────────┐
              │   反向代理 (Traefik)   │
              │   proxy-network      │
              └──────────┬───────────┘
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
    ┌─────────┐     ┌─────────┐     ┌─────────┐
    │  App A  │     │  App B  │     │  App C  │
    │ proxy + │     │ proxy + │     │ proxy + │
    │ default │     │ default │     │ default │
    └────┬────┘     └────┬────┘     └────┬────┘
         │               │               │
         ▼               ▼               ▼
    ┌─────────┐     ┌─────────┐     ┌─────────┐
    │   DB A  │     │   DB B  │     │   DB C  │
    │ default │     │ default │     │ default │
    │  only   │     │  only   │     │  only   │
    └─────────┘     └─────────┘     └─────────┘

3. 💾 可靠的数据与备份策略

数据是自托管服务的核心。不当的卷(Volume)管理可能导致灾难性的数据丢失。

3.1 📂 区分并善用卷(Volumes)与绑定挂载(Bind Mounts)

类型定义优点缺点
绑定挂载将主机上的文件/目录直接挂载到容器路径直观,易于从主机直接访问和备份依赖主机目录结构
命名卷由 Docker 管理的存储区域Docker 统一管理,便于迁移默认位于 /var/lib/docker/volumes/,不够直观

⚠️ 关键警告:Dockge 删除堆栈时的数据风险

Dockge 在删除一个堆栈时,会删除该堆栈所在的整个目录(例如 /opt/stacks/myapp/)。 如果你使用相对路径进行绑定挂载(如 ./data:/app/data),你的持久化数据会和 compose.yaml 文件一起被删除!

✅ 最佳实践:将持久化数据存储在堆栈目录之外

推荐的目录结构:
├── /opt/stacks/              # Dockge 堆栈目录
│   ├── myapp/
│   │   └── compose.yaml      # 堆栈配置文件
│   └── another-app/
│       └── compose.yaml
│
└── /opt/docker-data/         # 应用数据(独立于堆栈目录)
    ├── myapp/
    │   ├── config/
    │   └── data/
    └── another-app/
        └── data/

compose.yaml 配置示例:

services:
  myapp:
    image: myapp:latest
    volumes:
      # ✅ 正确:使用绝对路径,数据存储在堆栈目录之外
      - /opt/docker-data/myapp/config:/config
      - /opt/docker-data/myapp/data:/data

      # ❌ 错误:使用相对路径,删除堆栈时数据会丢失
      # - ./config:/config
      # - ./data:/data

3.2 🔄 制定备份策略

根据社区讨论,备份与恢复功能目前被视为 Dockge 的优先级功能需求,但尚未内置。 这并不妨碍我们建立一套可靠的备份流程。

一个完整的备份应包含两部分:

📑 配置文件备份(compose.yaml 和 .env)

方法说明推荐度
Git 版本控制stacks 目录创建 Git 仓库,每次修改后提交⭐⭐⭐⭐⭐
定期压缩备份使用脚本定期将配置目录打包⭐⭐⭐
同步到云存储使用 rclone 等工具同步到云端⭐⭐⭐⭐

Git 备份示例:

# 初始化 Git 仓库
cd /opt/stacks
git init

# 创建 .gitignore 排除敏感文件(可选,但 .env 建议单独加密备份)
echo "*.log" > .gitignore

# 首次提交
git add .
git commit -m "Initial commit: all stacks configuration"

# 添加远程仓库(使用私有仓库!)
git remote add origin git@github.com:yourusername/my-stacks.git
git push -u origin main

💽 持久化数据备份

工具特点适用场景
rsync轻量、增量同步简单备份到另一台服务器或 NAS
restic加密、去重、支持多种后端备份到云存储(S3、B2 等)
borgbackup高效去重、加密本地或远程备份
ZFS 快照文件系统级快照,即时回滚需要 ZFS 文件系统支持

rsync 备份脚本示例:

#!/bin/bash
# backup-docker-data.sh

BACKUP_SOURCE="/opt/docker-data"
BACKUP_DEST="/mnt/backup/docker-data"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/docker-backup.log"

echo "[$DATE] Starting backup..." >> $LOG_FILE

# 使用 rsync 增量备份
rsync -avz --delete \
  --exclude '*.log' \
  --exclude '*.tmp' \
  "$BACKUP_SOURCE/" "$BACKUP_DEST/"

echo "[$DATE] Backup completed." >> $LOG_FILE

设置定时任务(cron):

# 每天凌晨 3 点执行备份
0 3 * * * /opt/scripts/backup-docker-data.sh

4. 🖥️ 多服务器管理:Dockge Agents

Dockge 1.4.0 版本引入了 Agent(代理)模式,允许你从一个主实例界面管理部署在不同服务器上的多个 Dockge 实例。这使得你可以在一个统一的仪表盘中查看和管理所有服务器上的容器堆栈。

4.1 🔧 工作原理

Agent 模式采用主从架构:

┌─────────────────────────────────────────────────────────┐
│                      你的浏览器                          │
└────────────────────────┬────────────────────────────────┘
                         │ 仅需连接主实例
                         ▼
              ┌──────────────────────┐
              │   Dockge 主实例       │
              │   (充当代理)          │
              └──────────┬───────────┘
                         │ 转发请求/响应
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
    ┌─────────┐     ┌─────────┐     ┌─────────┐
    │ Agent 1 │     │ Agent 2 │     │ Agent 3 │
    │ 服务器 A │     │ 服务器 B │     │ 服务器 C │
    └─────────┘     └─────────┘     └─────────┘

主实例充当代理角色,将请求和响应在你的浏览器与各个远程 Agent 之间进行转发。 这意味着你的浏览器只需连接到主实例,无需直接访问各个远程服务器。

4.2 📋 设置步骤

  1. 部署远程 Dockge 实例:在每台需要管理的服务器上安装并运行 Dockge
  2. 在主实例中添加 Agent
    • 在主 Dockge 实例的仪表盘右侧,找到 "Dockge Agents" 面板
    • 点击 "Add Agent"
    • 输入远程 Dockge 实例的 URL(如 https://server2.example.com:5001)、用户名和密码
  3. 验证连接:连接成功后,该远程实例会出现在代理列表中,状态显示为"在线"
  4. 统一管理:现在,当你新建或编辑一个堆栈时,可以在 "Dockge Agent" 下拉菜单中选择将此堆栈部署到当前节点或任意一个已连接的远程节点上

4.3 ⚠️ 安全注意事项

🔴 重要安全警告

根据社区反馈Agent 的凭据(用户名、密码、URL)目前以明文形式存储在 Dockge 的数据库中。 这带来以下风险:

  • 如果主实例被入侵,攻击者可获取所有 Agent 的访问凭据
  • 如果你在多处复用相同密码,风险会进一步放大

缓解措施:

措施说明
🔑 使用唯一密码为每个 Dockge 实例设置不同的强密码
🔒 网络隔离将 Agent 置于内网或 VPN 中,不直接暴露到公网
🛡️ 反向代理 + HTTPS确保主实例和 Agent 之间的通信加密
📋 等待 API 密钥功能社区正在讨论实现基于 API 密钥的认证方式作为更安全的替代方案

5. 🛡️ 安全加固

将 Dockge 暴露在公网时,务必采取额外的安全措施。

5.1 🔐 基础安全措施

措施优先级说明
使用反向代理 + HTTPS🔴 必须将 Dockge 置于 Traefik、Caddy 或 Nginx Proxy Manager 之后,配置 TLS 加密
设置强密码🔴 必须使用复杂的随机密码,避免常见弱密码
限制访问来源🟡 推荐通过防火墙或反向代理限制允许访问的 IP 范围
定期更新🟡 推荐及时升级到最新版本以获取安全修复

5.2 🔑 增加身份验证层

可以利用 forward-auth 服务或反向代理自带的身份验证功能,为 Dockge 的访问入口添加一层额外的登录保护。

常用的身份验证方案:

方案说明复杂度
Traefik ForwardAuth配合 Authelia、Authentik 等实现 SSO⭐⭐⭐
Nginx Basic Auth简单的 HTTP 基本认证
Cloudflare Access零信任访问控制,支持多种身份提供商⭐⭐
Tailscale / WireGuard通过 VPN 访问,不暴露到公网⭐⭐

5.3 🖥️ 关于控制台功能的安全说明

从近期版本开始,Dockge 默认禁用了"控制台"(Console)功能。 这是一个允许你直接在 Web 界面中执行容器内命令的功能。

如果你确实需要此功能并了解其风险,可以通过设置环境变量启用:

services:
  dockge:
    image: louislam/dockge:1
    environment:
      - DOCKGE_ENABLE_CONSOLE=true  # 启用控制台功能

⚠️ 警告:启用此功能意味着任何能访问 Dockge 界面的人都可以在你的容器内执行命令,请确保已做好充分的访问控制。


6. 📊 Dockge 的局限性与适用场景

在决定是否使用 Dockge 之前,了解它的设计边界非常重要。 根据项目官方说明,Dockge 专注于提供更好的 Docker Compose 管理体验,而非成为一个全功能的容器管理平台。

6.1 ⚖️ Dockge vs Portainer:如何选择?

特性DockgePortainer
配置存储📁 文件系统(透明)🗄️ 内部数据库(封闭)
学习曲线✅ 非常简单⚠️ 功能多,较复杂
启动速度✅ 即时加载⚠️ 较慢
网络管理❌ 基础✅ 完整
卷管理❌ 基础✅ 完整
日志查看⚠️ 合并显示,无法按容器过滤✅ 独立查看每个容器日志
多用户/MFA❌ 不支持✅ 支持
Kubernetes 支持❌ 不支持✅ 支持
适合人群🏠 家庭用户、个人项目🏢 团队、企业环境

6.2 ✅ Dockge 适合的场景

  • 🏠 家庭 Homelab:管理个人的自托管服务
  • 👤 单用户环境:无需复杂的权限管理
  • 📝 重视配置透明性:希望配置文件保持可读、可版本控制
  • 🎯 专注 Docker Compose:不需要管理单独的容器或 Kubernetes
  • 追求简洁高效:不喜欢 Portainer 的复杂界面

6.3 ❌ 可能需要其他工具的场景

  • 需要详细的容器级日志分析和调试
  • 需要完整的网络和卷管理功能
  • 需要多用户协作和权限控制
  • 需要管理 Docker Swarm 或 Kubernetes
  • 需要事件日志和审计追踪

💡 提示:你完全可以同时使用 Dockge 和 Portainer!使用 Dockge 进行日常的堆栈管理,在需要深入调试或高级操作时切换到 Portainer。


7. 🎯 结论

Dockge 以其简洁直观的设计赢得了用户的青睐,但它的强大之处远不止于表面。通过掌握环境变量管理、高级网络配置、稳健的数据备份策略以及多节点部署能力,你可以将 Dockge 从一个简单的容器管理器,转变为一个强大、可靠且高效的自托管服务运维中心。

核心要点回顾:

主题关键实践
📝 Compose 优化移除过时的 version 字段;使用 .env 分离配置;配合 healthcheck 使用 depends_on
🌐 网络管理使用自定义网络隔离服务;通过外部网络集成反向代理
💾 数据安全使用绝对路径挂载,避免数据存储在堆栈目录内;建立 Git + 自动化脚本的备份体系
🖥️ 多节点管理善用 Agent 模式统一管理;注意凭据安全问题
🛡️ 安全加固HTTPS 是底线;考虑额外的身份验证层;谨慎启用控制台功能

不断实践这些进阶技巧,将使你在容器化部署的道路上更加游刃有余。