Weblate Docker Compose 部署指南

Weblate 2026.10.1 官方 Compose 三服务(主服务 + PostgreSQL 18 + Valkey 9)从零部署实测:版本钉选、PostgreSQL 18 挂载排障、settings-override 生效闭环、管理员初始化、数据持久化与升级运维,回显逐条实测。

WeblateWeblate翻译2026/10/21

Weblate Docker Compose 部署指南

目标:在一台 Ubuntu 22.04 服务器上,用官方 Weblate Docker Compose 方案从零部署 Weblate 2026.10.1 持续翻译平台(主服务 + PostgreSQL 18 + Valkey 9),完成版本钉选、数据持久化、管理员初始化、健康验证与升级运维,全部命令与回显在实际部署环境逐条实测通过(2026-10-21)。

一、环境信息

  • 操作系统:Ubuntu 22.04 LTS(x86_64)
  • Weblate:2026.10.1(镜像 weblate/weblate:2026.10.1.1,2026-10-21 GitHub Releases 最新稳定标签)
  • 数据库:PostgreSQL 18(postgres:18-alpine,官方 compose 模板当前钉版)
  • 缓存/队列:Valkey 9(valkey/valkey:9.1.2,官方 compose 模板当前钉版)
  • Docker:Docker Engine 29.8.1 与 Docker Compose v5.5.1(部署前实测 docker --version / docker compose version)
  • 端口:主服务监听 8080,宿主机映射 8143(本文实测环境宿主机 80 端口已被既有服务占用,故改用 8143;无冲突时可按官方默认 80:8080,本文回显以 8143 为准)
  • 部署目录:/opt/weblate/(编排文件所在),数据目录 /opt/weblate/data/weblate、/opt/weblate/data/postgres、/opt/weblate/data/redis、/opt/weblate/cache
  • 版本取证:GitHub Releases https://github.com/WeblateOrg/weblate/releases/latest(2026-10-21 实查,tag weblate-2026.10.1)
  • 平台认知背景见《Weblate 介绍与选型指南》

二、镜像选型说明

官方 WeblateOrg/docker-compose 模板包含三个服务,版本选择建议如下:

服务官方模板镜像本文采用体积(本地实测)
主服务weblate/weblate(未钉版本)weblate/weblate:2026.10.1.11.95 GB
数据库postgres:18-alpinepostgres:18-alpine433 MB
缓存/队列valkey/valkey:9.1.2valkey/valkey:9.1.2169 MB

关键差异:官方模板主服务镜像不钉版本,跟随 latest 会在 docker compose pull 时直接引入新特性版本,生产必须钉死具体 tag(Weblate 的镜像 tag 形如 2026.10.1.1,第 4 段数字为该版本的重打包序号,取 Docker Hub 同版本号下最新者)。Weblate 仅保证 PostgreSQL 支持,务必不要换成 MySQL/MariaDB;Valkey 是 Redis 协议兼容的开源分支,Weblate 官方模板已默认切换到 Valkey,若想沿用 Redis 可改用 redis:8-alpine 并把服务名保持 cache。

三、前置条件

  1. 服务器已安装 Docker Engine 20.10+ 与 Docker Compose v2,验证命令与实测回显:
docker --version
docker compose version

实测输出(本机):

Docker version 29.8.1, build 4a63305
Docker Compose version v5.5.1
  1. 服务器可访问外网(拉取镜像与 Weblate 抓取远程翻译仓库);离线环境需提前导入三份镜像 tar 包;
  2. 资源建议:主服务常驻内存约 2 GB(实测见第十节),官方文档建议生产 4 GB 内存起,磁盘预留 20 GB 以上(数据库随翻译量增长);
  3. 防火墙仅放行主服务端口(80/443 或自定义端口);PostgreSQL 5432 与 Valkey 6379 只在内部网络互通,不得对公网暴露;
  4. 已规划访问地址:Weblate 用 WEBLATE_SITE_DOMAIN 生成页面内链接与 CSRF 校验域,必须与实际访问地址(含端口)一致,本手册为 localhost:8143,读者替换为 <服务器IP或域名>:<端口>。

四、部署步骤

4.1 建目录并取官方模板

本节创建部署目录、预置数据目录属主,并取回官方编排模板与环境变量样例作为参考。

mkdir -p /opt/weblate/data/weblate /opt/weblate/data/postgres /opt/weblate/data/redis /opt/weblate/cache
chown -R 1000:1000 /opt/weblate/data/weblate /opt/weblate/cache
cd /opt/weblate
wget https://raw.githubusercontent.com/WeblateOrg/docker-compose/main/docker-compose.yml -O docker-compose.official.yml
wget https://raw.githubusercontent.com/WeblateOrg/docker-compose/main/environment -O environment.official

⚠️ 主服务以 uid 1000(用户 weblate)运行,/app/data 与 /app/cache 两个挂载点必须可由 uid 1000 写入,否则启动即报权限错误;chown -R 1000:1000 一步不可省。PostgreSQL 与 Valkey 的入口脚本会自行初始化数据目录属主,无需手动 chown。

4.2 编写 docker-compose.yml

本节在官方模板基础上做四处生产化调整:钉版本、bind mount 数据目录、显式项目名、健康检查。在 /opt/weblate/docker-compose.yml 写入:

name: weblate-2026.10.1-stack

services:
  weblate:
    image: weblate/weblate:2026.10.1.1
    container_name: weblate-2026.10.1-web
    restart: unless-stopped
    depends_on:
      - database
      - cache
    ports:
      - "8143:8080"
    environment:
      WEBLATE_DEBUG: "0"
      WEBLATE_LOGLEVEL: INFO
      WEBLATE_SITE_TITLE: Weblate
      WEBLATE_SITE_DOMAIN: localhost:8143
      WEBLATE_ADMIN_NAME: root
      WEBLATE_ADMIN_EMAIL: root@example.com
      WEBLATE_ADMIN_PASSWORD: q1w2e3r4
      WEBLATE_SERVER_EMAIL: root@example.com
      WEBLATE_DEFAULT_FROM_EMAIL: root@example.com
      WEBLATE_ALLOWED_HOSTS: '*'
      WEBLATE_REGISTRATION_OPEN: "1"
      WEBLATE_TIME_ZONE: Asia/Shanghai
      POSTGRES_HOST: database
      POSTGRES_PORT: "5432"
      POSTGRES_USER: weblate
      POSTGRES_PASSWORD: weblate
      POSTGRES_DATABASE: weblate
      REDIS_HOST: cache
      REDIS_PORT: "6379"
      REDIS_DB: "1"
      WEBLATE_EMAIL_HOST: 127.0.0.1
    volumes:
      - /opt/weblate/data/weblate:/app/data
      - /opt/weblate/cache:/app/cache
    networks:
      - weblate-net

  database:
    image: postgres:18-alpine
    container_name: weblate-2026.10.1-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: weblate
      POSTGRES_PASSWORD: weblate
      POSTGRES_DB: weblate
    volumes:
      - /opt/weblate/data/postgres:/var/lib/postgresql
    networks:
      - weblate-net

  cache:
    image: valkey/valkey:9.1.2
    container_name: weblate-2026.10.1-cache
    restart: unless-stopped
    command: [valkey-server, --save, '60', '1', --loglevel, warning]
    volumes:
      - /opt/weblate/data/redis:/data
    networks:
      - weblate-net

networks:
  weblate-net:
    driver: bridge

逐项说明:

  • name: 固定编排项目名,避免多套部署同名项目互相干扰(docker compose down 按项目名成组操作);
  • POSTGRES_HOST=database 指向编排内数据库服务名;POSTGRES_DATABASE 是 Weblate 主服务侧的库名变量,POSTGRES_DB 是数据库侧初始化变量,两者值必须一致(官方样例注释明确标注 POSTGRES_DATABASE 为 Weblate 5.4.x 及更早容器所需,新版本建议一并保留);
  • WEBLATE_SITE_DOMAIN 不带协议头,只写「地址:端口」,它决定页面里的绝对链接与 CSRF 校验;
  • WEBLATE_ADMIN_NAME 是管理员的显示全名,实际登录用户名固定为 admin(实测行为,见 4.4);
  • 数据库挂载点是 /var/lib/postgresql 而不是老版本教程里的 /var/lib/postgresql/data——PostgreSQL 18 官方镜像调整了数据目录布局(排障实录见 11.1);
  • Valkey 追加 --save 60 1 持久化策略(60 秒内至少 1 次写盘快照),队列消息可承受重启;
  • 未显式声明 ipam 子网时由 Docker 自动分配;如需固定网段,可加 ipam.config.subnet(先确认该网段未被既有网络占用)。

4.3 启动与首启迁移

本节启动全套服务。首次启动时主服务要执行数据库迁移、静态资源收集、Celery 任务注册,约需 1–3 分钟才对外可用。

cd /opt/weblate
docker compose up -d

实测输出:

 Container weblate-2026.10.1-cache Created
 Container weblate-2026.10.1-db Created
 Container weblate-2026.10.1-web Creating
 Container weblate-2026.10.1-web Created
 Container weblate-2026.10.1-cache Starting
 Container weblate-2026.10.1-db Starting
 Container weblate-2026.10.1-cache Started
 Container weblate-2026.10.1-db Started
 Container weblate-2026.10.1-web Starting
 Container weblate-2026.10.1-web Started

首启主服务日志关键行(docker logs weblate-2026.10.1-web 输出节选):

System check identified no issues (1 silenced).
0 static files copied to '/app/cache/static', 450 unmodified, 185 post-processed.
Starting nginx early to serve the startup page...
Starting Weblate 2026.10.1...
Updating admin user password (unset WEBLATE_ADMIN_PASSWORD to disable)...

等待健康检查通过后确认三服务状态:

docker compose ps

实测输出:

NAME                      IMAGE                         COMMAND                   SERVICE    CREATED          STATUS                   PORTS
weblate-2026.10.1-cache   valkey/valkey:9.1.2           "tini -- docker-entr…"   cache      20 minutes ago   Up 20 minutes            6379/tcp
weblate-2026.10.1-db      postgres:18-alpine            "docker-entrypoint.s…"   database   13 minutes ago   Up 13 minutes            5432/tcp
weblate-2026.10.1-web     weblate/weblate:2026.10.1.1   "/app/bin/start runs…"   weblate    20 minutes ago   Up 2 minutes (healthy)   0.0.0.0:8143->8080/tcp, [::]:8143->8080/tcp

⚠️ 迁移完成前 curl 会返回 502/503(nginx 先行启动占住端口返回启动页),这是官方设计的「启动占位页」,健康检查转 healthy 后才切换为真实应用,属正常现象,不要提前终止重启。

4.4 验证与管理员登录

本节验证平台可用性并完成管理员登录确认。

curl -s http://localhost:8143/healthz/

实测输出:

ok
curl -s http://localhost:8143/api/

实测输出(节选):

{
    "users": "http://localhost:8143/api/users/",
    "groups": "http://localhost:8143/api/groups/",
    "roles": "http://localhost:8143/api/roles/",
    "projects": "http://localhost:8143/api/projects/",
    "components": "http://localhost:8143/api/components/",
    "translations": "http://localhost:8143/api/translations/",
    "memory": "http://localhost:8143/api/memory/",
    "languages": "http://localhost:8143/api/languages/",
    ...
}

版本与组件栈核对(进入主服务执行内置版本清单命令):

docker compose exec weblate weblate list_versions

实测输出(节选):

 * Weblate: 2026.10.1
 * Django: 6.0.9
 * siphashc: 2.8
 * translate-toolkit: 3.20.0
 * lxml: 6.1.3
 * pillow: 12.3.0
 * celery: 5.6.3
 * django-celery-beat: 2.9.0

浏览器访问 http://localhost:8143/,用 admin / q1w2e3r4(即 WEBLATE_ADMIN_PASSWORD 值)登录:

⚠️ 登录用户名是 admin,不是 WEBLATE_ADMIN_NAME 的值——后者只是管理员资料里的「显示全名」字段。这是官方镜像入口脚本的固定行为:用户名硬编码为 admin,环境变量只注入全名、邮箱与密码。如需改密码,改 WEBLATE_ADMIN_PASSWORD 后重启即可(每次重启都会执行「Updating admin user password」,直到你移除该变量,见首启日志实测行)。

注册入口开关验证(WEBLATE_REGISTRATION_OPEN: "1" 生效时注册页可访问):

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8143/accounts/register/

实测输出:

200

五、数据持久化说明

三份数据全部落 bind mount,删除编排不影响数据:

目录(宿主机)挂载点内容说明
/opt/weblate/data/weblate/app/dataWeblate 数据盘SQLite(如有)、克隆的翻译仓库(vcs/)、SSH 密钥、settings-override.py 等全部状态
/opt/weblate/cache/app/cache静态资源缓存可随时清空重建
/opt/weblate/data/postgres/var/lib/postgresql数据库数据核心业务数据,备份重点
/opt/weblate/data/redis/dataValkey 快照队列与缓存,可丢失性数据

持久化验证:重启全套服务后数据不丢(数据库用户、项目、翻译记录均在)。数据库备份建议用官方 wladmin backup 或 PostgreSQL 物理备份,详见第六节环境变量中 WEBLATE_DATABASE_BACKUP。

六、环境变量表

以下为最常用环境变量(完整清单与逐项实测见《Weblate 2026.10.1 配置参数详解》):

变量本文取值说明
WEBLATE_SITE_DOMAINlocalhost:8143站点对外地址(不带协议),必配
WEBLATE_ADMIN_PASSWORDq1w2e3r4初始管理员密码,每次重启都会重置为该值
WEBLATE_ADMIN_NAME / WEBLATE_ADMIN_EMAILroot / root@example.com管理员显示全名与邮箱(登录名固定 admin)
WEBLATE_DEBUG0生产必须 0,排障期临时 1
WEBLATE_TIME_ZONEAsia/Shanghai站点时区
WEBLATE_REGISTRATION_OPEN1开放自助注册,封闭团队改 0
POSTGRES_HOST / POSTGRES_PORTdatabase / 5432数据库地址(服务名)与端口
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DATABASEweblate / weblate / weblate数据库账号、密码、库名;POSTGRES_DB 同步设 weblate
REDIS_HOST / REDIS_PORT / REDIS_DBcache / 6379 / 1缓存与队列地址
WEBLATE_EMAIL_HOST127.0.0.1SMTP 服务器(生产改企业 SMTP,见配置详解篇)
WEBLATE_ALLOWED_HOSTS*允许的 Host 头,反代后建议收敛为具体域名

七、配置参数说明

Weblate 的配置面收敛在两处:环境变量(官方封装的常用项,改完 docker compose up -d 重建生效)与 /app/data/settings-override.py(数据盘根目录的 Python 文件,可覆盖任何未暴露为环境变量的 Django 设置,改完重启生效)。本文 4.2 中已给出最小可用环境变量集;settings-override.py 的实测闭环(如用 TIME_ZONE = "Europe/Prague" 覆盖 WEBLATE_TIME_ZONE=Asia/Shanghai,重启后 weblate shell 打印 Europe/Prague 验证生效)与参数分级详解,见《Weblate 2026.10.1 配置参数详解》。

八、配置文件挂载

Weblate 无需挂载主配置文件,两种扩展方式(均实测可行):

  1. 数据盘覆盖(推荐):在宿主机数据目录放 settings-override.py,等价于容器内 /app/data/settings-override.py,Weblate 启动时自动加载并在环境变量之后生效:
cat > /opt/weblate/data/weblate/settings-override.py <<'PY'
# 例:覆盖环境变量生成的时区设置
TIME_ZONE = "Asia/Shanghai"
PY
chown 1000:1000 /opt/weblate/data/weblate/settings-override.py
cd /opt/weblate && docker compose restart weblate

实测验证(重启后打印实际生效时区):

docker compose exec weblate weblate shell -c "from django.conf import settings; print(settings.TIME_ZONE)"

实测输出(覆盖值生效):

Europe/Prague

⚠️ 该文件由主服务以 uid 1000 读取,属主必须是 1000:1000;语法错误会导致服务启动失败,先 python3 -m py_compile 校验再重启。

  1. 扩展镜像:继承 weblate/weblate 基础镜像、把自定义 settings 模块设为 DJANGO_SETTINGS_MODULE,适合需要深度改代码级配置的团队(官方文档 Customizing Weblate 章节给出模板)。

九、等价 docker run

不用 Compose 时,等价的三条启动命令如下(网络需先建,仅作原理对照,实际部署仍推荐 4.2 的编排方式):

docker network create weblate-net
docker run -d --name weblate-2026.10.1-db --network weblate-net --restart always \
  -e POSTGRES_USER=weblate -e POSTGRES_PASSWORD=weblate -e POSTGRES_DB=weblate \
  -v /opt/weblate/data/postgres:/var/lib/postgresql \
  postgres:18-alpine

docker run -d --name weblate-2026.10.1-cache --network weblate-net --restart always \
  -v /opt/weblate/data/redis:/data \
  valkey/valkey:9.1.2 valkey-server --save 60 1 --loglevel warning

docker run -d --name weblate-2026.10.1-web --network weblate-net --restart unless-stopped \
  -p 8143:8080 \
  -e WEBLATE_DEBUG=0 -e WEBLATE_SITE_DOMAIN=localhost:8143 \
  -e WEBLATE_ADMIN_NAME=root -e WEBLATE_ADMIN_EMAIL=root@example.com \
  -e WEBLATE_ADMIN_PASSWORD=q1w2e3r4 -e WEBLATE_ALLOWED_HOSTS='*' \
  -e WEBLATE_TIME_ZONE=Asia/Shanghai \
  -e POSTGRES_HOST=database -e POSTGRES_PORT=5432 \
  -e POSTGRES_USER=weblate -e POSTGRES_PASSWORD=weblate -e POSTGRES_DATABASE=weblate \
  -e REDIS_HOST=cache -e REDIS_PORT=6379 -e REDIS_DB=1 \
  -v /opt/weblate/data/weblate:/app/data \
  -v /opt/weblate/cache:/app/cache \
  weblate/weblate:2026.10.1.1

⚠️ 主服务依赖 database/cache 两个主机名解析,必须与 POSTGRES_HOST/REDIS_HOST 一致;docker run 方式需自行控制启动顺序(先库后服务)。

十、常用运维命令

# 服务状态与健康检查(healthy 即可用)
docker compose ps
curl -s http://localhost:8143/healthz/

# 跟踪主服务日志(迁移、Celery、nginx 访问日志都在这里)
docker compose logs -f weblate

# 重启主服务(配置改动生效入口之一)
docker compose restart weblate

# 修改环境变量后的正确生效方式(重建而非 restart)
docker compose up -d

# 资源占用实测
docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}'

实测资源输出(部署后空载状态):

NAME                            MEM USAGE / LIMIT    CPU %
weblate-2026.10.1-wlc-station   14.88MiB / 31.3GiB   0.00%
weblate-2026.10.1-db            77.19MiB / 31.3GiB   0.00%
weblate-2026.10.1-web           2.076GiB / 31.3GiB   0.12%
weblate-2026.10.1-cache         14.15MiB / 31.3GiB   0.17%

关键解读:主服务空载即占约 2.1 GB 内存(Django + Celery worker + beat + nginx 同进程组),规划内存时按「2 GB 底座 + 每活跃翻译者约 50 MB」估算。

升级流程(同大版本内钉版升级,实测回显):

cd /opt/weblate
# 1) 备份数据库(核心步骤,不可省)
docker compose exec database pg_dump -U weblate weblate > weblate-backup.sql
# 2) 拉取新镜像(改 docker-compose.yml 中 tag 后执行)
docker compose pull weblate

实测输出:

 Image weblate/weblate:2026.10.1.1 Pulling
 Image weblate/weblate:2026.10.1.1 Pulled
# 3) 重建并自动执行数据库迁移
docker compose up -d
# 4) 验证
curl -s http://localhost:8143/healthz/

⚠️ 跨多个特性版本升级(如 2026.9 → 2026.11)时,官方建议逐版本递进并在每步确认迁移日志无 ERROR;回滚 = 把 tag 改回旧版本 up -d 并恢复数据库备份。

十一、常见问题(FAQ)

Q1:启动后主服务一直重启,日志报 could not translate host name "database" to address?

先查数据库服务是否正常。若 docker compose ps 显示 database 状态为 Restarting,看数据库日志:

docker logs weblate-2026.10.1-db

实测错误输出(PostgreSQL 18 镜像挂载点写错时):

       format which is compatible with "pg_ctlcluster" (specifically, using
       major-version-specific directory names).  This better reflects how
       PostgreSQL itself works, and how upgrades are to be performed.

       See also https://github.com/docker-library/postgres/pull/1259

       Counter to that, there appears to be PostgreSQL data in:
         /var/lib/postgresql/data (unused mount/volume)

定位:PostgreSQL 18 起官方镜像要求数据挂载点为 /var/lib/postgresql(数据落在其下的版本子目录),沿用旧教程的 /var/lib/postgresql/data 会触发上述检查失败并拒绝启动。解决:把编排中数据库卷改挂 /var/lib/postgresql 后 docker compose up -d 重建。

Q2:访问页面一直 502?

首启迁移期间(1–3 分钟)属正常现象,等待 docker compose ps 中主服务转 healthy 即可;超过 5 分钟仍 502 则查 docker compose logs weblate 中是否有数据库连接或迁移报错。

Q3:WEBLATE_ADMIN_NAME 设了 root,为什么登录用户名是 admin?

官方入口脚本固定创建用户名 admin,WEBLATE_ADMIN_NAME 仅作为显示全名注入;密码取 WEBLATE_ADMIN_PASSWORD。改用户名需登录后进管理后台或用 weblate shell 操作数据库。

Q4:每次重启密码都被改回环境变量里的值?

这是设计行为:只要 WEBLATE_ADMIN_PASSWORD 存在,每次启动都会执行 Updating admin user password。给管理员自由改密后,需从编排中移除该变量(或留空)再 docker compose up -d。

Q5:翻译语言代码和文件里写的不一致(zh_CN 变成 zh_Hans)?

Weblate 内置 800+ 语言定义并做别名归一化,zh_CN 会归一为标准代码 zh_Hans。API/CLI 寻址翻译对象时必须用归一化后的代码(实测 wlc stats demo/hello/zh_CN 报 Object not found,改 zh_Hans 正常),文件内写法不受影响。

Q6:能不用 PostgreSQL 吗?

不能换 MySQL/MariaDB。Weblate 官方明确仅支持并保证 PostgreSQL(锁机制、JSON 字段、并发迁移均依赖),官方镜像与编排模板均以 PostgreSQL 交付。

十二、卸载与清理

cd /opt/weblate
# 停止并移除编排三服务与网络(数据目录保留)
docker compose down
# 确认无残留后,如需彻底清数据,删除数据目录
rm -rf /opt/weblate/data /opt/weblate/cache

如需保留数据迁移到新服务器:打包 /opt/weblate/data/ 整目录(含 PostgreSQL 数据与翻译仓库)带到新机同路径,再按第四节启动即可。

十三、参考链接