Kinto 26.5.0 Docker Compose 部署指南
Kinto 26.5.0 Docker Compose 部署指南:web+PostgreSQL+Memcached 三服务栈的部署文件、kinto.ini 定制、启动与健康验证、admin 账号与 Admin UI、数据持久化备份,及监听地址等排障实录。
Kinto 26.5.0 Docker Compose 部署指南
一、部署形态与环境规划
1.1 形态决策
Kinto 官方提供三种安装路径:Docker 镜像(kinto/kinto-server)、Python 包(pip install kinto)与源码构建。本文按官方推荐的 Docker Compose 范式部署——官方仓库的 docker-compose.yml 样例由三个服务组成:web(Kinto 本体)、db(PostgreSQL 14,持久化存储)、cache(Memcached,缓存后端)。默认镜像内置配置把存储/权限/缓存都指向内存后端,重启即丢数据,因此生产可用形态必须外接 PostgreSQL 与 Memcached,这正是官方 compose 样例的存在意义。
💡 技术拓展:Kinto 的三后端指 storage(记录持久化)、cache(缓存与会话状态)、permission(权限 ACL 存储)三类可插拔组件,见《Kinto 26.5.0 介绍与选型指南》第二节。三后端可以各自指向不同实现,本文按官方样例统一收敛到"PostgreSQL 存数据 + Memcached 做缓存 + PostgreSQL 存权限"。
1.2 环境前置
本次实测环境(2026-10-30):
| 项 | 值 |
|---|---|
| 操作系统 | Linux(5.15 内核) |
| Docker | 29.9.2 |
| Docker Compose | v5.6.1 |
| Kinto 镜像 | kinto/kinto-server:26.5.0(351MB) |
| PostgreSQL 镜像 | postgres:14(629MB) |
| Memcached 镜像 | memcached:1(129MB) |
| 对外端口 | 8149(映射服务 8888 端口,部署前用 ss -ltn 确认空闲) |
| 专用网络 | kinto-26.5.0-net,显式子网 10.89.57.0/24,与宿主机上其他业务网段隔离 |
版本口径说明:镜像 tag 为 26.5.0,对应 GitHub Releases 上的 26.5.0(查询日期 2026-10-30);官方镜像内 pip show kinto 与 kinto version 显示 0.0.0,这是官方镜像构建流程不回填版本元数据的已知现象,不影响功能,以镜像 tag 为准。
镜像拉取(Docker Hub 直连慢时挂代理):
docker pull kinto/kinto-server:26.5.0
docker pull postgres:14
docker pull memcached:1
⚠️ 网络说明:本环境直连 Docker Hub 超时,实测走代理
192.168.1.72:7897后三个镜像均正常拉取;若代理地址不可用,可换用国内镜像加速器。
二、编写部署文件
2.1 项目目录结构
/opt/kinto/
├── docker-compose.yml # 部署栈定义
├── config/
│ └── kinto.ini # 自定义服务配置(挂载进 web 服务)
└── data/
└── db/ # PostgreSQL 数据落盘目录(自动生成)
2.2 docker-compose.yml 全文
name: kinto-26.5.0-stack
services:
db:
image: postgres:14
container_name: kinto-26.5.0-db
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
volumes:
- ./data/db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
cache:
image: memcached:1
container_name: kinto-26.5.0-cache
command: -m 64
restart: unless-stopped
web:
image: kinto/kinto-server:26.5.0
container_name: kinto-26.5.0-web
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
ports:
- "8149:8888"
volumes:
- ./config:/etc/kinto
environment:
KINTO_INI: /etc/kinto/kinto.ini
restart: unless-stopped
networks:
default:
name: kinto-26.5.0-net
driver: bridge
ipam:
config:
- subnet: 10.89.57.0/24
逐段解说:
- 显式项目名
name: kinto-26.5.0-stack:官方 Dockerfile 定义 web 服务的启动命令为kinto migrate && kinto start,首次启动自动建表;显式项目名避免与其他 compose 项目冲突,也便于按名整栈管理; - db 健康检查:
pg_isready就绪后才启动 web,防止 Kinto 先于数据库启动导致迁移失败;数据通过./data/db实现宿主机持久化; - cache 限内存:
-m 64把 Memcached 内存上限压到 64MB,缓存服务按官方样例不落盘、重启可丢; - web 端口映射:宿主机 8149 → 服务 8888(Kinto 默认监听端口);
- 自定义配置注入:
./config:/etc/kinto加KINTO_INI环境变量,这是官方文档给出的"Custom configuration file"标准做法——镜像默认配置有监听地址陷阱,必须替换(见 2.3 与第七节排障实录)。
2.3 生成并定制 kinto.ini
Kinto 的配置是单个 INI 文件。用官方镜像自带 CLI 生成一份针对 PostgreSQL + Memcached 的初始配置(在 compose 项目目录执行,生成结果落到宿主机 ./config/):
docker compose run --rm -v "$PWD/config:/out" --entrypoint sh web -c 'kinto init --ini /out/kinto.ini --host 0.0.0.0 --backend postgresql --cache-backend memcached'
实测回显:
INFO Created config /out/kinto.ini
kinto init 各参数:--host 0.0.0.0 让服务监听所有网卡(必须显式指定,默认值 127.0.0.1 会导致端口映射后无法访问,见第七节);--backend postgresql 指定存储/权限后端;--cache-backend memcached 指定缓存后端。生成后需要手工改三处:
# 1. 存储后端指向 compose 网络内的 db 服务(默认模板写的是 localhost)
kinto.storage_url = postgresql://postgres:postgres@db/postgres
# 2. 权限后端同样指向 db
kinto.permission_url = postgresql://postgres:postgres@db/postgres
# 3. 缓存后端:模板把 Memcached 地址写进了 kinto.cache_url 键,
# 但 Memcached 后端实际读取的是 kinto.cache_hosts,必须手工改名
kinto.cache_hosts = cache:11211
完整配置文件关键段落(kinto init 生成的原文节选,# 注释保留):
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = %(http_port)s
[app:main]
use = egg:kinto
# Plugins
kinto.includes = kinto.plugins.default_bucket
kinto.plugins.admin
kinto.plugins.accounts
# kinto.plugins.history
# Backends
kinto.storage_backend = kinto.core.storage.postgresql
kinto.storage_url = postgresql://postgres:postgres@db/postgres
kinto.cache_backend = kinto.core.cache.memcached
kinto.cache_hosts = cache:11211
kinto.permission_backend = kinto.core.permission.postgresql
kinto.permission_url = postgresql://postgres:postgres@db/postgres
# Authentication
kinto.userid_hmac_secret = 21a00c06abffd4d4d161ff762a8dc42b48b5e1f32a5462a1892d1013cd95eb53
multiauth.policies = account
# Bucket ID salt
kinto.default_bucket_hmac_secret = b4bd4fcf4bfd2b04e003117c27eef6b8e80fa5c8bcf873a58c6d08f71f8236fc
# Accounts API configuration
multiauth.policy.account.use = kinto.plugins.accounts.AccountsPolicy
# Allow anyone to create accounts.
kinto.account_create_principals = system.Everyone
# Set user 'account:admin' as the administrator.
kinto.account_write_principals = account:admin
# Allow administrators to create buckets
kinto.bucket_create_principals = account:admin
两个 *_hmac_secret 是 kinto init 随机生成的密钥(分别用于用户 ID 哈希与默认桶 ID 派生),一经投入使用不可更换,否则旧用户身份与默认桶映射全部错位;多实例部署时所有实例必须使用同一份密钥。配置文件所有参数域的逐一解释见《Kinto 26.5.0 配置参数详解》。
三、启动部署栈
3.1 启动
docker compose up -d
实测回显(-d 后台启动,db 等待健康检查通过后 web 才启动):
[+] Running 5/5
✔ Network kinto-26.5.0-net Created
✔ Container kinto-26.5.0-cache Started
✔ Container kinto-26.5.0-db Healthy
✔ Container kinto-26.5.0-web Started
3.2 状态核验
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
kinto-26.5.0-cache memcached:1 "docker-entrypoint.s…" cache 8 minutes ago Up 8 minutes 11211/tcp
kinto-26.5.0-db postgres:14 "docker-entrypoint.s…" db 8 minutes ago Up 8 minutes (healthy) 5432/tcp
kinto-26.5.0-web kinto/kinto-server:26.5.0 "sh -c 'kinto migrat…" web 8 minutes ago Up 8 minutes 0.0.0.0:8149->8888/tcp, [::]:8149->8888/tcp
三个服务全部 Up,db 带 (healthy) 标记,web 的 8149→8888 映射就绪。PostgreSQL 与 Memcached 端口未对宿主机暴露,仅在专用网络内部可达,这是有意为之。
3.3 启动日志解读
docker compose logs web
实测回显(节选,已略去无害警告行):
INFO Running kinto 0.0.0.
INFO Detected PostgreSQL storage schema version 26.
INFO PostgreSQL storage schema is up-to-date.
INFO Detected PostgreSQL permission schema version 2.
INFO PostgreSQL permission schema is up-to-date.
Running kinto 0.0.0. rid=None
Starting server in PID 9.
Serving on http://0.0.0.0:8888 rid=None
"GET /v1?" 200 (1 ms) agent=curl/8.5.0 errno=0 rid=3635a67e-8af8-416e-88b2-602b08990d6c time=2026-10-30T08:06:53.707000
要点:web 服务每次启动先自动执行 kinto migrate——首次启动把 PostgreSQL 存储模式建到 schema version 26、权限模式建到 schema version 2,之后启动显示 up-to-date;随后 waitress 监听 0.0.0.0:8888 并开始记录访问日志(每行含请求 ID、耗时、User-Agent)。
四、服务健康验证
4.1 根视图(hello)
curl -s http://127.0.0.1:8149/v1/
实测回显:
{
"project_name": "kinto",
"project_version": "0.0.0",
"http_api_version": "1.23",
"project_docs": "https://kinto.readthedocs.io/",
"url": "http://127.0.0.1:8149/v1/",
"config": {
"path": "/etc/kinto/kinto.ini",
"hash": "502807b704fb0a4ae64d3efd4295394432775c5da9fe2140f564f19fd788ad39",
"modified": "2026-10-30T08:06:08.215283"
},
"settings": {
"explicit_permissions": true,
"batch_max_requests": 25,
"readonly": false
},
"capabilities": {
"default_bucket": {"description": "The default bucket is an alias for a personal bucket where collections are created implicitly.", "url": "https://kinto.readthedocs.io/en/latest/api/1.x/buckets.html#personal-bucket-default"},
"admin": {"description": "Serves the admin console.", "url": "https://github.com/Kinto/kinto-admin/", "version": "6.6.0"},
"accounts": {"description": "Manage user accounts.", "url": "https://kinto.readthedocs.io/en/latest/api/1.x/accounts.html", "validation_enabled": false},
"permissions_endpoint": {"description": "The permissions endpoint can be used to list all user objects permissions.", "url": "https://kinto.readthedocs.io/en/latest/configuration/settings.html#activating-the-permissions-endpoint"}
}
}
根视图同时是能力自描述文档:capabilities 列出当前启用的插件(default_bucket/admin/accounts),http_api_version: 1.23 是 API 契约版本。返回的 url 字段即服务自认的对外地址,反代部署后若该值异常,需配置 kinto.http_scheme/kinto.http_host(见配置详解篇)。
4.2 心跳端点
curl -s http://127.0.0.1:8149/v1/__heartbeat__
实测回显:
{
"storage": true,
"permission": true,
"cache": true
}
三个后端全部 true 才算健康,负载均衡健康检查建议直接指向此端点。
五、管理账号与 Admin UI
5.1 创建 admin 账号
默认配置启用了 accounts 插件,首个管理员账号通过 API 创建(密码哈希后入库,接口返回的是 bcrypt 串):
curl -s -X PUT http://127.0.0.1:8149/v1/accounts/admin -d '{"data": {"password": "q1w2e3r4"}}' -H "Content-Type:application/json"
实测回显:
{
"permissions": {
"write": ["account:admin"]
},
"data": {
"password": "$2b$12$jrSO7FtobNAfYOWyQVS6GenoSjl0cWOtyIHWsebxcKbPw1OPeLBTe",
"id": "admin",
"last_modified": 1793347628888
}
}
默认配置中 kinto.account_write_principals = account:admin 意味着只有 admin 能增删账号,kinto.account_create_principals = system.Everyone 允许匿名自助注册(生产收紧时改掉,见配置详解篇)。
5.2 鉴权核验
用 Basic 认证访问根视图,确认身份与主体(principals):
curl -s http://127.0.0.1:8149/v1/ -u admin:q1w2e3r4
实测回显(节选 user 字段):
{
"user": {
"id": "account:admin",
"principals": ["account:admin", "system.Authenticated", "system.Everyone"],
"bucket": "deaec1ea-8c0a-4584-d5fb-2ad9942e9161"
}
}
bucket 字段是该用户个人默认桶的派生 ID(由 kinto.default_bucket_hmac_secret 对用户 ID 做 HMAC 得出)。
5.3 Admin UI
浏览器访问 http://<服务器地址>:8149/v1/admin/ 即打开内置的 Kinto Admin 管理界面(版本 6.6.0),以 admin/q1w2e3r4 登录后可视化操作桶/集合/记录与权限。Admin 资源由 web 服务直接托管,无需单独部署前端。
六、数据持久化与日常运维
6.1 数据落盘与备份
全部业务数据在 PostgreSQL 中,库内共 5 张表(存储/权限/元数据/时间戳/用户主体),实测 psql -U postgres -c "\dt":
List of relations
Schema | Name | Type | Owner
--------+------------------------+-------+----------
public | access_control_entries | table | postgres
public | metadata | table | postgres
public | objects | table | postgres
public | timestamps | table | postgres
public | user_principals | table | postgres
(5 rows)
数据经 bind mount 落在宿主机 ./data/db/,备份用标准 pg_dump 即可:
docker compose exec db pg_dump -U postgres postgres > kinto-backup-$(date +%F).sql
恢复时先 docker compose down,清空 ./data/db/ 后重启空库,再 psql -f 导入备份。
6.2 生命周期命令
docker compose stop # 停栈(保留网络与存储)
docker compose start # 复启
docker compose down # 删栈(数据仍在 ./data/db/)
docker compose up -d # 再建栈
升级版本:改 docker-compose.yml 中镜像 tag(如 26.5.0 → 下一版本),docker compose up -d 滚动重建,web 启动时自动执行 kinto migrate 完成数据库模式升级——Kinto 的 schema migration 是内置于启动流程的,无需手工跑迁移。
七、排障实录
7.1 端口映射后 Connection reset by peer
现象:docker compose up -d 后 curl http://127.0.0.1:8149/v1/ 返回 Recv failure: Connection reset by peer,但 docker compose logs web 显示 Serving on http://127.0.0.1:8888。
根因:镜像在构建期执行 kinto init 时未传 --host,内置配置文件监听地址为默认值 127.0.0.1(容器内回环地址);端口映射把宿主机 8149 转发到服务网卡 8888,但服务只接受来自容器内回环的连接,内核直接重置。CLI 的 --host 参数只属于 kinto init(决定写进 ini 的监听地址),kinto start 没有 host 参数。
处置:按官方"自定义配置文件"范式,kinto init --host 0.0.0.0 重新生成配置并挂载覆盖 /etc/kinto/kinto.ini(见 2.3),重启后日志变为 Serving on http://0.0.0.0:8888,访问恢复。
7.2 模板生成的 cache_url 键对 Memcached 无效
现象:kinto init --cache-backend memcached 生成的配置里,Memcached 地址写在了 kinto.cache_url;服务启动后缓存读写异常。
根因:Memcached 缓存后端实现读取的是 kinto.cache_hosts(源码 settings[prefix + "hosts"]),cache_url 是文档/模板间的历史残留键名,只对 PostgreSQL/Redis 类 URL 型后端有效。
处置:把该行改为 kinto.cache_hosts = cache:11211(多节点空格分隔),重启生效。
7.3 挂载目录写权限(uid 10001)
现象:用一次性执行生成配置到挂载目录时报 PermissionError: [Errno 13] Permission denied。
根因:官方镜像以非 root 用户 app(uid 10001)运行,向宿主机挂载目录写文件要求该目录对 uid 10001 可写。
处置:chmod 777 ./config(或 chown 10001)后再执行生成;运行期 web 只需读配置文件,正常权限即可。
7.4 时区警告
启动日志出现 WARNI Database timezone is not UTC (ETC/UTC)——Kinto 期望数据库时区为 UTC,宿主机时区为 Asia/Shanghai 时连接串落到 Etc/UTC 之外的本地时区即触发。记录时间戳仍以毫秒整数返回,功能无碍;对时区敏感的部署可在 PostgreSQL 侧统一 timezone = 'UTC' 消除该警告。