配合 Takuto 使用外部数据库
默认情况下,Takuto 把数据存放在一个本地 SQLite 文件里(数据目录下的 takuto.db)。
若是多用户部署或生产使用,你可以改为把 Takuto 指向一个外部的 PostgreSQL、
MariaDB 或 MySQL 数据库。
用 takuto-cli 接入已有的数据库 container
如果你用 Takuto CLI,且数据库跑在本机的一个 container 里,你不用手动翻译任何东西。
在 takuto setup 时选择 “A database container running on this machine (auto-wire it)”,并按
你从宿主机使用的方式给出 URL —— 也就是你会粘进 psql 或 GUI 客户端的那个 localhost 串:
[database]
connection = "postgres://takuto:<DB_PASSWORD>@localhost:5433/takuto"
local_container = true # 由向导写入 —— 告诉 CLI 在启动时自动接线
之后每次 takuto start,CLI 会 (1) 找到发布该端口的运行中 container 及其内部端口,
(2) 用稳定别名 takuto_db 把它接到 Takuto 的网络上,(3) 把一个面向 container 的
TAKUTO_DATABASE_CONNECTION(…@takuto_db:5432/…)写进 takuto.env,供引擎在启动时使用。
你照旧用 localhost 思考;网络命名空间的翻译交给 CLI。
唯一的要求:在 takuto start 之前先启动你的数据库 container。如果还没有任何东西发布该端口,
CLI 会给出警告并保持连接串不变 —— 把数据库起起来再重跑 takuto start。
远程或宿主机本地的数据库则不同:在向导里选 remote / host-native 选项,并给出一个本身 就可达的 URL。
内置的 Compose overlay
如果你是用 Docker Compose 从 Takuto Core 跑引擎,受支持的路径就是内置的数据库 overlay。它会把数据库添加到正确的网络上,替你注入连接串,并在 Takuto 启动前 等待数据库变为健康状态 —— 从而规避掉下面那两个网络与启动竞态的问题:
# PostgreSQL
docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d
# or: make start BACKEND=postgres
# MariaDB / MySQL
docker compose -f docker-compose.yml -f docker-compose.mariadb.yml up -d
# or: make start BACKEND=mariadb
在你的环境里用 POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB(或对应的 MARIADB_*)
覆盖默认值。这个 overlay 会设置 TAKUTO_DATABASE_CONNECTION(它会覆盖 [database].connection),
所以你不必手动编辑任何连接串,并且首次启动时会跑一次性的 SQLite → 外部数据库导入。
手动来做(直接运行引擎)
如果你不用 CLI、自己运行 Takuto Core,就没有自动接线:你要设置一个 Takuto container 能直接连上的连接串。本页其余部分讲的就是这种情形 —— 你单独运行、或已经在另一个网络上的数据库。
最要紧的一条规则
config.toml 里的连接串是由 Takuto container 本身使用的。所以那个串里的主机
必须从该 container 内部可达:
- ✅ 如果你的数据库作为另一个 container 运行,请使用它的 container/服务名及其 内部端口,并确保两个 container 共享同一个网络。
- ❌ 不要用
localhost或127.0.0.1—— 在 Takuto container 内部,这指回的是 Takuto 自己,而非你的数据库。 - ❌ 不要用宿主发布的端口(例如
-p 5433:5432这样的映射)。那个端口只存在于你 的宿主机上,而不在 container 网络上。
经验法则:
localhost:<published-port>是用来从你的宿主机连接的(psql、某个 GUI 客户端)。<container-name>:<internal-port>才是给 Takuto 用的。
复用你已经有的数据库 container
已经在某个 container 里跑着 PostgreSQL(或 MariaDB/MySQL)—— 也许来自另一个 Compose
项目?不用重建。把它接到 takuto container 实际使用的网络上 —— 即 dind sidecar 的网络
—— 给它一个稳定的别名,再用这个别名构造连接串:
# 1. 找到 dind sidecar(也即 takuto)所在的网络:
docker inspect takuto-dind | grep -A8 '"Networks"'
# 2. 用一个稳定的别名把你已有的 DB container 接到该网络:
docker network connect --alias takuto_db <第1步得到的网络> <你的-db-container>
# 3. 用别名 + 数据库的内部端口构造连接串,例如:
# postgresql://<user>:<password>@takuto_db:5432/<db>
连接串里的 host 是这个别名(takuto_db)—— 绝不是 localhost —— 端口是 container 的
内部端口(5432 / 3306),而不是用 -p 发布的端口。把它填进 [database].connection
(第 2 步)并重启。下面的步骤则介绍如何从零创建一个数据库。
第 1 步 —— 在 Takuto 的网络上跑一个数据库 container
Takuto 的各 container 共享一个 Docker/Podman 网络(通过 Compose 启动时,就是该项目的
默认网络,例如 <project>_default)。把你的数据库放到同一个网络上。最简单的做法是把
数据库作为一个服务加到同一个 Compose 文件里,让它自动加入;或者,把它独立运行并挂接到该
网络上。
每种引擎都需要在首次启动时创建一个数据库和一个应用用户:
PostgreSQL
docker run -d --name takuto_db --network <takuto-network> \
-e POSTGRES_USER=takuto \
-e POSTGRES_PASSWORD='<DB_PASSWORD>' \
-e POSTGRES_DB=takuto \
-v takuto_db-data:/var/lib/postgresql/data \
-p 5433:5432 \
postgres:16-alpine
MariaDB
docker run -d --name takuto_db --network <takuto-network> \
-e MARIADB_ROOT_PASSWORD='<ROOT_PASSWORD>' \
-e MARIADB_DATABASE=takuto \
-e MARIADB_USER=takuto \
-e MARIADB_PASSWORD='<DB_PASSWORD>' \
-v takuto_db-data:/var/lib/mysql \
-p 3306:3306 \
mariadb:11
MySQL
docker run -d --name takuto_db --network <takuto-network> \
-e MYSQL_ROOT_PASSWORD='<ROOT_PASSWORD>' \
-e MYSQL_DATABASE=takuto \
-e MYSQL_USER=takuto \
-e MYSQL_PASSWORD='<DB_PASSWORD>' \
-v takuto_db-data:/var/lib/mysql \
-p 3306:3306 \
mysql:8
持久化: 上面那个
-v takuto_db-data:/…命名卷,正是让你的数据在 container 重建后 依然留存的关键。没有它,删除 container 就会删掉数据。
究竟哪个网络才是 “Takuto 的网络”? 这正是大家容易栽跟头的地方。当 Docker-in-Docker sidecar 启用时,
takutocontainer 没有属于自己的网络 —— 它共享dindcontainer 的 网络命名空间(network_mode: service:dind)。所以真正要紧的网络,是dindcontainer 所 挂接的那个(通常是 Compose 项目的默认网络,例如takuto-core_default),而不是一个以 Takuto 命名的网络。用这条命令找到它:docker inspect <dind-container> | grep -A8 '"Networks"'把你的数据库挂接到那个网络上,并按它在该网络上的名称/别名来引用它。
数据库已经跑在另一个网络上了? 你不必重建它 —— 把它桥接到 Takuto 的网络上,并赋予它你 连接串所期望的那个别名:
docker network connect --alias takuto_db <takuto-network> <your-db-container>
--alias takuto_db会让该数据库在那个网络上解析为takuto_db,于是像…@takuto_db:5432/…这样的连接串无需改动便能继续工作。
第 2 步 —— 在 config.toml 里设置连接串
编辑 .takuto/config.toml 的 [database] 小节:
[database]
connection = "<CONNECTION_STRING>"
fail_fast = true # 数据库不可达时中止启动(推荐)
import_from_sqlite = true # 首次连接时迁移已有的本地 SQLite 数据
为你的引擎使用对应的 scheme 和内部端口,并以数据库的 container 名作为主机:
| 引擎 | 连接串 |
|---|---|
| PostgreSQL | postgresql://takuto:<DB_PASSWORD>@takuto_db:5432/takuto |
| MariaDB | mysql://takuto:<DB_PASSWORD>@takuto_db:3306/takuto |
| MySQL | mysql://takuto:<DB_PASSWORD>@takuto_db:3306/takuto |
MariaDB 和 MySQL 都使用 mysql:// scheme。注意这里是内部端口(5432 / 3306)——
而不是 -p 里发布出来的那个。
第 3 步 —— 重启 Takuto
Takuto 在启动时读取 config.toml,所以重启它以应用变更:
takuto restart
第 4 步 —— 验证
查看 Takuto 的日志。一次成功的连接会记录类似这样的内容:
Multi-user database initialized (external backend) backend="postgres" url="postgresql://takuto:****@takuto_db:5432/takuto"
在 fail_fast = true 时,配置错误或不可达的数据库会让启动中止并报错,而不是悄悄回退到
SQLite —— 所以一次干净的启动就意味着外部数据库已被启用。当 Takuto 的 egress 层识别出
该主机时,它也会记录 Allowing database sidecar: takuto_db:5432。你也可以连上数据库,确认
Takuto 的那些表(users、sessions、credentials、repositories 等等)已被创建。
从你的宿主机连接(可选)
要用本地客户端检视数据库,请使用发布出来的端口(-p),并经由 localhost 连接:
postgresql://takuto:<DB_PASSWORD>@localhost:5433/takuto
mysql://takuto:<DB_PASSWORD>@localhost:3306/takuto
这是唯一一处 localhost 是正确的地方 —— 因为你是从宿主机连接的,而不是从 Takuto
container 内部。
故障排查
| 症状 | 可能原因 |
|---|---|
启动时 pool timed out / connection refused | 连接串用了 localhost 或发布出来的端口,而非 <container-name>:<internal-port>;又或者数据库 container 不在 Takuto 的网络上。 |
启动时 Database backend unreachable | 两种常见原因:(1) 当 Takuto 跑那个 5 秒的 SELECT 1 探测时,数据库还没准备好接受连接 —— 一种启动竞态;或 (2) 数据库不在 Takuto 的网络上。修复办法:使用内置的 overlay(它会等待数据库的健康检查)、确保数据库在 Takuto 启动前已经起来且健康,或把数据库挂接到 dind container 的网络上(见第 1 步)。 |
| 启动立即中止 | fail_fast = true 且数据库不可达或凭据有误 —— 修正连接串/凭据。(在 fail_fast = false 时,它会改为记录一条警告并回退到 SQLite。) |
| 重建数据库 container 后数据消失 | 没有挂接命名卷;加上一个(第 1 步)。 |
| 认证 / 访问错误 | 应用用户/数据库没有被创建,或连接串里的密码与 container 的环境变量不一致。 |
完整的键集(连接池大小、超时、SQLite 导入)见 [database] 参考。