Mathesar 0.12.0 Docker Compose 部署指南
官方 Compose 三服务(应用/内置 PostgreSQL/Caddy)从零部署 Mathesar 0.12.0 全流程:启动与就绪验证实测回显、内置库与外部 PostgreSQL 16 双形态接入、bind mount 持久化与 down/up 销毁性验证、环境变量表、等价 docker run 与运维 FAQ。
Mathesar 0.12.0 Docker Compose 部署指南
目标:用官方 Docker Compose 从零把 Mathesar 0.12.0 跑起来并完成首次安装,覆盖「内置数据库」与「连接外部已有 PostgreSQL」两种形态、数据持久化验证与常用运维。全部步骤与回显均在 Ubuntu 22.04 宿主上实测(Mathesar 0.12.0 + PostgreSQL 17.6 内置库 + PostgreSQL 16.15 外部库)。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64,Linux 5.15)
- Docker:24.x / Compose v2(
docker compose子命令可用) - Mathesar:0.12.0(
mathesar/mathesar:0.12.0,约 2.24 GB) - 反向代理:
mathesar/mathesar-caddy:latest(约 1.65 GB,随官方 compose 一起提供) - 内置数据库:
pgautoupgrade/pgautoupgrade:17-bookworm(约 1.13 GB,提供 PostgreSQL 17.6) - 外部数据库(形态 B 实测用):
postgres:16-alpine(PostgreSQL 16.15) - 网络规划:Compose 默认网络
mathesar-0120-stack-net;Web 入口宿主端口 8128(宿主 80 已被占用,故改映射);外部 PG 映射宿主端口 8129 - 部署目录:
/opt/mathesar/(本文以该路径书写,实测部署即采用该目录布局)
⚠️ 说明:官方 docker-compose.yml 原样使用 80/443 端口与
latest应用 tag。本文为在本机完成实测做了三处本地适配并逐处标注:1) Caddy 宿主端口 80→8128(443 映射移除,因为DOMAIN_NAME使用 http);2) 显式name: mathesar-0120-stack项目名与固定网段;3) 应用镜像 tag 由latest锁定为0.12.0(版本可复现)。读者可按需保留官方原值。
二、镜像选型说明
官方 compose 一共用到三个镜像,均有明确分工:
| 镜像 | 角色 | 说明 |
|---|---|---|
mathesar/mathesar:0.12.0 | 应用服务 | Django + Gunicorn(监听 8000,仅内网 expose,不直接对外),含完整 Web UI 与 JSON-RPC API |
pgautoupgrade/pgautoupgrade:17-bookworm | 内置 PostgreSQL | Mathesar 官方选定的基础库镜像;特色是启动时自动执行大版本升级(17-bookworm 表示 PG 17),承载元数据库 mathesar_django 与(可选的)业务库 |
mathesar/mathesar-caddy:latest | 反向代理 | 内置 Mathesar 专用 Caddyfile,负责 /static/*、/media/* 文件直出与其余流量反代到 mathesar_service:8000,对外暴露 80/443 |
选型要点:应用与 Caddy 镜像均为 Mathesar 官方构建发布;若追求版本锁定,把 mathesar/mathesar-caddy:latest 也固定到与官方 release 对应的 tag(本实测环境沿用 latest,启动正常);pgautoupgrade 镜像的「自动大版本升级」特性适合长期运行的内置库形态。
三、前置条件
- 宿主已安装 Docker 与 Compose v2:
docker compose version能正常输出版本。 - 宿主 80(或你自定义的映射端口,如 8128)未被占用:
ss -ltnp | grep -E ':80 |:8128 '应无输出或非目标进程。 - 磁盘余量 ≥ 6 GB(三个镜像合计约 5 GB,加上数据目录)。
- 可访问 Docker Hub(或已配置镜像加速/代理)。
验证宿主就绪的实测回显:
$ docker compose version
Docker Compose version v2.x
$ ss -ltn | grep 8128
(无输出,端口可用)
四、部署步骤
4.1 建目录并写入 compose 文件
mkdir -p /opt/mathesar && cd /opt/mathesar
mkdir -p msar/static msar/media msar/secrets msar/caddy msar/pgdata
vi docker-compose.yml
docker-compose.yml 全文(官方 0.12.0 版 compose + 本文三处适配,适配处均有注释):
name: mathesar-0120-stack
x-config: &config
DOMAIN_NAME: ${DOMAIN_NAME:-http://localhost}
POSTGRES_DB: ${POSTGRES_DB:-mathesar_django}
POSTGRES_USER: ${POSTGRES_USER:-mathesar}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mathesar}
POSTGRES_HOST: ${POSTGRES_HOST:-mathesar_db}
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
FILE_STORAGE_DICT: ${FILE_STORAGE_DICT:-{}}
SSO_CONFIG_DICT: ${SSO_CONFIG_DICT:-{}}
OIDC_CONFIG_DICT: ${OIDC_CONFIG_DICT:-{}} # deprecated, use SSO_CONFIG_DICT
REQUIRE_SSO_LOGIN: ${REQUIRE_SSO_LOGIN:-false}
MATHESAR_DJANGO_ADMIN_ENABLED: ${MATHESAR_DJANGO_ADMIN_ENABLED:-false}
MATHESAR_LANDING_PAGE_URL: ${MATHESAR_LANDING_PAGE_URL:-}
MATHESAR_INSTANCE_NAME: ${MATHESAR_INSTANCE_NAME:-Mathesar}
MATHESAR_AUTH_LOGO_URL: ${MATHESAR_AUTH_LOGO_URL:-}
MATHESAR_LOGIN_PAGE_TEXT_DICT: ${MATHESAR_LOGIN_PAGE_TEXT_DICT:-{}}
MATHESAR_LOGIN_PAGE_BACKGROUND: ${MATHESAR_LOGIN_PAGE_BACKGROUND:-}
MATHESAR_TERMS_OF_SERVICE_URL: ${MATHESAR_TERMS_OF_SERVICE_URL:-}
MATHESAR_PRIVACY_POLICY_URL: ${MATHESAR_PRIVACY_POLICY_URL:-}
services:
service:
container_name: mathesar_service
image: mathesar/mathesar:0.12.0 # 官方为 mathesar/mathesar:latest,本文锁定 0.12.0
environment:
<<: *config
DJANGO_SETTINGS_MODULE: config.settings.production
ALLOWED_HOSTS: ${ALLOWED_HOSTS:-*}
DEBUG: ${DEBUG:-false}
SECRET_KEY: ${SECRET_KEY-}
WEB_CONCURRENCY: ${WEB_CONCURRENCY-3}
PER_USER_DATABASES_ENABLED: ${PER_USER_DATABASES_ENABLED-false}
volumes:
- ./msar/static:/code/static
- ./msar/media:/code/.media
- ./msar/secrets:/code/.secrets
depends_on:
db:
condition: service_healthy
healthcheck:
test: curl -f http://localhost:8000/healthz/ready/
interval: 10s
timeout: 5s
retries: 30
start_period: 5s
expose:
- "8000"
db:
image: pgautoupgrade/pgautoupgrade:17-bookworm
container_name: mathesar_db
environment: *config
expose:
- "5432"
volumes:
- ./msar/pgdata:/var/lib/postgresql/data
caddy-reverse-proxy:
image: mathesar/mathesar-caddy:latest
environment: *config
ports:
- "8128:80" # 官方为 "80:80"(及 "443:443"),本机 80 被占用改为 8128
volumes:
- ./msar/media:/code/.media
- ./msar/static:/code/static
- ./msar/caddy:/data
networks:
default:
name: mathesar-0120-stack-net
driver: bridge
ipam:
config:
- subnet: 10.89.56.0/24
配置解读:
x-config锚点把三个服务共用的环境变量收拢到一处,service与db都通过*config继承,改一处全局生效。service.depends_on.db.condition: service_healthy保证数据库完全就绪后应用才启动——这是首次启动时mathesar_service会等待较长时间的原因。service只expose 8000不映射宿主端口,外部访问一律经 Caddy;db同理只在内网expose 5432。- 三个 bind mount 目录都落在部署目录下的
msar/内,备份/迁移只需带走整个/opt/mathesar/。
4.2 启动
cd /opt/mathesar && docker compose up -d
实测回显(首次创建):
Container mathesar-0120-stack-caddy-reverse-proxy-1 Creating
Container mathesar_db Creating
Container mathesar-0120-stack-caddy-reverse-proxy-1 Created
Container mathesar_db Created
Container mathesar_service Creating
Container mathesar_service Created
Container mathesar-0120-stack-caddy-reverse-proxy-1 Starting
Container mathesar_db Starting
Container mathesar-0120-stack-caddy-reverse-proxy-1 Started
Container mathesar_db Started
Container mathesar_db Waiting
Container mathesar_db Healthy
Container mathesar_service Starting
Container mathesar_service Started
观察点:mathesar_db Waiting → Healthy 即 depends_on 条件在生效;应用容器要等数据库健康检查通过才 Starting。首次拉取镜像耗时取决于网络,三个镜像约 5 GB。
4.3 验证就绪
# 1) 三个服务全部 Up,service/db 显示 (healthy)
docker compose ps
# 2) 应用健康检查端点
curl -s http://localhost:8128/healthz/ready/
# 3) 未登录访问根路径应 302 到登录页
curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://localhost:8128/
实测回显:
$ docker compose ps
NAME IMAGE SERVICE STATUS PORTS
mathesar-0120-stack-caddy-reverse-proxy-1 mathesar/mathesar-caddy:latest caddy-reverse-proxy Up 2 hours 443/tcp, 2019/tcp, 443/udp, 0.0.0.0:8128->80/tcp
mathesar_db pgautoupgrade/pgautoupgrade:17-bookworm db Up 2 hours (healthy) 5432/tcp
mathesar_service mathesar/mathesar:0.12.0 service Up 2 hours (healthy) 5432/tcp, 8000/tcp
$ curl -s http://localhost:8128/healthz/ready/
{"status": "ok"}
$ curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' http://localhost:8128/
302 -> http://localhost:8128/auth/login/?next=/
服务启动日志(docker compose logs service --tail 20 节选,实测):
==> Starting Mathesar...
==> Running Django setup...
Operations to perform:
Apply all migrations: account, auth, contenttypes, mathesar, sessions, socialaccount
Running migrations:
No migrations to apply.
No migrations to apply 表示元数据库结构已是最新(首次全新部署这里会执行一批 CREATE TABLE,属正常差异)。
4.4 首次安装向导与登录
浏览器打开 http://<宿主IP>:8128/,全新实例会进入安装向导(对应应用内 /complete_installation/ 路由),按页面提示创建管理员账号后即完成安装。本文演示实例创建的管理员为:
- 用户名:
admin - 密码:
q1w2e3r4
登录后进入库/表导航界面;http://localhost:8128/auth/login/ 是登录页固定地址(根路径未登录会被 302 到这里,实测见 4.3)。
4.5 形态 B:连接外部已有 PostgreSQL
Mathesar 的数据面不依赖内置库——它可以同时管理多个 PostgreSQL 服务器。实测在保留内置库的前提下,把一台外部 PostgreSQL 16.15 挂进同一网络并接入 Mathesar:
第一步,准备外部实例(已有多台 PG 的读者可跳过这一步,只需保证 Mathesar 能连通其 host:port):
# 外部 PostgreSQL 16 实例,数据目录同样落在部署目录下
docker run -d --name mathesar-0.12.0-extpg \
--network mathesar-0120-stack-net \
-p 8129:5432 \
-e POSTGRES_USER=pgadmin \
-e POSTGRES_PASSWORD=q1w2e3r4 \
-e POSTGRES_DB=business \
-v /opt/mathesar/extpg-data:/var/lib/postgresql/data \
postgres:16-alpine
实测版本确认(外部库内执行 SELECT version() 的回显):
PostgreSQL 16.15 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
第二步,接入 Mathesar——两种等价入口任选:
- Web UI:登录后进入「数据库」管理入口,选择连接已有数据库,填 Host
mathesar-0.12.0-extpg(同网络实例名/主机名)、端口5432、库名business、角色pgadmin、密码q1w2e3r4; - RPC 接口:用管理员会话调用
databases.setup.connect_existing(JSON-RPC,认证与调用方式见《Mathesar 0.12.0 API 使用详解》)。
接入成功的实测回显(databases.configured.list 返回两库,外部库 server_id=2):
[{"id": 1, "name": "warehouse", "server_id": 1, "last_confirmed_sql_version": "0.12.0", "needs_upgrade_attention": false, "nickname": "仓储示例库"},
{"id": 2, "name": "business", "server_id": 2, "last_confirmed_sql_version": "0.12.0", "needs_upgrade_attention": false, "nickname": "外部业务库"}]
servers.configured.list 同时返回两个 server(实测):
[{"id": 1, "host": "mathesar_db", "port": 5432, "sslmode": "prefer"},
{"id": 2, "host": "mathesar-0.12.0-extpg", "port": 5432, "sslmode": "prefer"}]
⚠️ 注意:Mathesar 连接外部库时会在目标库内安装 msar 函数 schema(实测外部库接入后同样出现
msar/__msar/mathesar_types),这是它的数据操作层,属预期行为;角色需具备建 schema 权限(本文用pgadmin超级角色无障碍)。
五、数据持久化说明
所有持久化数据都通过 bind mount 落在部署目录 /opt/mathesar/ 内:
| 宿主路径 | 挂载点 | 内容 |
|---|---|---|
./msar/pgdata | /var/lib/postgresql/data(db 服务) | PostgreSQL 数据目录:元数据库 mathesar_django + 内置形态的业务库 |
./msar/secrets | /code/.secrets(service 服务) | 自动生成的 SECRET_KEY 文件等 |
./msar/static | /code/static(service 与 caddy 共享) | Web UI 静态资源(启动时由应用落盘,Caddy 直出) |
./msar/media | /code/.media(service 与 caddy 共享) | 用户上传/导入的数据文件 |
./msar/caddy | /data(caddy 服务) | Caddy 数据(证书等) |
./extpg-data | /var/lib/postgresql/data(外部 PG) | 形态 B 的外部库数据 |
销毁性实测验证:把整套服务 docker compose down 后重新 up -d,数据完好——records.list 仍返回原有行(关羽/张飞等),databases.configured.list 中外部库配置仍在,健康检查恢复 200。也就是说 down 不触碰 bind mount 数据;只有删除宿主 msar/ 目录本身才会真正丢数据。
六、环境变量表
以下变量实测自 0.12.0 官方 compose 的 x-config 与 service 环境(docker compose exec service printenv 全量核对):
| 变量 | 默认值(compose) | 说明 |
|---|---|---|
DOMAIN_NAME | http://localhost | 站点对外地址;Caddy 以它作为站点名(含协议),反代与静态路径都挂在其下 |
POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD | mathesar_django / mathesar / mathesar | 元数据库连接三元组,db 与 service 共用 |
POSTGRES_HOST / POSTGRES_PORT | mathesar_db / 5432 | 元数据库地址 |
DJANGO_SETTINGS_MODULE | config.settings.production | 应用固定使用生产 settings(compose 内写死) |
ALLOWED_HOSTS | * | Django 允许的 Host 头;生产建议收敛为具体域名 |
DEBUG | false | Django 调试开关,生产保持 false |
SECRET_KEY | 空 | 会话签名密钥;留空时应用自动生成并写入 /code/.secrets/secret_key.txt(见 4.7 常见问题) |
WEB_CONCURRENCY | 3 | Gunicorn worker 数(实测进程树:1 主 + 3 worker) |
PER_USER_DATABASES_ENABLED | false | 是否启用「按用户隔离数据库」模式 |
FILE_STORAGE_DICT | {} | 下载链接文件存储后端配置(JSON;也支持 /code/file_storage.yml) |
SSO_CONFIG_DICT | {} | SSO 配置(JSON),0.12.0 起的规范入口 |
OIDC_CONFIG_DICT | {} | 旧版 OIDC 配置入口,保留兼容,官方标注 deprecated |
REQUIRE_SSO_LOGIN | false | 为 true 时强制 SSO 登录(本地口令登录被关闭) |
MATHESAR_DJANGO_ADMIN_ENABLED | false | 是否开启 Django 原生 /admin/ 后台 |
MATHESAR_LANDING_PAGE_URL | 空 | 未登录时根路径重定向到该地址(留空走默认登录页) |
MATHESAR_INSTANCE_NAME | Mathesar | 站点显示名 |
MATHESAR_AUTH_LOGO_URL | 空 | 登录页 Logo |
MATHESAR_LOGIN_PAGE_TEXT_DICT | {} | 登录页文案配置(JSON;也支持 /code/login_page.yml) |
MATHESAR_LOGIN_PAGE_BACKGROUND | 空 | 登录页背景 |
MATHESAR_TERMS_OF_SERVICE_URL / MATHESAR_PRIVACY_POLICY_URL | 空 | 服务条款/隐私政策链接 |
各变量与 Django settings 的映射细节、取值格式,见《Mathesar 0.12.0 配置参数详解》。
七、配置文件挂载
本部署形态下需要手工维护的配置文件为零——所有配置走环境变量。三个「可选配置文件」通过 YAML 提供更复杂的结构(挂到 /code/ 下即生效,优先级低于同名环境变量,实测自 settings 源码):
/code/sso.yml:SSO/OIDC 与 GitHub App 配置(当SSO_CONFIG_DICT的 JSON 过长不便维护时使用);/code/login_page.yml:登录页文案;/code/file_storage.yml:下载链接的文件存储后端(fsspec URI)。
如需使用,在 service 服务的 volumes 里追加一行挂载即可,例如:
volumes:
- ./msar/static:/code/static
- ./msar/media:/code/.media
- ./msar/secrets:/code/.secrets
- ./sso.yml:/code/sso.yml:ro
八、等价 docker run
不用 Compose 时,以下三条命令等价复现官方三服务拓扑(同一自定义网络内,注意启动顺序:先 db,再 service,最后 caddy):
# 1) 网络
docker network create mathesar-net
# 2) 内置 PostgreSQL(先启动,等它健康后再起应用)
docker run -d --name mathesar_db --network mathesar-net \
-e POSTGRES_DB=mathesar_django -e POSTGRES_USER=mathesar -e POSTGRES_PASSWORD=mathesar \
-e DOMAIN_NAME=http://localhost \
-v /opt/mathesar/msar/pgdata:/var/lib/postgresql/data \
pgautoupgrade/pgautoupgrade:17-bookworm
# 3) Mathesar 应用(SECRET_KEY 留空则自动生成到挂载的 secrets 目录)
docker run -d --name mathesar_service --network mathesar-net \
-e DOMAIN_NAME=http://localhost \
-e POSTGRES_DB=mathesar_django -e POSTGRES_USER=mathesar -e POSTGRES_PASSWORD=mathesar \
-e POSTGRES_HOST=mathesar_db -e POSTGRES_PORT=5432 \
-e DJANGO_SETTINGS_MODULE=config.settings.production \
-e ALLOWED_HOSTS='*' -e DEBUG=false -e WEB_CONCURRENCY=3 \
-v /opt/mathesar/msar/static:/code/static \
-v /opt/mathesar/msar/media:/code/.media \
-v /opt/mathesar/msar/secrets:/code/.secrets \
mathesar/mathesar:0.12.0
# 4) Caddy 反代(依赖容器名 mathesar_service 可解析,Caddyfile 内置在镜像中)
docker run -d --name mathesar_caddy --network mathesar-net \
-p 8128:80 \
-e DOMAIN_NAME=http://localhost \
-v /opt/mathesar/msar/media:/code/.media \
-v /opt/mathesar/msar/static:/code/static \
-v /opt/mathesar/msar/caddy:/data \
mathesar/mathesar-caddy:latest
生产环境仍建议用 Compose:depends_on 健康检查顺序、x-config 变量收拢、整栈一键升级都是 docker run 手工维护不了的。
九、常用运维命令
# 状态与资源
docker compose ps # 三个服务的运行状态与健康检查结果
docker stats --no-stream mathesar_service mathesar_db # 实测:service 约 285 MiB、db 约 84 MiB(空载)
# 日志
docker compose logs service --tail 50 # 应用日志(启动迁移、请求错误)
docker compose logs db --tail 50 # PostgreSQL 日志
# 启停
docker compose stop service # 单独停应用
docker compose start service # 再启动
docker compose restart service # 重启应用
docker compose down # 停止并移除三容器与网络(bind mount 数据保留)
docker compose up -d # 重新拉起
实测 docker compose down 回显:
Container mathesar_service Removing
Container mathesar_service Removed
Container mathesar_db Stopping
Container mathesar_db Stopped
Container mathesar_db Removing
Container mathesar_db Removed
Network mathesar-0120-stack-net Removing
Network mathesar-0120-stack-net Resource is still in use
⚠️ 最后一行
Resource is still in use不是错误:如果按 4.5 接入了外部 PostgreSQL(--network mathesar-0120-stack-net),该网络被外部实例占用而无法删除,属预期现象;docker compose up -d会原样复用这个网络,外部库连接不受影响(已实测验证)。
十、常见问题(FAQ)
Q1:宿主 80 端口被占用,怎么改入口端口?
只改 caddy-reverse-proxy 的 ports 一处即可,如 - "8128:80";DOMAIN_NAME 相应写成 http://<宿主IP>:8128。本指南全文即按 8128 实测。
Q2:SECRET_KEY 没设置,会有问题吗?
不会丢功能:应用启动时检测到 SECRET_KEY 为空,会自动生成随机密钥并写入挂载目录的 .secrets/secret_key.txt(实测文件存在,50 字节),重启复用同一文件。要显式管理时,在 compose 的 service 环境里传入 SECRET_KEY: ${SECRET_KEY} 并在宿主 .env 里赋值即可。
Q3:service 一直 restarting / healthy 起不来?
先看 docker compose logs service --tail 50。最常见原因是元数据库未就绪或连接参数错误:确认 POSTGRES_HOST 指向 db 服务的容器名(compose 内为 mathesar_db),且 db 容器已 (healthy)。应用自带 /healthz/ready/(实测返回 {"status": "ok"}),可用 curl http://localhost:8128/healthz/ready/ 快速分层定位是 Caddy、应用还是数据库的问题。
Q4:接入外部 PostgreSQL 时连不上?
外部库必须与 mathesar_service 网络可达:用 --network mathesar-0120-stack-net(或先把网络 connect 上去)并直接用容器名作 Host。若外部实例先于 compose 网络存在,用 docker network connect mathesar-0120-stack-net <外部实例名> 挂入即可。另外确认目标库角色有建 schema 权限(Mathesar 首次接入要装 msar 函数 schema)。
Q5:升级版本怎么做?
改 compose 中应用镜像 tag(如 mathesar/mathesar:0.12.0 → 目标版本),然后 docker compose up -d 重建 service;应用启动时会自动执行元数据库迁移(日志中的 Running migrations)。业务库侧 Mathesar 用 last_confirmed_sql_version/needs_upgrade_attention 字段追踪 SQL 层版本,如需对齐可调用 databases.upgrade_sql(见 API 篇)。升级前先备份 msar/ 整个目录。
Q6:忘了 admin 密码怎么办?
登录页提供密码重置入口(/auth/password_reset_confirm/ 路由,需要邮件后端);无邮件后端的内网环境,可临时开启 MATHESAR_DJANGO_ADMIN_ENABLED=true 进入 Django 原生后台改密,改完关闭。
十一、参考链接
- 官方 compose 文件(0.12.0 原版):https://github.com/mathesar-foundation/mathesar/blob/0.12.0/docker-compose.yml
- 官方安装文档:https://docs.mathesar.org/
- 应用镜像:https://hub.docker.com/r/mathesar/mathesar
- Caddy 镜像:https://hub.docker.com/r/mathesar/mathesar-caddy
- 本专栏相关:《Mathesar 0.12.0 介绍与选型指南》(架构与选型背景)、《Mathesar 0.12.0 配置参数详解》(环境变量逐项详解)、《Mathesar 0.12.0 API 使用详解》(RPC 接口)