Ajenti Docker Compose 部署指南
Ajenti 2.2.18 官方无容器镜像的 Docker Compose 自建部署全记录:python:3.11-bookworm 基底加官方 21 插件 pip 清单、entrypoint 首启初始化与自签证书、8129 端口发布、命名卷配置持久化、down/up 数据保留验证与 pip 限速排障实录(Ubuntu 22.04 + Docker 29.9.2 实测,2026-11-02)。
Ajenti Docker Compose 部署指南
目标:在一台 Ubuntu 22.04 服务器上,用 Docker Compose 从零构建并部署 Ajenti 2.2.18 管理面板(官方无容器镜像,本篇给出完整自建方案),完成 HTTPS 访问、root 登录、配置与日志持久化、down/up 数据保留与反代路径等全链路实测。已在 Ubuntu 22.04(x86_64)+ Docker Engine 29.9.2 + Compose v5.6.1 实测通过。
Ajenti 是 Linux & BSD 的模块化服务器管理面板(定位、架构与选型见《Ajenti 介绍与选型指南》)。它的官方安装形态是"主机 pip 安装 + systemd 托管",不提供官方 Docker 镜像,因此容器化部署的全部工作量在于:把官方文档的依赖清单与 pip 安装清单翻译成一个可复现的 Dockerfile。本篇即完成这件事,并把它固化为一条 docker compose up 命令。
一、环境信息
| 项目 | 取值 |
|---|---|
| 服务器操作系统 | Ubuntu 22.04(x86_64) |
| Docker Engine / Compose | 29.9.2 / v5.6.1(docker compose 子命令) |
| Ajenti 版本 | ajenti-panel 2.2.18(PyPI 最新稳定版,2026-10-25 发布;GitHub Release 标签为 v2.2.15,pip 通道更新更快) |
| 面板基础镜像 | python:3.11-bookworm(自建,Debian 12 底) |
| 项目目录 | /opt/ajenti-2.2.18/(Dockerfile、entrypoint.sh、config.yml、docker-compose.yml、data/logs/) |
| Compose 项目名 | ajenti-2.2.18-stack |
| 服务名 / 主机名 | ajenti / ajenti-demo |
| 监听 | 面板 HTTPS 8000(服务内)→ 宿主发布 8129 |
| 内部网络 | user-defined bridge ajenti-2218-stack_ajenti-net(compose 把项目名 ajenti-2.2.18-stack 归一化为资源前缀 ajenti-2218-stack_),网段 10.89.56.0/24,固定地址 10.89.56.10 |
| 配置持久化 | 命名卷 ajenti-2218-stack_ajenti-config → 服务内 /etc/ajenti |
| 日志持久化 | 宿主 bind /opt/ajenti-2.2.18/data/logs → 服务内 /var/log/ajenti |
| 演示账号 | root / q1w2e3r4(os 认证,即系统口令) |
💡 说明:Ajenti 默认监听 8000 端口且默认启用 HTTPS(自签证书)。本方案把宿主端口显式规划为 8129,避开 8000 的常见冲突;服务内端口保持 8000 不动,与官方文档所有示例路径一致。
二、镜像选型说明
Ajenti 官方不发容器镜像(2026-11-02 实查:GitHub Releases 仅有源码包,PyPI 仅有 pip 包,Docker Hub 无 ajenti 官方组织)。因此镜像只能自建。自建方案里真正要选的是"基底 + 依赖来源":
| 选型项 | 本方案取值 | 理由 |
|---|---|---|
| 基底镜像 | python:3.11-bookworm | 官方支持 Debian 9+;bookworm(Debian 12)的 python3-apt、python3-augeas 等系统绑定包齐全,与官方 apt 依赖清单一一对应 |
| Ajenti 本体 | pip 安装 ajenti-panel 2.2.18 | 官方推荐的安装通道(docs install.rst),版本随 PyPI 滚动 |
| 插件集 | 官方"全插件"清单 21 个 ajenti.plugin.* | docs install.rst "With all plugins" 原文清单,覆盖终端/文件/cron/服务/软件包等全部功能域 |
| 系统绑定 | apt 安装 python3-apt、python3-augeas、python3-dbus + .pth 桥接 | packages/augeas/dbus 插件必须 import 发行版自带的系统绑定,pip 版 Python 默认看不到 dist-packages,需显式加路径 |
⚠️ 注意:基底不要选
python:3.11-slim或滚动到 Debian 13(trixie)标签的变体——trixie 已移除python3-apt等 Python 3.11 时代的系统绑定包,apt 依赖层会直接失败。本系列实验早期在 slim/trixie 上实测撞墙后固定为 bookworm。
💡 技术拓展:面板类软件容器化的三条常见路线——
路线 做法 取舍 官方镜像直用 docker run官方发布镜像最省事,但 Ajenti 没有 自建 pip 镜像 官方 pip 清单 + 系统依赖装入 Debian 基底(本方案) 与官方文档同源、可复现、版本可控 社区第三方镜像 Docker Hub 个人维护的 ajenti 镜像 版本陈旧(多停留在 1.x/2.0 时代)、无人维护,不建议生产使用 本方案采用"自建 pip 镜像",因为它是唯一与官方安装文档保持依赖一致性的路线。
三、前置条件
- 服务器已安装 Docker Engine 与 Compose v2+ 插件:
docker --version && docker compose version
回显(实测):
Docker version 29.9.2, build a82e528
Docker Compose version v5.6.1
- 宿主 8129 端口空闲:
ss -ltn | grep ':8129 ' || echo "8129 free"
- 服务器可直连 PyPI 与 deb.debian.org(构建期下载依赖;无法直连的环境见 4.6 节代理构建参数与 11.1 排障实录);
- 磁盘余量 ≥ 2GB(构建后镜像实测大小见 4.6 节回显)。
四、部署步骤
4.1 建立项目目录
所有部署文件集中在一个目录,compose 的相对路径构建上下文与 bind 挂载都以它为根:
mkdir -p /opt/ajenti-2.2.18/data/logs
cd /opt/ajenti-2.2.18
目录规划:
/opt/ajenti-2.2.18/
├── docker-compose.yml # 编排:构建、端口、网络、持久化
├── Dockerfile # 自建面板镜像定义
├── entrypoint.sh # 首启初始化(配置落盘 + 自签证书)+ 前台启动
├── config.yml # 默认主配置(构建时打进镜像,首启复制到持久卷)
└── data/logs/ # 宿主侧日志目录(bind 进 /var/log/ajenti)
4.2 编写 Dockerfile
/opt/ajenti-2.2.18/Dockerfile 全文如下(每段对应官方文档的一个安装步骤):
FROM python:3.11-bookworm
ENV DEBIAN_FRONTEND=noninteractive
# 官方 Debian/Ubuntu 依赖清单 + 运行时工具(对应 docs install.rst 手动安装一节)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential libssl-dev libffi-dev \
libaugeas0 augeas-tools python3-augeas \
python3-apt python3-dbus \
dbus sudo vim-tiny nano procps iproute2 net-tools \
curl git ca-certificates less cron ntpdate \
&& rm -rf /var/lib/apt/lists/*
# 让 pip 版 python 能 import apt/apt_pkg/augeas(Debian 系统包位于 dist-packages)
RUN echo '/usr/lib/python3/dist-packages' > /usr/local/lib/python3.11/site-packages/dist-packages.pth
# 可选构建参数:内网/慢链环境构建时传 --build-arg PIP_PROXY=http://<proxy>:<port>
ARG PIP_PROXY=""
# 可选构建参数:国内环境传 --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
ARG PIP_INDEX_URL=""
RUN pip install --no-cache-dir ${PIP_PROXY:+--proxy ${PIP_PROXY}} ${PIP_INDEX_URL:+-i ${PIP_INDEX_URL}} setuptools pip wheel -U
# 官方"全插件"安装清单(docs install.rst)
RUN pip install --no-cache-dir ${PIP_PROXY:+--proxy ${PIP_PROXY}} ${PIP_INDEX_URL:+-i ${PIP_INDEX_URL}} \
ajenti-panel \
ajenti.plugin.ace \
ajenti.plugin.augeas \
ajenti.plugin.auth-users \
ajenti.plugin.core \
ajenti.plugin.dashboard \
ajenti.plugin.datetime \
ajenti.plugin.filemanager \
ajenti.plugin.filesystem \
ajenti.plugin.network \
ajenti.plugin.notepad \
ajenti.plugin.packages \
ajenti.plugin.passwd \
ajenti.plugin.plugins \
ajenti.plugin.power \
ajenti.plugin.services \
ajenti.plugin.settings \
ajenti.plugin.terminal \
ajenti.plugin.cron \
ajenti.plugin.supervisor \
ajenti.plugin.session-list
# 演示账号口令(os 认证走系统口令)
RUN echo 'root:q1w2e3r4' | chpasswd
COPY config.yml /opt/ajenti-default-config.yml
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
EXPOSE 8000
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
逐段说明:
- apt 依赖层:
build-essential/libssl-dev/libffi-dev编译cryptography、lxml等 sdist 依赖;augeas-tools/libaugeas0/python3-augeas支撑 augeas 插件;python3-apt支撑 packages 插件;sudo支撑auth.allow_sudo提权模型;vim-tiny/nano/procps/iproute2让面板内的终端、文件编辑、服务管理开箱可用。 .pth桥接:pip 安装的 Python 3.11 与发行版系统 Python 的包目录(/usr/lib/python3/dist-packages)互不可见,写入.pth文件后import apt_pkg、import augeas才能成功——这是 Ajenti 容器化最容易踩的坑(见 11.3 节)。ARG PIP_PROXY/ARG PIP_INDEX_URL:两个可选构建参数默认空串不启用;${VAR:+--flag ${VAR}}写法保证仅在传参时拼出对应 pip 选项,镜像内不留任何代理/源残留。国内网络构建强烈建议传清华源(见 4.6 与 11.1)。chpasswd:Ajenti 默认认证 provider 是os(直接校验系统口令),演示环境把 root 口令设为q1w2e3r4。生产环境应改为provider: users自建账号体系(详见配置篇)。
4.3 编写 entrypoint.sh
服务进程需要一个"首启初始化 + 前台常驻"的入口,/opt/ajenti-2.2.18/entrypoint.sh:
#!/bin/bash
set -e
mkdir -p /etc/ajenti /var/log/ajenti
if [ ! -f /etc/ajenti/config.yml ]; then
cp /opt/ajenti-default-config.yml /etc/ajenti/config.yml
echo "[entrypoint] initial config.yml created"
fi
if [ ! -f /etc/ajenti/ajenti.pem ]; then
ajenti-ssl-gen "$(hostname)"
echo "[entrypoint] self-signed certificate generated"
fi
exec ajenti-panel -c /etc/ajenti/config.yml
- 首启把镜像内置默认配置复制进持久卷
/etc/ajenti,此后卷内文件优先,升级重建镜像不会覆盖你改过的配置; - 首启用官方工具
ajenti-ssl-gen以主机名签一张自签证书/etc/ajenti/ajenti.pem(对应官方文档"缺证书就登录空白页"的补救命令); exec ajenti-panel -c ...让面板进程作为 1 号进程前台运行,docker stop能把 SIGTERM 正确传给它。
4.4 默认主配置 config.yml
/opt/ajenti-2.2.18/config.yml——这份文件会被打进镜像作为"出厂配置",完整参数含义见 《Ajenti 2.2.18 配置参数详解》:
auth:
allow_sudo: true
emails: {}
provider: os
users_file: /etc/ajenti/users.yml
bind:
host: 0.0.0.0
mode: tcp
port: 8000
color: bluegrey
language: en
max_sessions: 9
session_max_time: 3600
trusted_domains: []
trusted_proxies: []
name: Ajenti Demo Server
restricted_user: nobody
ssl:
certificate: ''
client_auth:
certificates: []
enable: false
force: false
enable: true
force: false
fqdn_certificate: ''
email:
enable: false
smtp:
password: ''
port: ''
server: ''
user: ''
要点:bind.host: 0.0.0.0 + bind.port: 8000(服务内监听)、ssl.enable: true(HTTPS)、auth.provider: os(系统账号登录)、language: en(官方仓库默认值是 ru,部署时必须显式改掉)。
💡 说明:出厂
ssl.certificate: ''故意留空——首启由ajenti-ssl-gen生成自签证书后把路径回写进卷内配置(见 4.8 节日志的config.yml updated with certificate path!行)。各参数逐项含义见配置篇。
4.5 编写 docker-compose.yml
/opt/ajenti-2.2.18/docker-compose.yml 全文:
name: ajenti-2.2.18-stack
services:
ajenti:
build: .
image: ajenti-2.2.18-panel:local
container_name: ajenti-2.2.18-panel
hostname: ajenti-demo
ports:
- "8129:8000"
volumes:
- ajenti-config:/etc/ajenti
- /opt/ajenti-2.2.18/data/logs:/var/log/ajenti
networks:
ajenti-net:
ipv4_address: 10.89.56.10
restart: unless-stopped
networks:
ajenti-net:
driver: bridge
ipam:
config:
- subnet: 10.89.56.0/24
volumes:
ajenti-config:
字段解读:
| 字段 | 取值 | 作用 |
|---|---|---|
name | ajenti-2.2.18-stack | 显式项目名,down 只影响本组件资源 |
build / image | . / ajenti-2.2.18-panel:local | 本地构建并固定标签,便于 docker run 等价复现 |
container_name | ajenti-2.2.18-panel | 固定名,便于 exec/logs |
hostname | ajenti-demo | 首启 ajenti-ssl-gen $(hostname) 的证书 CN |
ports | 8129:8000 | 宿主 8129 → 服务内 8000 |
volumes | 命名卷 + bind | /etc/ajenti 配置持久化;data/logs 日志落宿主 |
networks | 10.89.56.0/24,固定 IP | 显式网段规划,避免与既有网络冲突 |
restart | unless-stopped | 宿主机重启后面板自动拉起 |
4.6 构建镜像
cd /opt/ajenti-2.2.18
docker compose build --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
构建输出节选(实测首尾):
Image ajenti-2.2.18-panel:local Building
#1 [internal] load local bake definitions
#1 reading from stdin 602B done
#1 DONE 0.0s
#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 2.24kB done
#2 DONE 0.0s
#3 [internal] load metadata for docker.io/library/python:3.11-bookworm
#3 DONE 0.2s
...
#15 DONE 18.2s
#16 resolving provenance for metadata file
#16 DONE 0.0s
Image ajenti-2.2.18-panel:local Built
构建完成后核对产物:
docker images ajenti-2.2.18-panel
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
ajenti-2.2.18-panel:local dcc98dd37504 1.87GB 457MB U
(Docker 29 的 docker images 以 DISK USAGE/CONTENT SIZE 两列展示共享与独占占用;本镜像独占层 457MB、含共享层总占用 1.87GB,与"磁盘余量 ≥ 2GB"的前置要求吻合。)
⚠️ 注意:
ajenti.plugin.*系列在 PyPI 上只发 sdist(源码包),21 个插件 + 依赖全部要现场解包构建 wheel,正常耗时 10–20 分钟;若中途超时按 11.1 节处理。
4.7 启动服务栈
docker compose up -d
回显(实测):
Network ajenti-2218-stack_ajenti-net Creating
Volume ajenti-2218-stack_ajenti-config Creating
Volume ajenti-2218-stack_ajenti-config Creating
Network ajenti-2218-stack_ajenti-net Creating
Volume ajenti-2218-stack_ajenti-config Created
Volume ajenti-2218-stack_ajenti-config Created
Network ajenti-2218-stack_ajenti-net Created
Network ajenti-2218-stack_ajenti-net Created
Container ajenti-2.2.18-panel Creating
Container ajenti-2.2.18-panel Created
Container ajenti-2.2.18-panel Starting
Container ajenti-2.2.18-panel Started
查看运行状态与端口发布:
docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
ajenti-2.2.18-panel ajenti-2.2.18-panel:local "/usr/local/bin/entr…" ajenti Less than a second ago Up Less than a second 0.0.0.0:8129->8000/tcp, [::]:8129->8000/tcp
4.8 验证启动日志
docker compose logs ajenti
回显(实测):
[entrypoint] initial config.yml created
:: Certificate /etc/ajenti/ajenti.pem generated!
:: /etc/ajenti/config.yml updated with certificate path!
[entrypoint] self-signed certificate generated
(ajenti-ssl-gen 执行时伴随大量 pyOpenSSL DeprecationWarning 行,属预期噪音,已滤除;成功标志即上面两条 :: 行。)
面板进程自身的日志不写 stdout 而是落 /var/log/ajenti/ajenti.log(宿主 bind 目录 data/logs/),首启就绪序列(实测节选):
2026-11-02 14:57:45,077 INFO : Ajenti Core 2.2.18
2026-11-02 14:57:45,077 INFO : Master PID - 1
2026-11-02 14:57:45,077 INFO : Detected platform: debian / Linux 7.0.0-38-generic x86_64
2026-11-02 14:57:45,077 INFO : Python version: 3.11.18
2026-11-02 14:57:45,092 INFO : Discovered 20 plugins
2026-11-02 14:57:45,097 WARNING : Not loading [supervisor] because dependency failed: BinaryDependency (supervisorctl)
2026-11-02 14:57:45,166 INFO : Loaded 19 plugins
2026-11-02 14:57:45,166 INFO : Binding to [0.0.0.0]:8000
2026-11-02 14:57:45,170 INFO : No secret found, generating new secret key
2026-11-02 14:57:45,174 INFO : SSL enabled
Binding to [0.0.0.0]:8000 + SSL enabled 为面板主进程就绪标志;Not loading [supervisor] 一条 WARNING 属预期——镜像未装 supervisorctl,需要管理 supervisor 服务时再补装。
4.9 验证 HTTPS 访问与登录
curl -kIs https://localhost:8129/ | head -8
HTTP/1.1 302 Found
X-Auth-Identity:
Location: /view/login/normal
X-Worker-Name: restricted session
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self';
Date: Mon, 02 Nov 2026 14:58:17 GMT
Content-Length: 0
未登录访问根路径即 302 跳转登录页;登录页本体 curl -ks -o /dev/null -w '%{http_code}\n' https://localhost:8129/view/login/normal 返回 200。
登录接口实测(os 认证,root / q1w2e3r4):
curl -ks -c /tmp/ajcjB -o /tmp/ajbodyB -X POST https://localhost:8129/api/core/auth \
-H 'Content-Type: application/json' \
-d '{"mode":"normal","username":"root","password":"q1w2e3r4"}'
cat /tmp/ajbodyB
curl -ks -X POST https://localhost:8129/api/core/auth \
-H 'Content-Type: application/json' \
-d '{"mode":"normal","username":"root","password":"bad"}'
curl -kb /tmp/ajcjB -s https://localhost:8129/api/core/identity
{"success": true, "username": "root"}
{"success": false, "error": null}
{"identity": {"user": "root", "uid": 0, "effective": 0, "elevation_allowed": true, "profile": {}}, "machine": {"name": "Ajenti Demo Server", "hostname": "ajenti-demo"}, "color": "bluegrey"}
正确口令返回 success: true 并下发会话 Cookie;错误口令返回 success: false;带 Cookie 调 /api/core/identity 确认登录态与面板标题。
浏览器访问 https://<服务器IP>:8129,信任自签证书后用 root / q1w2e3r4 登录,即可看到 Dashboard/配置/终端/软件包等页面。
五、数据持久化说明
| 服务内路径 | 内容 | 持久化方式 | 宿主/卷位置 |
|---|---|---|---|
/etc/ajenti/config.yml | 主配置 | 命名卷 ajenti-2218-stack_ajenti-config | 卷内 |
/etc/ajenti/users.yml | provider: users 时的面板用户库 | 同上 | 卷内 |
/etc/ajenti/ajenti.pem | 自签 HTTPS 证书 | 同上 | 卷内 |
/etc/ajenti/smtp.yml | 邮件中继凭据(找回密码用) | 同上 | 卷内 |
/var/log/ajenti/ajenti.log | 运行日志与失败登录记录 | bind | /opt/ajenti-2.2.18/data/logs/ |
/var/log/ajenti/crash-*.txt | 崩溃栈(实测命名 crash-<日期>-<时刻>h<分>.txt,官方文档写 crash-DATE.log,以代码为准) | bind | 同上 |
持久化验证——重建栈后配置不丢:
docker compose down
docker compose up -d
grep -c 'initial config.yml created' data/logs/ajenti.log # 首启标记不新增 = 卷内配置未重初始化
curl -k -s -o /dev/null -w '%{http_code}\n' https://localhost:8129/
Container ajenti-2.2.18-panel Removing
Container ajenti-2.2.18-panel Removed
Network ajenti-2218-stack_ajenti-net Removing
Network ajenti-2218-stack_ajenti-net Removed
Container ajenti-2.2.18-panel Created
Container ajenti-2.2.18-panel Starting
Container ajenti-2.2.18-panel Started
0
after up: 302
down 不带 -v 时命名卷保留,重建容器后首启初始化标记不再新增(计数 0),配置、证书、会话密钥全部原样恢复。
💡 说明:Ajenti 无内置数据库,全部状态就是这几个 YAML/PEM 文件;备份
/etc/ajenti卷即备份整个面板配置。导出方法见第十章。
六、环境变量与构建参数说明
Ajenti 面板进程不读取环境变量,配置唯一来源是 /etc/ajenti/config.yml(这是它与 1Panel 等"环境变量驱动"面板的关键差异)。本镜像涉及的环境变量/构建参数只有:
| 名称 | 位置 | 默认值 | 说明 |
|---|---|---|---|
DEBIAN_FRONTEND | 构建期 ENV | noninteractive | 仅 apt 无人值守用 |
PIP_PROXY | 构建 ARG | 空(不启用) | --build-arg PIP_PROXY=http://<proxy>:<port> 时为 pip 指定代理,不进镜像 |
PIP_INDEX_URL | 构建 ARG | 空(官方源) | --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple 换国内源,不进镜像 |
TZ | 可选 ENV | UTC | 容器时区;面板 datetime 插件读写的是系统时区,建议宿主与容器一致 |
💡 技术拓展:容器化应用的配置注入两条主流路线——
路线 代表 特点 环境变量驱动 imgproxy、多数 Go 服务 十二要素、compose environment:即可改配置文件挂载 Ajenti、多数传统 Linux 服务 需挂载配置目录 + 首启初始化(本方案的 entrypoint/volume 设计即为此) Ajenti 属于后者,所以本方案用"镜像带出厂配置 + 命名卷存运行配置"的组合,而不是 env 覆盖。
七、配置参数说明(速览)
出厂 config.yml 各块含义速览(逐项详解、修改方法与生效验证见 《Ajenti 2.2.18 配置参数详解》):
| 块/键 | 本方案取值 | 一句话含义 |
|---|---|---|
auth.provider | os | 登录账号来源:系统账号(另一选项 users 面板自管) |
auth.allow_sudo | true | 允许 sudo 组成员在面板内提权 |
bind.host/port | 0.0.0.0:8000 | 监听地址与端口 |
ssl.enable | true | HTTPS(证书 /etc/ajenti/ajenti.pem) |
session_max_time | 3600 | 会话有效期(秒) |
max_sessions | 9 | 同时在线会话上限 |
language | en | 界面语言(官方默认 ru,必须显式改) |
restricted_user | nobody | 受限操作降权用户 |
八、配置文件挂载方式
运行期配置在命名卷内,修改走"进服务改文件 + 重启进程":
docker compose exec ajenti sed -i 's/^name: Ajenti Demo Server/name: Ajenti Ops Demo/' /etc/ajenti/config.yml
docker compose restart
curl -ks -c /tmp/rj -X POST https://localhost:8129/api/core/auth -H 'Content-Type: application/json' -d '{"mode":"normal","username":"root","password":"q1w2e3r4"}'
curl -kb /tmp/rj -s https://localhost:8129/api/core/identity
{"identity": {"user": "root", "uid": 0, "effective": 0, "elevation_allowed": true, "profile": {}}, "machine": {"name": "Ajenti Ops Demo", "hostname": "ajenti-demo"}, "color": "bluegrey"}
改回原值并重启即恢复稳态。面板 Settings 页改标题/主题色等参数写回的是同一个文件,效果相同(参数逐项详解见配置篇)。
entrypoint 只在 /etc/ajenti/config.yml 不存在时才复制出厂配置,因此卷内文件永远优先,升级镜像不会覆盖修改。
若更希望"配置即代码"(宿主 git 管理),可把主配置改为 bind 单文件挂载:
# docker-compose.yml volumes 段的替代写法(二选一)
volumes:
- ajenti-config:/etc/ajenti
- ./config.yml:/etc/ajenti/config.yml:ro # 宿主文件直接接管主配置
⚠️ 注意:单文件 bind 后
config.yml变只读,面板内 Settings 页保存会失败(写入方是进程本身);需要面板内改配置时去掉:ro或回到命名卷方案。
九、等价 docker run
compose 的运行时等价命令(同镜像、同持久化语义,仅网络用默认 bridge 演示):
docker run -d --name ajenti-run-demo -p 8131:8000 ajenti-2.2.18-panel:local
e9e5944c1d3907b23b9f446ddf8709b4be83d7efb305f2e05228552bbcb2923e
run-demo 8131: 302
[entrypoint] initial config.yml created
:: Certificate /etc/ajenti/ajenti.pem generated!
:: /etc/ajenti/config.yml updated with certificate path!
[entrypoint] self-signed certificate generated
(run-demo 8131: 302 为 curl -k -s -o /dev/null -w '%{http_code}' https://localhost:8131/ 的实测输出;其余为 docker logs ajenti-run-demo 节选。)
验证完毕销毁该演示实例:
docker rm -f ajenti-run-demo
ajenti-run-demo
十、常用运维命令
| 操作 | 命令 |
|---|---|
| 状态 | docker compose ps |
| 跟踪日志 | docker compose logs -f ajenti |
| 重启面板 | docker compose restart |
| 进入服务 | docker compose exec ajenti bash |
| 停止并删除栈(保留数据卷) | docker compose down |
| 连数据一起销毁 | docker compose down -v |
| 改 Dockerfile 后重建并拉起 | docker compose up -d --build |
| 导出配置备份 | docker run --rm -v ajenti-2218-stack_ajenti-config:/etc/ajenti -v "$(pwd)":/backup alpine tar czf /backup/ajenti-etc.tar.gz /etc/ajenti |
实测节选(配置备份导出):
docker run --rm -v ajenti-2218-stack_ajenti-config:/etc/ajenti -v "$(pwd)":/backup alpine \
tar czf /backup/ajenti-etc.tar.gz /etc/ajenti
ls -la ajenti-etc.tar.gz
tar: removing leading '/' from member names
-rw-r--r-- 1 root root 4466 Nov 2 23:01 ajenti-etc.tar.gz
全部配置状态仅 4.4KB(五个 YAML/PEM 文件),还原时把 tar 解回同名卷即可。其余命令回显见 4.7(ps)、五章(down/up)、八章(exec/restart)实测节。
十一、常见问题
11.1 构建期 pip 下载超时/卡死
现象:docker compose build 停在 Downloading ajenti_plugin_core-0.117.tar.gz (17.5 MB) 长时间不动(本篇实验实测在该处卡死 5 分钟以上无字节流动),或最终报 ConnectTimeoutError。
定位:小体积包(几 MB)能过、大包卡死,多为到 files.pythonhosted.org 的链路被限速。本篇实测对照:同一台服务器直连官方源下载该 17.5MB 包仅 302KB/s(20 秒超时窗口只完成 4.5MB),而清华镜像源同包 20.9MB/s 整包秒下:
URL=https://files.pythonhosted.org/packages/30/99/b5af989e33a2f1082a5e7c6dede275aedff351d3871af0167c1d724d8d12/ajenti_plugin_core-0.117.tar.gz
timeout 20 curl -s -o /dev/null -w "official=%{speed_download} B/s size=%{size_download}\n" "$URL"
timeout 20 curl -s -o /dev/null -w "tuna=%{speed_download} B/s size=%{size_download}\n" \
"https://pypi.tuna.tsinghua.edu.cn/packages/30/99/b5af989e33a2f1082a5e7c6dede275aedff351d3871af0167c1d724d8d12/ajenti_plugin_core-0.117.tar.gz"
official=302132 B/s size=4532101
tuna=20883032 B/s size=17513806
解决:构建时传入国内源参数(Dockerfile 已内置支持):
docker compose build --build-arg PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
海外/有代理环境则传 --build-arg PIP_PROXY=http://<proxy>:<port>,两者可同用。
11.2 登录后页面空白
官方文档已知问题:gipc/gevent 版本过旧导致。容器方案按 2.2.18 全新安装不受影响(实测版本核对):
docker compose exec ajenti pip3 show gipc gevent | grep -E '^(Name|Version)'
Name: gipc
Version: 1.8.0
Name: gevent
Version: 25.5.1
若你手动改过依赖导致回落旧版,按官方补救命令升级:pip install gipc gevent -U。
11.3 packages/augeas 插件报 ModuleNotFoundError: No module named 'apt_pkg'
原因:pip 版 Python 看不到 Debian 系统绑定目录。解决:确认 Dockerfile 的 .pth 桥接层存在(4.2 节),验证:
docker compose exec ajenti python3 -c "import apt_pkg, augeas; print('apt_pkg/augeas import ok')"
apt_pkg/augeas import ok
11.4 浏览器证书告警
自签证书属预期行为。生产建议:前置反代挂正式证书(配合 trusted_domains/trusted_proxies/url_prefix,见配置篇),或用 ajenti-client-ssl-gen 走客户端证书方案。
十二、参考链接
- 官方安装文档(依赖清单与 pip 全插件清单出处):https://docs.ajenti.org/en/latest/man/install.html
- 官方运行/排障文档:https://docs.ajenti.org/en/latest/man/run.html
- 官方配置文档:https://docs.ajenti.org/en/latest/man/config.html
- GitHub 仓库:https://github.com/ajenti/ajenti
- PyPI ajenti-panel:https://pypi.org/project/ajenti-panel/ (2.2.18,查询日期 2026-11-02)
- 同系列:《Ajenti 介绍与选型指南》、《Ajenti 2.2.18 配置参数详解》、《Ajenti 2.2.18 常用 CLI 命令与工具详解》