Inboxen 2026.2.22.0.27.49 Docker Compose 部署指南
Inboxen 2026.2.22.0.27.49 官方无镜像、Docker Compose 自建镜像部署实测:多阶段构建 Web 镜像、五服务栈编排、Postfix 收信网关 chroot 与 transport 排障、telnet SMTP 端到端投信验证。
Inboxen 2026.2.22.0.27.49 Docker Compose 部署指南
目标:用 Docker Compose 一键拉起 Inboxen 2026.2.22.0.27.49 的完整服务栈(Web + PostgreSQL + Redis + Nginx + Postfix 收信链路),完成首次启动、管理员登录、收件箱创建与 telnet SMTP 端到端投信验证。本文全部命令与输出均为实测记录。
一、环境信息
| 项目 | 值 |
|---|---|
| 宿主操作系统 | Debian GNU/Linux 12.15 (bookworm),内核 6.1.0-37-amd64 |
| Docker | Engine 29.1.3 + Compose v5.6.1 |
| Inboxen 版本 | 2026.2.22.0.27.49(Codeberg 官方 PyPI 索引最新包) |
| 基础镜像 | python:3.12-slim(Web)、debian:12-slim(Postfix) |
| 组件镜像 | postgres:16-alpine、redis:7-alpine、nginx:alpine |
| Compose 项目名 | inboxen-2026.2.22-stack(name: 显式声明) |
| 宿主端口 | 8131 → Nginx 80(Web 入口)、8132 → Postfix 25(SMTP 入口) |
| 收信域名 | inboxen.lan |
| 管理员账号 | admin / q1w2e3r4 |
| 实测日期 | 2026-10-26 |
💡 端口说明:Inboxen 常规部署约定 Web 走 8128、SMTP 走 8129;本实验宿主机上这两个端口已被其它进程占用,故实测改用 8131/8132。读者环境空闲时可直接改回,仅影响
compose.yaml里两处ports:映射。
二、官方镜像实查结论与自建方案
动手前先确认「有没有官方镜像可拉」。2026-10-26 实查结论:
- 官方没有发布任何容器镜像:官方代码仓(
https://codeberg.org/Inboxen/Inboxen)仓库内无 Dockerfile、无 compose 编排;README 的安装路径只有源码与 pip 包两种;官方文档 Getting Started / The Setting File 两篇均未提及容器部署。 - Docker Hub 上的
crazymax/inboxen是第三方社区镜像,且最后推送停留在 2019-07-15(deploy-20190609标签,Docker Hub API 实查),与当前版本 2026.2.22.0.27.49 相差近七年,不可用。
因此本文自建镜像:Web 服务用多阶段构建(builder 阶段装编译工具与 Inboxen 包,final 阶段只带运行时依赖),Postfix 收信网关用 Debian 官方包。整栈五个服务全部显式声明在一份 compose.yaml 中。
💡 技术拓展:为什么 Web 镜像要选
python:3.12-slim而不是 alpine?Inboxen 依赖 psycopg2(PostgreSQL 适配),该包在 PyPI 上以 C 扩展 sdist 形式发布(实测 PyPI 无 cp312 预编译 wheel),安装时需要 gcc + PostgreSQL 开发头文件现场编译;musl libc(alpine)下编译链路差异大、坑多,Debian slim 基因与本文 B1 篇《Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南》实测环境一致,排障结论可直接复用。
三、栈架构与工作目录
五个服务的协作关系(与物理机部署完全同构,只是每块职责各占一个服务):
外部发件方
│ SMTP (宿主 8132 → postfix:25)
▼
postfix 服务(inboxen-2026222-stack-postfix)
│ transport 表: inboxen.lan → smtp:[web]:8823
▼
web 服务(inboxen-2026222-stack-web)
├─ Gunicorn :8000 ← Django Web 应用(inboxen.wsgi)
├─ Salmon :8823 ← SMTP 收信管道(inboxen.router)
├─ Celery worker + beat ← 异步任务(渲染/搜索/清理)
│ │
▼ ▼
postgres 服务 redis 服务
(业务数据) (Celery broker)
▲
│ HTTP (宿主 8131 → nginx:80 → web:8000)
nginx 服务(反代 + /static/ 静态资源)
工作目录组织(本实验位于 /opt/inboxen-compose/,读者可任选):
/opt/inboxen-compose/
├── compose.yaml # 栈编排:5 服务 + 4 卷
├── Dockerfile # Web 镜像(多阶段构建)
├── settings_prod.py # Django settings 覆盖模块(Salmon 监听地址)
├── entrypoint.sh # web 首启初始化 + 进程编排
├── inboxen.config # Inboxen 主配置(挂载进 web)
├── nginx.conf # Nginx 反代配置
└── postfix/
├── Dockerfile # Postfix 网关镜像
└── start.sh # Postfix 收信域/transport 启动脚本
四、Web 镜像:Dockerfile 与配套文件
4.1 Dockerfile(多阶段构建)
# syntax=docker/dockerfile:1
# 多阶段构建:builder 阶段装编译工具并安装 Inboxen,final 阶段只带运行时依赖
FROM python:3.12-slim AS builder
# gcc 编译 psycopg2(PyPI 上为纯 sdist,无预编译 wheel)需要三件套:
# gcc + libpq-dev(pg_config/头文件)+ libc6-dev(gcc 的 Recommends 依赖,
# --no-install-recommends 下必须显式装,否则报 stdlib.h: No such file or directory)
RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc libpq-dev libc6-dev \
&& rm -rf /var/lib/apt/lists/*
# Inboxen 官方包发布在项目自建的 Codeberg PyPI 索引,依赖来自公共 PyPI,双源安装
RUN pip install --prefix=/install "inboxen==2026.2.22.0.27.49" \
--index-url https://pypi.org/simple \
--extra-index-url https://codeberg.org/api/packages/inboxen/pypi/simple/ \
&& pip install --prefix=/install setuptools redis gunicorn django-debug-toolbar
FROM python:3.12-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends libpq5 \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /install /usr/local
WORKDIR /app
COPY settings_prod.py entrypoint.sh /app/
RUN chmod +x /app/entrypoint.sh
# DJANGO_SETTINGS_MODULE 指向覆盖模块(官方 settings.py 头部注释认可的定制方式):
# 仅把 Salmon 收信监听地址从 localhost 改为 0.0.0.0,供栈内 Postfix 服务转发
ENV DJANGO_SETTINGS_MODULE=settings_prod \
SALMON_SETTINGS_MODULE=inboxen.router.config.settings \
PYTHONPATH=/app
EXPOSE 8000 8823
ENTRYPOINT ["/app/entrypoint.sh"]
三个实测要点:
libc6-dev必须显式安装:--no-install-recommends会跳过 gcc 的 Recommends 依赖,实测首次构建在编译 psycopg2 时报fatal error: stdlib.h: No such file or directory,补上后一次通过。- 四个补装包各有用途:
setuptools(Python 3.12 无 distutils,依赖链 django-bootstrap-form 需要)、redis(Celery Redis broker 传输包,缺了 worker 起不来)、gunicorn(WSGI 服务器)、django-debug-toolbar(本教程 HTTP 模式下 debug 模式必需)。 - 双源 pip 安装:Inboxen 官方包在 Codeberg 自建 PyPI 索引,依赖在公共 PyPI,缺一不可。
4.2 settings_prod.py:让 Salmon 监听对外网卡
Inboxen 默认 SALMON_SERVER = {"host": "localhost", "port": 8823},单机物理部署够用;compose 栈里 Postfix 在另一个服务里,必须监听 0.0.0.0。官方 settings.py 头部注释明确支持「导入后覆盖」的定制方式:
# 按 Inboxen 官方 settings.py 头部注释建议:导入默认 settings 后按需覆盖。
# 本模块只做一件事:让 Salmon SMTP 收信进程监听 0.0.0.0:8823(默认 localhost,
# 在单机部署里足够;compose 栈中 Postfix 在另一个服务里,必须监听对外网卡)。
from inboxen.settings import * # noqa
SALMON_SERVER = {"host": "0.0.0.0", "port": 8823, "type": "smtp"}
生效验证(入栈后执行,实测回显):
from django.conf import settings
print(settings.SALMON_SERVER)
# {'host': '0.0.0.0', 'port': 8823, 'type': 'smtp'}
4.3 entrypoint.sh:首启初始化与进程编排
#!/bin/sh
set -e
cd /app
echo "== [1/3] 初始化数据库与静态资源 =="
inboxen migrate
inboxen collectstatic --noinput
echo "== [2/3] 引导管理员与收信域名(幂等,已存在则跳过) =="
DJANGO_SUPERUSER_PASSWORD=q1w2e3r4 inboxen createsuperuser --noinput \
--username admin --email admin@inboxen.lan || echo "superuser admin 已存在,跳过"
inboxen createdomain inboxen.lan || echo "domain inboxen.lan 已存在,跳过"
echo "== [3/3] 启动 Celery worker / beat / Salmon,随后前台运行 Gunicorn =="
mkdir -p run logs
celery -A inboxen worker -l warning --events -Ofair -f logs/celery-worker.log &
celery -A inboxen beat -l warning -f logs/celery-beat.log &
# 放后台启动:salmon 的 daemonize 行为随运行环境不稳定,后台方式保证不阻塞 gunicorn
salmon start --pid run/router.pid --boot inboxen.router.config.boot &
sleep 3
exec gunicorn inboxen.wsgi -b 0.0.0.0:8000 --workers 2 --access-logfile - --error-logfile -
⚠️ 实测踩坑:
salmon start阻塞入口脚本。Salmon 的--daemon/--no-daemon虽默认 daemon,但实测在同一命令行下其 daemonize 行为随环境不稳定——本栈首次启动时入口脚本停在salmon start一行、Gunicorn 始终未拉起(Nginx 返回 502)。改为后台启动(&)后无论其是否内部守护都不阻塞,问题消失。这是自建镜像编排 Inboxen 的关键一坑。
五、Inboxen 主配置 inboxen.config
pip 包形态下 inboxen 命令以工作目录下的 inboxen.config 为配置源,本栈把它以只读卷挂进 web 服务的 /app:
debug: true
secret_key: "b2-compose-experiment-026-1nboxen-key"
database:
host: "postgres"
name: "inboxen"
user: "inboxen"
password: "q1w2e3r4"
port: "5432"
tasks:
broker_url: "redis://redis:6379/0"
enable_registration: true
enable_inbox_creation: true
allowed_hosts:
- "*"
cache:
location: "/app/cache"
| 字段 | 本栈取值 | 说明 |
|---|---|---|
database.host | postgres | compose 服务名即 DNS 名,服务间互访直接用服务名 |
tasks.broker_url | redis://redis:6379/0 | 同上;单机栈用 Redis 兼任 broker 最简 |
debug | true | 生产模式内置 SECURE_SSL_REDIRECT=True,纯 HTTP 入口会 301 跳 https 导致打不开站点;实验栈保持 true,生产请置 false 并上 TLS |
cache.location | /app/cache(绝对路径) | 默认值是相对路径,Django 启动告警 caches.W003;挂了命名卷后写绝对路径消除告警 |
allowed_hosts | ["*"] | 仅限实验;生产写实际域名 |
六、Postfix 收信网关镜像
6.1 postfix/Dockerfile
FROM debian:12-slim
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends postfix \
&& rm -rf /var/lib/apt/lists/*
COPY start.sh /start.sh
RUN chmod +x /start.sh
EXPOSE 25
ENTRYPOINT ["/start.sh"]
6.2 postfix/start.sh
#!/bin/sh
set -e
# 收信域:inboxen.lan(允许任意外部来源投往该域,缺省会被 554 Relay access denied 拒收)
postconf -e "relay_domains = ${RELAY_DOMAINS}"
# transport 表:该域全部转交 web 服务的 Salmon 收信进程(8823 端口)。
# 注意 [web] 必须加方括号:不带括号 Postfix 会按 MX 查询主机名,容器内必失败
printf '%s smtp:[web]:8823\n' "${RELAY_DOMAINS}" > /etc/postfix/transport
postmap /etc/postfix/transport
postconf -e "transport_maps = hash:/etc/postfix/transport"
# 日志直写 stdout,docker compose logs postfix 即可排障(Postfix >= 3.4 支持)
postconf -e "maillog_file = /dev/stdout"
# Debian 的 Postfix smtp 投递进程默认 chroot 到 /var/spool/postfix 运行,
# 必须把 DNS/名称解析配置拷进 chroot,否则 transport 目标主机名解析失败(deferred 4.4.3)
mkdir -p /var/spool/postfix/etc
cp /etc/resolv.conf /etc/services /var/spool/postfix/etc/
[ -f /etc/nsswitch.conf ] && cp /etc/nsswitch.conf /var/spool/postfix/etc/
exec postfix start-fg
两个实测踩坑都集中在这份脚本里:
- transport 目标必须写
smtp:[web]:8823(带方括号)。实测写成smtp:web:8823时 Postfix 对web做 MX 查询,投递报status=deferred (Name service error for name=web type=MX: Host not found);加方括号后走 A/AAAA 直查。 - Debian Postfix 的 chroot DNS 坑。即使加了方括号,实测仍报
type=AAAA: Host not found——根因是 Debian 的 smtp 投递进程默认 chroot 到/var/spool/postfix,而 Docker 注入的/etc/resolv.conf(nameserver 127.0.0.11)没有同步进 chroot。补cp /etc/resolv.conf ... /var/spool/postfix/etc/后立刻恢复。修正后的投递日志:
postfix-1 | Oct 26 06:13:05 localhost postfix/smtp[112]: 04016208745: to=<fmcvdl@inboxen.lan>, relay=web[172.19.0.4]:8823, delay=3.1, delays=3/0.01/0.04/0.04, dsn=2.0.0, status=sent (250 OK)
七、compose.yaml 栈编排
name: inboxen-2026.2.22-stack
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: inboxen
POSTGRES_USER: inboxen
POSTGRES_PASSWORD: q1w2e3r4
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U inboxen -d inboxen"]
interval: 5s
timeout: 3s
retries: 20
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 20
web:
build: .
volumes:
- ./inboxen.config:/app/inboxen.config:ro
- static_content:/app/static_content
- inboxen_media:/app/media_content
- inboxen_cache:/app/cache
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- static_content:/app/static_content:ro
ports:
- "8131:80"
depends_on:
- web
postfix:
build: ./postfix
environment:
RELAY_DOMAINS: inboxen.lan
ports:
- "8132:25"
depends_on:
- web
volumes:
pgdata:
static_content:
inboxen_media:
inboxen_cache:
配套 nginx.conf(静态资源由命名卷直接服务,动态请求反代到 web):
server {
listen 80;
server_name _;
location /static/ {
alias /app/static_content/;
}
location / {
proxy_pass http://web:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
编排要点:
| 设计 | 说明 |
|---|---|
name: inboxen-2026.2.22-stack | 显式项目名,栈资源(网络/服务名/镜像名前缀)全部挂在该名字下;compose 会把名称中的 . 规范化,实际镜像名为 inboxen-2026222-stack-web/inboxen-2026222-stack-postfix(见第八节 docker compose images 实测回显) |
| postgres/redis 带 healthcheck | web 的 depends_on.condition: service_healthy 保证数据库就绪后才执行 migrate,避免首启竞态 |
| static_content 命名卷 | web 内 collectstatic 写入,nginx 只读挂载同一卷直接对外服务 |
| Salmon 端口 8823 不对外发布 | 收信管道只接受栈内 postfix 转发,不暴露宿主 |
| Gunicorn 前台运行 | exec 作为 1 号进程,docker compose stop web 能正确收尾 |
八、启动与首启验证
8.1 构建镜像
cd /opt/inboxen-compose
docker compose build
实测回显(尾部):
Image inboxen-2026222-stack-postfix Built
Image inboxen-2026222-stack-web Built
镜像体积实测(docker images):
inboxen-2026222-stack-web 390MB
inboxen-2026222-stack-postfix 188MB
8.2 拉起全栈
docker compose up -d
实测回显(尾部):
Container inboxen-2026222-stack-postgres-1 Healthy
Container inboxen-2026222-stack-redis-1 Healthy
Container inboxen-2026222-stack-web-1 Started
Container inboxen-2026222-stack-nginx-1 Started
Container inboxen-2026222-stack-postfix-1 Started
首次冷启动时 web 会执行完整迁移,docker compose logs web 关键回显(节选):
web-1 | == [1/3] 初始化数据库与静态资源 ==
web-1 | Operations to perform:
web-1 | Apply all migrations: auth, blog, cms, contenttypes, django_celery_results, inboxen, monitor, otp_static, otp_totp, search, sessions, tickets, two_factor
web-1 | Running migrations:
web-1 | Applying contenttypes.0001_initial... OK
web-1 | ...
web-1 | Applying two_factor.0001_squashed_0008_delete_phonedevice... OK
web-1 |
web-1 | 57 static files copied to '/app/static_content'.
web-1 | == [2/3] 引导管理员与收信域名(幂等,已存在则跳过) ==
web-1 | Superuser created successfully.
web-1 | inboxen.lan created!
web-1 | == [3/3] 启动 Celery worker / beat / Salmon,随后前台运行 Gunicorn ==
💡 幂等性说明:
entrypoint.sh里 migrate/createsuperuser/createdomain 都可重复执行——重建 web 服务时迁移为空操作、管理员与域名提示「已存在,跳过」,数据卷不受影响。
8.3 栈状态核查
docker compose ps
docker compose images
实测回显:
SERVICE IMAGE STATUS PORTS
nginx nginx:alpine Up 3 minutes 0.0.0.0:8131->80/tcp, [::]:8131->80/tcp
postfix inboxen-2026222-stack-postfix Up 44 seconds 0.0.0.0:8132->25/tcp, [::]:8132->25/tcp
postgres postgres:16-alpine Up 7 minutes (healthy) 5432/tcp
redis redis:7-alpine Up 7 minutes (healthy) 6379/tcp
web inboxen-2026222-stack-web Up 3 minutes 8000/tcp, 8823/tcp
CONTAINER REPOSITORY TAG PLATFORM IMAGE ID SIZE CREATED
inboxen-2026222-stack-nginx-1 nginx alpine linux/amd64 a3554c0d0b48 93.6MB 4 days ago
inboxen-2026222-stack-postfix-1 inboxen-2026222-stack-postfix latest linux/amd64 30771574da02 188MB 3 minutes ago
inboxen-2026222-stack-postgres-1 postgres 16-alpine linux/amd64 f46107955874 419MB 4 days ago
inboxen-2026222-stack-redis-1 redis 7-alpine linux/amd64 57e4255cc971 57.3MB 4 days ago
inboxen-2026222-stack-web-1 inboxen-2026222-stack-web latest linux/amd64 2f97f2faf8a3 390MB 6 minutes ago
Web 入口可达性:
curl -s -o /dev/null -w '%{http_code}\n' -L http://127.0.0.1:8131/
200
浏览器打开 http://<宿主IP>:8131/,进入 /user/account/login/ 用 admin / q1w2e3r4 登录(登录表单是两步验证向导,第一步只需账号密码)。
九、端到端收信验证
9.1 创建收件箱
登录 Web 后在首页点击 Create an Inbox 亦可;命令行方式(在 web 服务里进 Django shell):
docker compose exec -T web inboxen shell <<'EOF'
from django.contrib.auth.models import User
from inboxen.models import Inbox, Domain
u = User.objects.get(username="admin")
d = Domain.objects.get(domain="inboxen.lan")
i = Inbox.objects.create(domain=d, user=u)
print("INBOX-ADDR:", i.inbox + "@" + d.domain)
EOF
实测回显:
39 objects imported automatically (use -v 2 for details).
INBOX-ADDR: fmcvdl@inboxen.lan
💡 收件箱本地部份由系统按
inbox_length(默认 6 位小写字母)随机生成,无须也不能指定名字;Inbox.objects.create(domain=…, user=…)是官方 QuerySet 管理器提供的标准入口。
9.2 telnet SMTP 投信
在宿主机(或任一能访问宿主 8132 端口的机器)执行,实测完整会话(每步等待上一响应再发下一条):
220 localhost.localdomain ESMTP Postfix (Debian/GNU)
250 localhost.localdomain
250 2.1.0 Ok
250 2.1.5 Ok
354 End data with <CR><LF>.<CR><LF>
250 2.0.0 Ok: queued as 04016208745
221 2.0.0 Bye
对应输入序列:
HELO client.example.net
MAIL FROM:<sender@example.net>
RCPT TO:<fmcvdl@inboxen.lan>
DATA
From: Sender <sender@example.net>
To: fmcvdl@inboxen.lan
Subject: Hello From Compose
This message arrived through the Docker Compose stack.
.
QUIT
⚠️ 与 B1 篇同一时序坑:DATA 正文必须以单独一行
.结束,且等250 ... queued as ...出现后再发QUIT,否则 Postfix 丢弃会话、信件无痕消失。
9.3 三重验证
① Postfix 投递日志(栈内日志直写 stdout):
docker compose logs postfix | grep 04016208745
实测回显(关键行):
postfix-1 | Oct 26 06:13:05 localhost postfix/smtp[112]: 04016208745: to=<fmcvdl@inboxen.lan>, relay=web[172.19.0.4]:8823, delay=3.1, delays=3/0.01/0.04/0.04, dsn=2.0.0, status=sent (250 OK)
relay=web[172.19.0.4]:8823 说明信件已从 postfix 服务转交 web 服务内的 Salmon。
② Web 端可见:登录后打开 http://<宿主IP>:8131/inbox/fmcvdl@inboxen.lan/,信件列表出现主题 Hello From Compose。命令行验证(先取 CSRF token 走登录表单,再带 Cookie 访问收件箱页):
curl -s -b cookies.txt -L http://127.0.0.1:8131/inbox/fmcvdl@inboxen.lan/ | grep -o "Hello From Compose"
实测回显:
Hello From Compose
③ 数据库落库:
docker compose exec -T web inboxen shell <<'EOF'
from inboxen.models import Email
print("EMAIL-TOTAL:", Email.objects.count())
EOF
实测回显:
EMAIL-TOTAL: 1
十、日常运维操作
# 查看各服务日志(postfix 日志直写 stdout,收信排障首选)
docker compose logs -f web
docker compose logs -f postfix
# 重启单个服务(数据卷保留,重跑幂等初始化)
docker compose restart web
# 升级 Inboxen 版本:改 Dockerfile 里的 inboxen== 版本号后重建
docker compose build web && docker compose up -d web
# 备份数据库
docker compose exec postgres pg_dump -U inboxen inboxen > inboxen-backup.sql
# 停栈(保留数据卷)
docker compose down
# 停栈并删除全部数据卷(彻底清空,含 PostgreSQL 业务数据)
docker compose down -v
十一、常见排障
| 现象 | 根因 | 处置 |
|---|---|---|
web 构建报 fatal error: stdlib.h: No such file or directory(编译 psycopg2 时) | --no-install-recommends 跳过了 gcc 的 libc6-dev | builder 阶段显式 apt-get install libc6-dev |
Nginx 返回 502,web 日志停在 salmon start 无 Gunicorn 输出 | salmon 的 daemonize 行为随环境不稳定,阻塞了入口脚本 | entrypoint 里 salmon start … & 后台启动 |
投递报 status=deferred (… name=web type=MX: Host not found) | transport 目标 smtp:web:8823 未加方括号,Postfix 按 MX 查询 | 写成 smtp:[web]:8823 |
投递报 status=deferred (… name=web type=AAAA: Host not found),方括号已加 | Debian Postfix smtp 进程 chroot 运行,chroot 内无 resolv.conf | start.sh 里把 /etc/resolv.conf、/etc/services、/etc/nsswitch.conf 拷入 /var/spool/postfix/etc/ |
| 纯 HTTP 访问 301 跳 https | 生产模式(debug 关闭)内置 SECURE_SSL_REDIRECT=True | 实验栈保持 debug: true;生产上 TLS 终结 |
| 重建 postfix 后旧信一直不投 | deferred 队列在容器文件系统里,未持久化 | 数据面在 web 侧无影响;让发件方重投即可,或在 start.sh 给 /var/spool/postfix 挂卷持久化 |
ports: 报 port is already allocated | 宿主端口被占用 | 换空闲端口(本文实测即因 8128/8129 被占改用 8131/8132) |
web 起不来,celery worker 报 'NoneType' object has no attribute 'Redis' | Redis broker 传输包未装 | 镜像内 pip install redis(本文 Dockerfile 已内置) |
| 页面样式全丢、/static/ 404 | static_content 卷未挂到 nginx,或 collectstatic 未执行 | 核对两个服务的卷挂载与 entrypoint 的 collectstatic 步骤 |
十二、卸载
cd /opt/inboxen-compose
docker compose down -v # 停栈、删网络与数据卷
docker rmi inboxen-2026222-stack-web inboxen-2026222-stack-postfix # 删自建镜像
# postgres:16-alpine / redis:7-alpine / nginx:alpine / python:3.12-slim / debian:12-slim
# 为基础镜像,若其它组件仍使用则保留
十三、参考链接
- 官方代码仓:
https://codeberg.org/Inboxen/Inboxen(2026-10-26 查询) - 官方配置文档:
https://inboxen.readthedocs.io/en/latest/settings.html(2026-10-26 查询) - 官方 Getting Started:
https://inboxen.readthedocs.io/en/latest/getting_started.html(2026-10-26 查询) - 站内关联:《Inboxen 2026.2.22.0.27.49 介绍与选型指南》、《Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南》