dockge Docker Compose 部署指南
dockge Docker Compose 部署指南:Ubuntu 22.04 上经 Compose 完成生产化部署,含预检、官方 compose.yaml 逐项解说、初始化账号实测、首个栈全生命周期、终端日志与端口冲突/校验错误排障实录
dockge Docker Compose 部署指南
目标:在 Ubuntu 22.04 服务器上通过 Docker Compose 完成 dockge 的生产化部署,覆盖部署前预检、配置文件逐项解说、首次初始化账号、首个栈的全生命周期实测,以及端口冲突、配置校验错误等真实排障场景。本篇所有命令与回显均已在 Ubuntu 22.04 实测通过。
一、环境信息
本篇记录实测所用服务器的软硬件环境与软件版本。dockge 是轻量面板,对硬件要求不高,官方未给出硬性最低配置;实测环境按一般自托管服务器的入门规格记录如下,供读者对照自己的环境评估。
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- 服务引擎与编排工具:Docker Engine 29.8.1、Docker Compose v5.5.1(dockge 依赖此二者管理服务实例,版本满足官方要求的不低于 20 即可)
- dockge 版本:1.5.0(当前最新稳定版,发布物标签
louislam/dockge:1滚动指向该版本;版本核实方式见《dockge 1.5.0 介绍与选型指南》,其查询日期为 2026-10-18) - 部署目录规划:
/opt/dockge(dockge 自身部署文件与数据)、/opt/stacks(被管理的栈目录) - 网络规划:面板端口
5001(宿主端口与面板端口一致);dockge 自身编排网络显式指定网段10.89.26.0/24,与服务器上现有网段无重叠 - 硬件参考:2 vCPU / 2 GB 内存级别即可流畅运行(实测进程常驻内存约 200 MB 量级,面板响应迅速)
部署采用官方标准方式:单机部署一个 dockge 面板,通过挂载服务引擎套接字与栈目录,管理本机上的全部 Compose 栈。多机联邦属于进阶形态(在每台机器各跑一个 dockge 并互加 endpoint),本篇不展开。
二、部署前规划与预检
部署前先做三件事:确认端口空闲、确认目标网段未被占用、确认目录位置。这三步各花几秒钟,能避免部署后最常见的一类返工。
2.1 端口规划与预检
dockge 面板默认监听 5001 端口。先确认宿主机上该端口当前没有被其他进程监听:
$ ss -ltn | grep ":5001"
$ echo $?
1
ss -ltn 列出所有 TCP 监听套接字,grep ":5001" 过滤目标端口;本机回显为空且退出码为 1(grep 无匹配),说明 5001 空闲,可以直接使用。如果这里能看到监听记录(比如已有别的服务占了 5001),要么换掉那个服务,要么把 dockge 的宿主端口顺延为 5002(修改方法与实测见第八章 8.1)。
2.2 网段规划与预检
本篇给 dockge 自身的编排网络显式指定 10.89.26.0/24 网段(避免使用默认随机分配的 172.x 网段,防止与已有网络冲突,也便于跨环境统一规划)。指定前先复核服务器上现有网络没有占用这个网段:
$ docker network ls -q | xargs docker network inspect --format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}' | grep "10.89.26"
$ echo $?
1
命令把当前全部网络的名称与网段列出来再过滤 10.89.26;回显为空、退出码 1,说明该网段未被占用,可以放心使用。读者应把这里换成自己规划的网段做同样复核。网段选择上建议避开常见的 192.168.0.0/16(家庭/办公局域网常用)与 100.64.0.0/16(运营商级 NAT/部分组网工具常用),减少路由冲突概率。
2.3 目录规划
官方推荐两个目录:栈目录与 dockge 自身部署目录。创建并确认:
$ mkdir -p /opt/stacks /opt/dockge
$ ls -ld /opt/stacks /opt/dockge
drwxr-xr-x 2 root root 4096 Oct 18 09:04 /opt/dockge
drwxr-xr-x 2 root root 4096 Oct 18 09:04 /opt/stacks
/opt/stacks 是所有被管理栈的根目录——dockge 的每个栈对应其下的一个子目录(如 /opt/stacks/demo-stack/),子目录里放着该栈的 compose.yaml 与 .env;/opt/dockge 则存放 dockge 自己的部署文件与数据。两个目录分开是官方推荐布局,备份与迁移时各自职责清晰(运维层面的备份策略见《dockge 日常运维手册》)。
三、部署实施
本章按官方 README 的安装流程部署 dockge:获取官方 compose.yaml → 按需追加显式网段 → 校验配置 → 启动。整个过程只有一条启动命令,前期准备做扎实后执行非常顺滑。
3.1 获取官方 compose.yaml
进入部署目录,下载官方维护的 compose.yaml(该文件随 dockge 主分支更新,包含官方推荐的全部挂载与环境变量):
$ cd /opt/dockge
$ curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml
$ echo $?
0
$ cat compose.yaml
services:
dockge:
image: louislam/dockge:1
restart: unless-stopped
ports:
# Host Port : Container Port
- 5001:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
# If you want to use private registries, you need to share the auth file with Dockge:
# - /root/.docker/:/root/.docker
# Stacks Directory
# ⚠️ READ IT CAREFULLY. If you did it wrong, your data could end up writing into a WRONG PATH.
# ⚠️ 1. FULL path only. No relative path (MUST)
# ⚠️ 2. Left Stacks Path === Right Stacks Path (MUST)
- /opt/stacks:/opt/stacks
environment:
# Tell Dockge where is your stacks directory
- DOCKGE_STACKS_DIR=/opt/stacks
这就是官方 compose.yaml 的全文。逐项解说:
| 配置项 | 取值 | 解说 |
|---|---|---|
image | louislam/dockge:1 | 滚动标签,跟随 1.x 系列自动更新(当前指向 1.5.0);锁版本可写 louislam/dockge:1.5.0 |
restart: unless-stopped | 重启策略 | 引擎启动时自动拉起面板;手动停止后不再自动重启 |
ports: 5001:5001 | 端口映射 | 左侧宿主端口 : 右侧面板固定监听端口(容器内固定 5001,改映射只改左侧) |
volumes: /var/run/docker.sock:/var/run/docker.sock | 服务引擎套接字 | 面板的控制命脉:dockge 借此调用引擎 API 完成栈的部署/启停/删除。这也是安全模型的要点——能登录面板,等同于掌握该主机服务引擎的全部控制权 |
volumes: ./data:/app/data | 数据目录 | 存放用户账号、JWT 密钥等元数据(SQLite 数据库文件 dockge.db);备份这里即备份账号体系 |
volumes: /opt/stacks:/opt/stacks | 栈目录挂载 | 栈文件"真身"所在;官方注释连用三个 ⚠️ 强调:必须绝对路径、两侧路径必须完全一致 |
environment: DOCKGE_STACKS_DIR=/opt/stacks | 栈目录声明 | 告诉面板去哪里找栈;必须与上面的栈目录挂载保持一致 |
# - /root/.docker/:/root/.docker | (注释状态)私有仓库凭据 | 需要部署私有仓库中的服务实例时取消注释,让面板读取宿主机的登录凭据 |
官方注释里反复强调的"两侧路径必须完全一致"值得再解释一次:面板进程内部以 /opt/stacks 这条路径读写栈文件,如果宿主机把栈目录挂到容器内其他路径(比如 /app/stacks),面板写出的文件与宿主机上看到的路径就会错位,最坏情况数据写进错误路径。所以官方示例里宿主侧与容器侧都是 /opt/stacks,环境变量也是同一个值,三处一致。
3.2 追加显式网段
官方 compose.yaml 未指定网络网段,Compose 会随机从默认地址池里挑一个。为了网段可控(2.2 已复核 10.89.26.0/24 可用),在文件末尾追加显式网段声明:
$ printf '\nnetworks:\n default:\n ipam:\n config:\n - subnet: 10.89.26.0/24\n' >> compose.yaml
$ tail -7 compose.yaml
- DOCKGE_STACKS_DIR=/opt/stacks
networks:
default:
ipam:
config:
- subnet: 10.89.26.0/24
这段配置把该编排文件的默认网络固定为 10.89.26.0/24,部署后网络名为 dockge_default("项目名_default",项目名取目录名 dockge)。若读者的 2.2 预检发现规划网段已被占用,换一个网段再执行本步。
3.3 校验并启动
先用 docker compose config 校验配置文件语法(--quiet 只报错不打印渲染结果):
$ docker compose config --quiet
$ echo $?
0
退出码 0、无任何报错输出,说明 compose.yaml 语法与结构合法。随后启动:
$ docker compose up -d
Image louislam/dockge:1 Pulling
6e909acdb790 Pulling fs layer 0B
d714f4673cad Pulling fs layer 0B
be84add755f8 Pulling fs layer 0B
9a8d89ceeab1 Pulling fs layer 0B
a80bf94e51e2 Pulling fs layer 0B
7dec24f91d8e Pulling fs layer 0B
15981effcbf4 Pulling fs layer 0B
1523b165f21c Pulling fs layer 0B
de698ba33720 Pulling fs layer 0B
4d8f84d497cc Pulling fs layer 0B
...
6e909acdb790 Pull complete 0B
d714f4673cad Pull complete 0B
be84add755f8 Pull complete 0B
9a8d89ceeab1 Pull complete 0B
4c07c1809c8e Pull complete 0B
a80bf94e51e2 Pull complete 0B
7dec24f91d8e Pull complete 0B
15981effcbf4 Pull complete 0B
1523b165f21c Pull complete 0B
de698ba33720 Pull complete 0B
4d8f84d497cc Pull complete 0B
Image louislam/dockge:1 Pulled
Network dockge_default Creating
Network dockge_default Created
Container dockge-dockge-1 Creating
Container dockge-dockge-1 Created
Container dockge-dockge-1 Starting
Container dockge-dockge-1 Started
回显显示发布物分层拉取(中间省略号为进度帧,全文约百余行)、网络 dockge_default 创建、服务实例 dockge-dockge-1 创建并启动。首次拉取约 100 MB 量级,国内网络环境若拉取缓慢,可为服务引擎配置镜像加速或代理。
3.4 部署验证
三步验证:网段生效、服务实例健康、启动日志正常。
验证一:网段符合规划。
$ docker network inspect dockge_default --format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}'
dockge_default: 10.89.26.0/24
验证二:服务状态与健康检查。
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
dockge-dockge-1 louislam/dockge:1 "/usr/bin/dumb-init …" dockge 10 seconds ago Up 6 seconds (healthy) 0.0.0.0:5001->5001/tcp, [::]:5001->5001/tcp
状态列显示 Up (healthy)——镜像自带健康检查,面板进程就绪后状态才会转为 healthy;端口列显示宿主 5001 已映射。
验证三:启动日志确认监听。
$ docker logs dockge-dockge-1
2026-10-18T09:06:16Z [SERVER] INFO: Welcome to dockge!
2026-10-18T09:06:16Z [SERVER] INFO: NODE_ENV: production
2026-10-18T09:06:16Z [SERVER] INFO: Server Type: HTTP
2026-10-18T09:06:16Z [SERVER] INFO: Data Dir: ./data/
2026-10-18T09:06:16Z [DB] WARN: ENOENT: no such file or directory, open 'data/db-config.json'
2026-10-18T09:06:16Z [DB] INFO: Database Type: sqlite
2026-10-18T09:06:16Z [SERVER] INFO: Connected to the database
2026-10-18T09:06:16Z [SERVER] INFO: JWT secret is not found, generate one.
2026-10-18T09:06:16Z [SERVER] INFO: Stored JWT secret into database
2026-10-18T09:06:16Z [SERVER] INFO: No user, need setup
2026-10-18T09:06:16Z [SERVER] INFO: Listening on 5001
逐行解读:首次启动时数据目录为空,db-config.json 不存在属预期(WARN 后随即自动初始化);数据库类型 SQLite;JWT 密钥首次启动自动生成并入库;No user, need setup 表示尚无账号,首次打开页面会进入初始化流程;最后一行确认已监听 5001。
最后从服务器本机做一次 HTTP 探活,确认页面可访问:
$ curl -i --max-time 8 http://127.0.0.1:5001/ | head -14
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1189 100 1189 0 0 246k 0 --:--:-- --:--:-- --:--:-- 290k
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 1189
ETag: W/"4a5-SVnoSvukidEz28P8zL4V4Udn8mY"
Date: Sun, 18 Oct 2026 09:06:25 GMT
Connection: keep-alive
Keep-Alive: timeout=5
<!DOCTYPE html>
<html lang="en">
HTTP/1.1 200 OK 且返回 HTML 文档,面板服务正常。至此部署完成,浏览器访问 http://<服务器IP>:5001 即可打开界面(会先进入初始化页,见第四章)。
3.5 等价 docker run 形态
不使用 Compose 的读者可以用一条 docker run 命令达到完全相同的部署效果,参数与 3.1 节的 compose.yaml 逐项对应:
docker run -d \
--name dockge \
--restart unless-stopped \
-p 5001:5001 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/dockge/data:/app/data \
-v /opt/stacks:/opt/stacks \
-e DOCKGE_STACKS_DIR=/opt/stacks \
louislam/dockge:1
实测回显(输出为容器长 ID):
313bfea0454a1f82028a363f3f5dfd9e1d8a29ce227ed594ac53b2a4929874c2
参数与 compose.yaml 的对应关系:
| docker run 参数 | compose.yaml 对应项 | 说明 |
|---|---|---|
--restart unless-stopped | restart: unless-stopped | 重启策略,语义完全一致 |
-p 5001:5001 | ports: - 5001:5001 | 宿主端口 : 容器固定监听端口 |
-v /var/run/docker.sock:/var/run/docker.sock | volumes 第 1 项 | 服务引擎套接字,面板的控制命脉 |
-v /opt/dockge/data:/app/data | volumes: ./data:/app/data | 数据目录;compose 的 ./data 相对部署目录即 /opt/dockge/data,此处落绝对路径等价 |
-v /opt/stacks:/opt/stacks | volumes: - /opt/stacks:/opt/stacks | 栈目录,两侧路径必须一致(3.1 的 ⚠️ 说明同样适用) |
-e DOCKGE_STACKS_DIR=/opt/stacks | environment: DOCKGE_STACKS_DIR=/opt/stacks | 面板的栈目录声明,与栈目录挂载保持一致 |
启动后用同样的方式验证:
docker ps --filter name=dockge --format "{{.Names}} {{.Status}}"
curl -s -o /dev/null -w "%{http_code}\n" -m 10 http://127.0.0.1:5001/
实测回显:
dockge Up 12 seconds (healthy)
200
状态带 healthy 标记、HTTP 返回 200,与 Compose 形态部署后的行为完全一致。两种形态如何选:单机单面板、命令行维护为主选 docker run 简洁直接;需要把面板部署纳入版本化配置文件(compose.yaml 入库、随环境复制)或后续要追加网络/资源限制等编排能力时选 Compose——两者挂载与端口语义相同,切换形态只需停掉旧容器并保留 /opt/dockge/data 与 /opt/stacks 两个目录,账号与栈数据不丢失。
四、首次初始化与账号创建
dockge 的账号体系在首次访问时初始化:不存在任何用户时,页面强制进入 setup(初始化)页,创建的第一个用户自动成为管理员。
先用命令行确认初始化页可访问(GET /setup 返回 200):
$ curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 http://127.0.0.1:5001/setup
200
在浏览器打开 http://<服务器IP>:5001,页面会显示 "Create your admin account"(创建管理员账号)表单,依次填写:
- 用户名:admin
- 邮箱:admin@example.com
- 密码 / 重复密码:q1w2e3r4
提交后即完成管理员创建并直接进入面板主界面。
初始化过程也可以完全用 API 实测验证(便于脚本化部署或排查界面问题)。dockge 的前后端通过 Socket.IO 通道通信,服务端提供 setup 事件完成账号创建。实测过程如下(在服务器本机用 Node.js 脚本调用,节点环境仅用于演示 API 行为,与部署无关):
$ node step1-setup.mjs
connected id: NbWvLG6tov1VN7-tAAAB
setup => {"ok":true,"msg":"successAdded","msgi18n":true}
服务端返回 {"ok":true,"msg":"successAdded"}("已成功添加"),与管理员创建成功对应。重复执行同一注册会返回"用户名已存在"类错误,因此该接口仅在无用户或用户名未占用时成功。
创建成功后,登录接口签发 JWT 会话令牌。实测 login 事件:
$ node step2-login.mjs
login => {"ok":true,"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaCI6IjNjMDk2OTRmMzI3NTg0Mjg3ODU0NDdkNDJlOWE3ZmZmIiwiaWF0IjoxNzkyMzE0MzkwfQ.yroRFI_7Mil_0Wq271VNkfku1SJscRfycj-9VZGlurA"}
返回的 token 即 JWT(头部 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 解码为 {"alg":"HS256","typ":"JWT"},载荷含用户名 admin 与角色 admin)。浏览器界面登录后同样持有该令牌,后续会话以此续期。
用该令牌验证会话有效性(loginByToken 事件),再拉取一次栈列表确认面板数据通道正常:
$ node step3-verify.mjs
connected: knm9VK2ATHzYhCeaAAAH
loginByToken => {"ok":true}
requestStackList => {"ok":true,"msg":"Updated","msgi18n":true}
loginByToken 返回 {"ok":true} 说明令牌有效;requestStackList 返回 {"ok":true,"msg":"Updated"}(此时 /opt/stacks 为空,列表为空属正常)。至此账号与会话全部就绪,Web 界面可用 admin / q1w2e3r4 登录。
⚠️ 安全提示:生产环境请使用强密码并避免将 5001 端口直接暴露公网;dockge 持有服务引擎完全控制权(见 3.1 配置解说),公网暴露前应叠加反向代理认证、防火墙白名单等措施。
五、创建第一个栈
本章在面板里完整走一遍栈的创建与部署:创建一个名为 demo-stack 的演示栈(单服务 nginx,映射 8080 端口),验证 dockge 的文件式管理机制与部署链路。
5.1 栈的创建方式
dockge 中创建栈有两条等价路径:
- 界面创建:主界面右侧栈名输入框填入
demo-stack,点击 "+ Compose"——面板自动创建/opt/stacks/demo-stack/目录并打开编辑器; - 文件先行:直接在服务器上创建
/opt/stacks/demo-stack/compose.yaml,回到面板刷新,栈列表自动识别(这就是官方"不会绑架你的 compose 文件"的意义——已有存量栈目录可无缝纳管)。
无论哪种路径,面板编辑器保存的内容都会落盘为 /opt/stacks/demo-stack/compose.yaml,与服务器上手工创建完全等价。本章采用界面创建。
5.2 编写 compose.yaml 并部署
在编辑器中写入以下内容(单服务 nginx,8080 端口对外):
services:
web:
image: nginx:alpine
restart: unless-stopped
ports:
- "8080:80"
点击 Deploy(部署)按钮。面板立即把 YAML 写入磁盘,并在页面下方实时滚动部署终端输出。实测捕获的部署过程如下(终端流节选,ANSI 控制符已清理):
[+] Running 0/9
⠋ web [⠀⠀⠀⠀⠀⠀⠀⠀] Pulling 2.5s
⠸⠼ web [⣿⣿⣿⠀⠀⠀⠀⠀] Pulling 3.5s
⠴ web [⣿⣿⣿⣿⠀⠀⠀⠀] Pulling 3.6s
⠦ web [⣿⣿⣿⣿⣿⠀⠀⠀] Pulling 3.7s
⠧ web [⣿⣿⣿⣿⣿⣿⠀⠀] Pulling 3.9s
⠋ web [⣿⣿⣿⣿⣿⣿⣿⠀] 8.483MB / 28.8MB Pulling 4.2s
⠸ web [⣿⣿⣿⣿⣿⣿⣿⣀] 14.87MB / 28.8MB Pulling 4.4s
⠦ web [⣿⣿⣿⣿⣿⣿⣿⣤] 18.71MB / 28.8MB Pulling 4.7s
⠧ web [⣿⣿⣿⣿⣿⣿⣿⣿] 28.8MB / 28.8MB Pulling 5.8s
✔ web Pulled 5.8s
[+] Running 2/2
✔ Network demo-stack_default Created 0.0s
✔ Container demo-stack-web-1 Started 0.3s
可以清晰看到面板做的是标准 Compose 动作:先拉取 nginx:alpine(分 9 层,合计 28.8 MB),再创建栈专属网络 demo-stack_default,最后启动服务实例 demo-stack-web-1。部署完成时接口返回 {"ok":true,"msg":"Deployed"},栈列表中 demo-stack 状态变为绿色(运行中)。
服务可用性验证——本机探活 8080 端口:
$ curl -sI --max-time 5 http://127.0.0.1:8080/ | head -4
HTTP/1.1 200 OK
Server: nginx/1.31.7
Date: Sun, 18 Oct 2026 09:09:02 GMT
Content-Type: text/html
返回 200 且 Server: nginx/1.31.7,演示栈服务正常对外提供。
5.3 栈文件落盘验证
部署成功后回到服务器命令行,验证"面板操作 = 磁盘文件"这一核心机制:
$ ls -la /opt/stacks/demo-stack/
total 12
drwxr-xr-x 2 root root 4096 Oct 18 09:08 .
drwxr-xr-x 3 root root 4096 Oct 18 09:08 ..
-rw-r--r-- 1 root root 98 Oct 18 09:08 compose.yaml
$ cat /opt/stacks/demo-stack/compose.yaml
services:
web:
image: nginx:alpine
restart: unless-stopped
ports:
- "8080:80"
面板里编辑保存的 YAML 原样落盘为 98 字节的 compose.yaml。此时读者可以随手用 docker compose ls(或 docker ps)从命令行看到同样的服务实例——两边操作的是同一批编排对象,这就是文件式管理的价值。若栈定义了环境变量,面板还会在同级目录落盘 .env 文件(本例未定义,故无该文件)。
六、栈生命周期操作
面板对每个栈提供四个主要操作按钮:Restart(重启)、Stop(停止)、Start(启动)、Down(关闭),以及危险操作 Delete(删除)。它们的底层命令行语义与实测结果对照如下:
| 面板操作 | 底层 Compose 语义 | 服务实例 | 网络 | 栈文件 | 实测接口返回 |
|---|---|---|---|---|---|
| Deploy | compose up -d --remove-orphans | 创建/更新并启动 | 创建 | 写盘 | {"ok":true,"msg":"Deployed"} |
| Start | compose start | 启动已存在的实例 | 重建(若已删) | 保留 | {"ok":true,"msg":"Started"} |
| Restart | compose restart | 重启 | 不变 | 保留 | {"ok":true,"msg":"Restarted"} |
| Stop | compose stop | 停止(实例保留) | 保留 | 保留 | {"ok":true,"msg":"Stopped"} |
| Down | compose down --remove-orphans | 移除 | 移除 | 保留 | {"ok":true,"msg":"Downed"} |
| Delete | Down 后删除栈目录 | 移除 | 移除 | 删除 | {"ok":true,"msg":"Deleted"} |
其中最容易混淆的是 Down 与 Delete:Down 只回收运行态(服务实例与网络),compose.yaml 仍在磁盘上,随时 Start 恢复;Delete 则连栈目录一起删除,不可恢复(面板会弹出确认框)。以下为实测记录。
Restart 实测——操作后用命令行确认服务实例确实被重建:
$ node restart.mjs demo-stack
restartStack => {"ok":true,"msg":"Restarted","msgi18n":true}
$ docker ps --filter name=demo-stack --format '{{.Names}} {{.Status}}'
demo-stack-web-1 Up 3 seconds
Up 3 seconds 说明实例刚被重启(而非延续之前的运行时长),与 Restart 语义一致。
Stop 实测——停止后探活应失败,实例保留为 Exited 状态:
$ node stop.mjs demo-stack
stopStack => {"ok":true,"msg":"Stopped","msgi18n":true}
$ curl -s -o /dev/null -w "%{http_code}\n" --max-time 3 http://127.0.0.1:8080/
000
$ docker ps -a --filter name=demo-stack --format '{{.Names}} {{.Status}}'
demo-stack-web-1 Exited (0) 2 seconds ago
探活返回 000(连接失败)符合预期;Exited (0) 表示正常退出、实例对象仍在。
Start 实测——从停止状态恢复服务:
$ node start.mjs demo-stack
startStack => {"ok":true,"msg":"Started","msgi18n":true}
$ curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 http://127.0.0.1:8080/
200
Down 实测——运行态被回收,栈文件保留:
$ node down.mjs demo-stack
downStack => {"ok":true,"msg":"Downed","msgi18n":true}
$ ls /opt/stacks/demo-stack/
compose.yaml
$ docker ps -a --filter name=demo-stack --format '{{.Names}} {{.Status}}'
$ docker network ls --filter name=demo-stack --format '{{.Name}}'
docker ps -a 与 docker network ls 均无输出——服务实例与栈网络都被移除,但 compose.yaml 完好。此后再次 Start,面板会基于栈文件重建网络与服务实例(实测重新拉起后探活恢复 200)。
💡 技术拓展:面板操作后栈列表状态实时刷新(Socket.IO 推送,无需手动刷新页面)。面板内栈状态值与运行态对应:3 = 运行中(有活跃服务实例)、0 = 未激活(无任何实例)、1 = 非托管/退出态。面板显示状态与服务器真实状态始终保持一致,因为它就是按引擎实时查询的——即使你绕过面板用命令行操作了栈,面板下一次刷新也会如实反映(详见《dockge 日常运维手册》第 2.4 节的一致性实测)。
七、终端与日志功能
面板的终端与日志是排障时最常用的功能,本章说明各自的能力边界与一个重要的版本行为变化(1.5.0 起 Console 默认禁用)。
服务实例日志:栈详情页每个服务旁有日志入口,查看该服务实例的标准输出(等效 docker logs -f <服务实例>)。本例 demo-stack 部署后,面板日志面板实时滚动 nginx 启动输出(/docker-entrypoint.sh: ...、nginx/1.31.7 等行)。
服务实例终端:栈详情页可进入单个服务实例的交互式 shell(等效 docker exec -it <服务实例> sh)。nginx:alpine 这类精简基础包内可用命令有限,但 ls、cat 等排障常用命令均可用。
主机 Console 终端:面板还提供一个直接落在宿主机 shell 的交互式终端(Console),可执行任意命令。由于它等同于把宿主机 shell 开在网页里,官方在 1.5.0 起默认禁用该功能(1.5.0 Release Notes Breaking change:出于安全原因 Console 默认禁用),需要显式加环境变量开启。
实测未开启时的行为(面板调用的服务端接口直接返回拒绝):
$ node console-check.mjs
mainTerminal => {"ok":false,"msg":"Console is not enabled.","msgi18n":true}
在部署文件的环境变量段追加 DOCKGE_ENABLE_CONSOLE=true 后重建:
environment:
- DOCKGE_STACKS_DIR=/opt/stacks
- DOCKGE_ENABLE_CONSOLE=true
$ docker compose up -d
Container dockge-dockge-1 Running
Container dockge-dockge-1 Started
$ sleep 5 && curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 http://127.0.0.1:5001/
200
重建后再次调用,Console 打开成功:
$ node console-check.mjs
mainTerminal => {"ok":true}
此时面板左下角出现 Console 入口,打开即是宿主机 shell。确认面板版本与该行为对应:
$ docker exec dockge-dockge-1 node -e "console.log('dockge', require('./package.json').version)"
dockge 1.5.0
升级或新部署后若发现"Console/终端入口不见了",先检查这个环境变量——这是 1.5.0 的预期行为而非故障。
八、常见问题
本章收录部署阶段实测遇到的三类典型问题:端口冲突、配置校验错误、以及删不掉的"坏栈"。全部给出实测的复现方式与解决过程。
8.1 5001 端口被占用怎么办
现象:docker compose up -d 时报 Bind for 0.0.0.0:5001 failed: port is already allocated,或部署成功但浏览器无法访问。
处理:把宿主端口顺延为 5002(容器内端口固定 5001 不动,只改映射左侧)。实测完整过程:
$ sed -i 's/ - 5001:5001/ - 5002:5001/' /opt/dockge/compose.yaml
$ grep 5002 /opt/dockge/compose.yaml
- 5002:5001
$ cd /opt/dockge && docker compose up -d
Container dockge-dockge-1 Starting
Container dockge-dockge-1 Started
$ sleep 6 && curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 http://127.0.0.1:5002/
200
5002 探活 200,顺延生效。使用完毕改回 5001 再 docker compose up -d 重建即可恢复(实测改回后探活同样 200)。注意顺延后浏览器访问地址也要用新端口;若前面还有反向代理,同步改代理上游。
8.2 compose.yaml 校验错误的三种实测案例
面板保存/部署时会做两层校验:YAML 语法层(编辑器与服务端解析)与编排语义层(Compose 校验)。故意构造三种典型错误实测面板的报错表现。
案例一:YAML 层错误——用 Tab 缩进(YAML 标准禁止 Tab 缩进):
services:
web:
image: nginx:alpine
ports:
- "8081:80"
第 4 行 ports: 前是一个 Tab 字符。点部署后面板直接拒绝,错误信息定位精确:
deployStack => {"ok":false,"msg":"Tabs are not allowed as indentation at line 4, column 1:\n\n image: nginx:alpine\n\tports:\n^\n","msgi18n":true}
报错文案明确指出"第 4 行第 1 列不允许 Tab 缩进"并附上下文片段。这类错误不会落盘、不会创建栈,改回空格缩进即可。
案例二:语义层错误——宿主端口越界(端口号必须 1–65535,写 70000):
services:
web:
image: nginx:alpine
ports:
- "70000:80"
面板返回 {"ok":false,"msg":"Failed to deploy, please check the terminal output for more information."},具体错误在部署终端里。同源错误在服务器命令行复现,报错文本为:
$ cd /opt/stacks/bad-port-stack && docker compose up -d
invalid hostPort: 70000
$ docker compose config
invalid hostPort: 70000
案例三:语义层错误——非法 restart 策略(合法值只有 no/always/on-failure/unless-stopped,写成 maybe):
services:
web:
image: nginx:alpine
restart: maybe
面板同样返回"Failed to deploy, please check the terminal output",终端与命令行的具体报错:
$ cd /opt/stacks/bad-restart-stack && docker compose up -d
service:web:1 Error response from daemon: invalid restart policy: unknown policy 'maybe'; use one of 'no', 'always', 'on-failure', or 'unless-stopped'
Error response from daemon: invalid restart policy: unknown policy 'maybe'; use one of 'no', 'always', 'on-failure', or 'unless-stopped'
三类案例的共性结论:面板的报错分为"直接拒绝"(YAML 层,含精确行列定位)与"部署失败看终端"(语义层,终端里是引擎返回的原始错误)。排查时善用部署终端输出,比界面提示信息多得多。写好 compose.yaml 后先用 docker compose config(无参数即可渲染校验)在命令行预检一遍,是避免这类错误的快捷习惯。
8.3 "坏栈"删不掉:删除失败的实测与解决
接 8.2 案例二:端口越界的 bad-port-stack 虽然部署失败,但栈目录已落盘,面板栈列表里能看到它。此时点 Delete(删除)会失败:
deleteStack(bad-port-stack) => {"ok":false,"msg":"Failed to delete, please check the terminal output for more information."}
原因:删除操作的第一步是对栈执行 Down(compose down),而栈文件本身有错误(invalid hostPort),Down 同样过不了校验,于是整个删除流程中断。
解决方案:先修正栈文件使校验通过,再删除。实测——把越界端口 70000 改为 8081 后,从面板删除成功:
$ sed -i 's/70000/8081/' /opt/stacks/bad-port-stack/compose.yaml
$ grep -A1 'ports:' /opt/stacks/bad-port-stack/compose.yaml | tail -1
- "8081:80"
deleteStack(bad-port-stack) => {"ok":true,"msg":"Deleted"}
$ ls /opt/stacks/
demo-stack
作为对照,8.2 案例三的 bad-restart-stack(restart 值非法)虽也无法部署,但其错误发生在服务实例创建阶段(网络已建、实例未建),Down 能正常完成,因此面板删除一次成功({"ok":true,"msg":"Deleted"})。两者的差异印证了:删除是否成功,取决于栈文件能否通过 Compose 校验。遇到删不掉的栈,优先修文件再删;极端情况下也可在服务器上手工 docker compose down(修正错误后)再删除目录。
九、参考链接
- dockge 官方主页(含 compose.yaml 在线生成器):https://dockge.kuma.pet
- dockge 源码仓库与 README(安装章节):https://github.com/louislam/dockge
- dockge 1.5.0 Release Notes(Console 默认禁用等变更):https://github.com/louislam/dockge/releases/tag/1.5.0
- dockge 官方发布页(louislam/dockge):https://hub.docker.com/r/louislam/dockge
- Docker Compose 官方文档(config/up/down 语义参考):https://docs.docker.com/compose/
- 平台认知篇:《dockge 1.5.0 介绍与选型指南》(版本核实、架构与选型对比)
- 平台运维篇:《dockge 日常运维手册》(巡检、备份、升级、栈迁移与排障)