Listmonk 6.2.0 Docker Compose 部署指南

使用 Docker Compose 一键部署 Listmonk 6.2.0:官方镜像三段式启动命令解析、环境变量配置与管理员自动创建、服务状态与日志验证、数据持久化确认、版本升级与卸载清理

ListmonkListmonkDockerDocker ComposeLinuxPostgreSQL2026/10/17

Listmonk 6.2.0 Docker Compose 部署指南

目标:在一台安装了 Docker 与 Docker Compose 的 Linux 服务器上,使用官方镜像与 Docker Compose 一键部署 Listmonk 6.2.0(含 PostgreSQL 17 数据库),覆盖 compose 文件编写、启动、状态与日志验证、管理员账号确认、API 验证、数据持久化确认、版本升级与卸载清理。本文所有命令与回显均在 Listmonk v6.2.0 环境实测通过。

一、环境信息

本文所有命令与回显均在以下环境中实测:

  • 操作系统:Linux x86_64(已安装 Docker 与 Docker Compose 插件)
  • Listmonk 镜像:listmonk/listmonk:v6.2.0
  • 数据库镜像:postgres:17-alpine
  • 服务端口:9000(Listmonk Web 与 API)
  • 演示账号:admin / q1w2e3r4(通过环境变量在首次启动时自动创建)

二、官方部署方案解析

2.1 镜像与组成

官方维护的 Docker 镜像为 listmonk/listmonk,官方仓库根目录提供标准 docker-compose.yml,由两个服务组成:

  • app:Listmonk 主程序,对外暴露 9000 端口;
  • db:PostgreSQL 数据库(官方示例使用 postgres:17-alpine),数据落盘到命名卷。

镜像启动时会打印入口信息(实测日志):

Launching listmonk with user=[root] group=[root] PUID=[0] PGID=[0]

2.2 启动命令三段式

官方 compose 为 app 服务定义的启动命令是三段拼接(实测原文):

command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"]

三段含义:

  1. --install --idempotent --yes:仅当数据库还是空库(首次启动)时执行一次表结构安装,之后自动跳过;
  2. --upgrade --yes:每次启动都执行一次数据库结构升级检查,新版本镜像拉起后自动完成迁移;
  3. --config '':把配置文件路径传空串,表示完全不用配置文件,只从环境变量读取配置。

💡 技术拓展:--config '' 传空串是官方约定:Listmonk 尝试打开名为空串的配置文件失败后,会退化为纯环境变量模式。因此 compose 部署中所有配置都以 LISTMONK_ 前缀环境变量注入(详见第五章),而不是挂载 config.toml。

2.3 机密文件模式

官方镜像支持 LISTMONK_*_FILE 后缀模式加载 Docker secrets / Podman secrets:例如 LISTMONK_ADMIN_USER 对应 LISTMONK_ADMIN_USER_FILE=/path/to/file_with_value,程序会从指定文件读取真实值,避免明文口令出现在编排文件里。

三、部署步骤

3.1 编写 docker-compose.yml

创建部署目录并写入 compose 文件(基于官方结构,镜像 tag 固定为 v6.2.0,并补充了管理员自动创建的环境变量):

mkdir -p /opt/listmonk-compose && cd /opt/listmonk-compose
cat > docker-compose.yml <<'EOF'
x-db-credentials: &db-credentials
  POSTGRES_USER: &db-user listmonk
  POSTGRES_PASSWORD: &db-password listmonk
  POSTGRES_DB: &db-name listmonk

services:
  app:
    image: listmonk/listmonk:v6.2.0
    container_name: listmonk_app
    restart: unless-stopped
    ports:
      - "9000:9000"
    networks:
      - listmonk
    hostname: listmonk.example.com
    depends_on:
      - db
    command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"]
    environment:
      LISTMONK_app__address: 0.0.0.0:9000
      LISTMONK_db__user: *db-user
      LISTMONK_db__password: *db-password
      LISTMONK_db__database: *db-name
      LISTMONK_db__host: db
      LISTMONK_db__port: 5432
      LISTMONK_db__ssl_mode: disable
      LISTMONK_db__max_open: 25
      LISTMONK_db__max_idle: 25
      LISTMONK_db__max_lifetime: 300s
      TZ: Asia/Shanghai
      LISTMONK_ADMIN_USER: admin
      LISTMONK_ADMIN_PASSWORD: q1w2e3r4
    volumes:
      - ./uploads:/listmonk/uploads:rw

  db:
    image: postgres:17-alpine
    container_name: listmonk_db
    restart: unless-stopped
    ports:
      - "127.0.0.1:5432:5432"
    networks:
      - listmonk
    environment:
      <<: *db-credentials
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U listmonk"]
      interval: 10s
      timeout: 5s
      retries: 6
    volumes:
      - type: volume
        source: listmonk-data
        target: /var/lib/postgresql/data

networks:
  listmonk:

volumes:
  listmonk-data:
EOF

说明:

  • x-db-credentials 锚点统一管理数据库账号口令,app 与 db 两处复用;
  • LISTMONK_ADMIN_USER / LISTMONK_ADMIN_PASSWORD:首次以空库启动时自动创建超级管理员,免去网页初始化步骤(演示值 admin/q1w2e3r4,生产请用强口令);
  • db 的 5432 端口只绑定 127.0.0.1,仅本机可连,不暴露公网;
  • ./uploads 挂载到 /listmonk/uploads 用于媒体上传(启用后需在后台 Settings → Media 把上传目录改为 /listmonk/uploads);
  • healthcheck 使用 pg_isready -U listmonk,10 秒间隔、5 秒超时、最多重试 6 次。

3.2 启动服务

docker compose up -d

首次启动会拉取 listmonk/listmonk:v6.2.0 与 postgres:17-alpine 镜像、创建网络 listmonk_listmonk、创建数据卷 listmonk_listmonk-data,然后依次拉起 db 与 app。

3.3 查看服务状态

docker compose ps

实测回显(节选,省略启动时长字段):

NAME           IMAGE                      SERVICE   STATUS                 PORTS
listmonk_app   listmonk/listmonk:v6.2.0   app       Up                     0.0.0.0:9000->9000/tcp
listmonk_db    postgres:17-alpine         db        Up (healthy)           127.0.0.1:5432->5432/tcp

两个服务均 Up,db 的健康检查为 healthy,app 的 9000 端口映射到宿主机所有网卡的 9000。

3.4 检查启动日志

docker compose logs app

实测关键日志(节选):

connecting to db...
running upgrade...
no upgrades to run. Database is up to date.
initialized email (SMTP) messenger: @mailhog
http server started on [::]:9000
  • no upgrades to run. Database is up to date.:--install --idempotent 在空库完成首次安装、--upgrade 检查无待执行迁移;
  • initialized email (SMTP) messenger: @mailhog:内置默认 SMTP 投递通道已初始化(名称 @mailhog,此时指向默认占位 SMTP,实际发信需在后台 Settings 配置,见《快速入门与集成示例》);
  • http server started on [::]:9000:HTTP 服务就绪。

四、部署验证

4.1 Web 登录验证

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9000/

实测回显:

200

浏览器打开 http://<服务器IP>:9000/admin,用环境变量中设置的管理员账号登录(本文演示:admin / q1w2e3r4),能进入管理后台即部署成功。

4.2 API 验证

先创建一个 API 用户(登录后台 Admin → Users 新建类型为 API 的用户,请求体要点为 "type": "api"、"status": "enabled"、"user_role_id": 1),创建成功后响应中的 password 字段即 48 位 API Token。实测创建的演示用户:

{"data":{"id":5,"username":"composeapi","password":"6g9QyvVZFFvcf4LmLuutiU1B3rYw7sNHzth0WvVxF3rsEsNx","name":"Compose API","type":"api","status":"enabled","user_role":{"id":1,"name":"Super Admin","permissions":["campaigns:manage","templates:manage","roles:get","settings:get","settings:manage","subscribers:get_all","campaigns:get_all","campaigns:get_analytics","campaigns:send","bounces:manage","webhooks:post_bounce","media:get","templates:get","subscribers:get","subscribers:import","campaigns:get","campaigns:manage_all","bounces:get","media:manage","users:get","users:manage","lists:get_all","lists:manage_all","roles:manage","settings:maintain","subscribers:manage","subscribers:sql_query","tx:send"]}}}

用 Token 验证 API:

curl -s -o /dev/null -w "%{http_code}\n" -u "composeapi:6g9QyvVZFFvcf4LmLuutiU1B3rYw7sNHzth0WvVxF3rsEsNx" http://localhost:9000/api/lists

实测回显:

200

4.3 数据库表结构确认

首次启动的 --install 已在 PostgreSQL 中建好全部业务表(实测共 16 张,节选):

bounces、campaign_lists、campaign_media、campaign_views、campaigns、
link_clicks、links、lists、media、subscribers、...

可通过 docker exec listmonk_db psql -U listmonk -d listmonk -c '\dt' 自行查看完整表清单。

五、配置项说明

5.1 环境变量逐项

compose 中 app 服务注入的环境变量与 config.toml 配置键一一对应,命名规则为 LISTMONK_段__键(段与键之间是双下划线):

环境变量对应配置键实测值说明
LISTMONK_app__addressapp.address0.0.0.0:9000监听地址,容器内必须 0.0.0.0 才能映射到宿主机
LISTMONK_db__hostdb.hostdbcompose 网络内数据库服务名
LISTMONK_db__portdb.port5432数据库端口
LISTMONK_db__userdb.userlistmonk数据库账号
LISTMONK_db__passworddb.passwordlistmonk数据库口令
LISTMONK_db__databasedb.databaselistmonk数据库名
LISTMONK_db__ssl_modedb.ssl_modedisablecompose 内网直连无需 TLS
LISTMONK_db__max_opendb.max_open25最大连接数
LISTMONK_db__max_idledb.max_idle25最大空闲连接数
LISTMONK_db__max_lifetimedb.max_lifetime300s连接最长存活时间
LISTMONK_ADMIN_USER—(特殊变量)admin首次空库启动自动创建的超管用户名
LISTMONK_ADMIN_PASSWORD—(特殊变量)q1w2e3r4首次空库启动自动创建的超管密码

⚠️ 注意:v6 版本起 SMTP 发信配置不再支持用 LISTMONK_smtp__* 环境变量注入,必须通过后台 Settings 或 Settings API 配置(实测验证与原理解释见《配置参数详解》第六章)。

5.2 docker compose config 渲染确认

用 docker compose config 渲染最终生效的编排配置,可核对环境变量是否按预期注入。实测渲染节选:

name: listmonk
services:
  app:
    environment:
      LISTMONK_ADMIN_PASSWORD: q1w2e3r4
      LISTMONK_ADMIN_USER: admin
      LISTMONK_app__address: 0.0.0.0:9000
      LISTMONK_db__database: listmonk
      LISTMONK_db__host: db
      LISTMONK_db__max_idle: "25"
      LISTMONK_db__max_lifetime: 300s
      LISTMONK_db__max_open: "25"
      LISTMONK_db__password: listmonk
      LISTMONK_db__port: "5432"
      LISTMONK_db__ssl_mode: disable
      LISTMONK_db__user: listmonk
      TZ: Asia/Shanghai
    image: listmonk/listmonk:v6.2.0

5.3 数据卷与网络

docker volume ls

实测回显(节选):

local      listmonk_listmonk-data
docker network ls

实测回显(节选):

listmonk_listmonk   bridge

数据库名卷 listmonk_listmonk-data(默认命名规则为 项目名_卷名)承载全部 PostgreSQL 数据;compose 项目网络 listmonk_listmonk 提供 app 到 db 的服务名解析。

六、数据持久化与重启验证

数据落在命名卷中,重启服务后数据不丢失。实测重启并验证:

docker compose restart

重启完成后再次调用 API(凭据同 4.2 节):

curl -s -o /dev/null -w "%{http_code}\n" -u "composeapi:6g9QyvVZFFvcf4LmLuutiU1B3rYw7sNHzth0WvVxF3rsEsNx" http://localhost:9000/api/lists

实测回显:

200

重启后 API 正常响应、此前创建的数据完整可用,持久化验证通过。

七、常见问题

7.1 修改 LISTMONK_ADMIN_USER/PASSWORD 后管理员没变

这两个变量只在首次以空库启动时生效,用于自动创建超级管理员;数据库初始化完成后,再修改环境变量不会更新已有账号。如需改密码,登录后台 Admin → Users 修改即可。

7.2 媒体上传后文件不在宿主机

compose 已把 ./uploads 挂载到 /listmonk/uploads,但 Listmonk 默认上传目录不是它。需登录后台 Settings → Media,把上传路径改为 /listmonk/uploads 后保存,此后上传的文件才会落到宿主机目录。

7.3 首次启动 app 反复重启

多为数据库未就绪导致。db 服务定义了 pg_isready 健康检查,等待其转为 healthy 后 docker compose restart app 即可;若日志出现数据库连接被拒(connection refused),确认 LISTMONK_db__host 填的是 compose 服务名 db 而不是 localhost。

7.4 9000 端口被占用

将 compose 中 ports 的宿主侧改为其他端口(如 "19000:9000"),重启 compose 后用新端口访问。

八、升级与卸载

8.1 版本升级

官方启动命令中的 --upgrade --yes 保证了升级的自动化:修改 compose 中的镜像 tag 后重建 app 服务即可。以从 v6.1.0 升级到 v6.2.0 为例:

sed -i 's|listmonk/listmonk:v6.1.0|listmonk/listmonk:v6.2.0|' docker-compose.yml
docker compose up -d app

实测升级日志(节选):

2026/10/17 00:35:06.902686 main.go:106: v6.2.0 (ef0a7587 2026-06-26T10:21:29Z, linux/amd64)
2026/10/17 00:35:06.953000 main.go:165: running upgrade...
2026/10/17 00:35:06.957679 upgrade.go:80: running migration v6.2.0
2026/10/17 00:35:06.995526 upgrade.go:98: upgrade complete

upgrade complete 即迁移完成。注意:数据库迁移不会自动回滚——回滚版本需要换回旧镜像 tag 并恢复升级前的数据库备份(备份恢复实操见《进阶实战与运维》)。

8.2 卸载清理

docker compose down

该命令停止并移除两个服务与 compose 网络;数据库名卷 listmonk_listmonk-data 默认保留。如确认不再需要数据,追加 -v 一并删除卷:

docker compose down -v

卸载后可用 docker volume ls 核对卷已不存在,宿主机上的部署目录与 ./uploads 目录按需删除。

九、参考链接