Usar una base de datos externa con Takuto

Por defecto, Takuto guarda sus datos en un archivo SQLite local (takuto.db en el directorio de datos). Para configuraciones multiusuario o uso en producción, puedes apuntar Takuto a una base de datos externa PostgreSQL, MariaDB o MySQL en su lugar.

Conectar un container de base de datos existente con takuto-cli

Si usas el CLI de Takuto y tu base corre en un container en esta máquina, no traduces nada a mano. Durante takuto setup, elige «A database container running on this machine (auto-wire it)» y da la URL tal y como la usarías desde tu host — la de localhost que pegarías en psql o un cliente GUI:

[database]
connection = "postgres://takuto:<DB_PASSWORD>@localhost:5433/takuto"
local_container = true   # lo pone el asistente — indica al CLI que cablee al arrancar

En cada takuto start, el CLI (1) encuentra el container que publica ese puerto y su puerto interno, (2) lo conecta a la red de Takuto bajo el alias estable takuto_db, y (3) escribe una TAKUTO_DATABASE_CONNECTION orientada al container (…@takuto_db:5432/…) en takuto.env, que el motor usa al arrancar. Sigues pensando en localhost; el CLI hace la traducción de namespace de red.

El único requisito: arranca tu container de base de datos antes de takuto start. Si nada publica ese puerto todavía, el CLI avisa y deja la cadena sin cambios — levanta la base y vuelve a ejecutar takuto start.

Una base remota o nativa del host es distinta: elige la opción remote / host-native en el asistente y da una URL ya alcanzable tal cual.

El overlay de Compose incluido

Si ejecutas el motor desde Takuto Core con Docker Compose, la vía soportada es el overlay de base de datos incluido. Añade la base de datos en la red correcta, inyecta la cadena de conexión por ti y espera a que la base de datos esté sana antes de que Takuto arranque — lo que esquiva tanto el problema de red como el de carrera en el arranque que se describen más abajo:

# 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

Anula los valores por defecto con POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB (o los equivalentes MARIADB_*) en tu entorno. El overlay fija TAKUTO_DATABASE_CONNECTION (que anula [database].connection), así que no editas ninguna cadena a mano, y en el primer arranque se ejecuta una importación única de SQLite → externa.

Hacerlo a mano (ejecutando el motor directamente)

Si ejecutas Takuto Core tú mismo sin el CLI, no hay cableado automático: defines una cadena de conexión que el container Takuto pueda alcanzar tal cual. El resto de esta página cubre ese caso — una que ejecutas por separado, o que ya vive en otra red.

La regla que más importa

La cadena de conexión de config.toml la usa el propio container de Takuto. Así que el host de esa cadena debe ser alcanzable desde dentro de ese container:

  • ✅ Si tu base de datos corre como otro container, usa su nombre de container/servicio y su puerto interno, y asegúrate de que ambos containers comparten una red.
  • No uses localhost ni 127.0.0.1 — dentro del container de Takuto eso apunta de vuelta a Takuto, no a tu base de datos.
  • No uses el puerto publicado en el host (p. ej. un mapeo -p 5433:5432). Ese puerto solo existe en tu máquina host, no en la red de containers.

Regla práctica: localhost:<puerto-publicado> es para conectarte desde tu máquina host (psql, un cliente GUI). <nombre-container>:<puerto-interno> es para Takuto.

Reutilizar un container de base de datos que ya tienes

¿Ya tienes PostgreSQL (o MariaDB/MySQL) corriendo en un container — quizá de otro proyecto Compose? No lo recrees. Conéctalo a la red que el container takuto usa de verdad — la del sidecar dind — dale un alias estable y construye la cadena a partir de ese alias:

# 1. Encuentra la red del sidecar dind (y por tanto de takuto):
docker inspect takuto-dind | grep -A8 '"Networks"'

# 2. Conecta tu container de DB existente a esa red, con un alias estable:
docker network connect --alias takuto_db <red-del-paso-1> <tu-container-db>

# 3. Construye la cadena con el alias + el puerto INTERNO de la base, p. ej.:
#    postgresql://<user>:<password>@takuto_db:5432/<db>

El host es el alias (takuto_db) — nunca localhost — y el puerto es el puerto interno del container (5432 / 3306), no un puerto publicado con -p. Ponla en [database].connection (Paso 2) y reinicia. Los pasos de abajo cubren crear una base desde cero.

Paso 1 — Ejecuta un container de base de datos en la red de Takuto

Los containers de Takuto comparten una red de Docker/Podman (cuando se arrancan vía Compose, es la red por defecto del proyecto, p. ej. <project>_default). Pon tu base de datos en esa misma red. Lo más sencillo es añadir la base de datos como un servicio en el mismo archivo de Compose para que se una automáticamente; como alternativa, ejecútala de forma autónoma y conéctala a la red.

Cada motor necesita una base de datos y un usuario de aplicación creados en el primer arranque:

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

Persistencia: el volumen con nombre -v takuto_db-data:/… de arriba es lo que hace que tus datos sobrevivan a la recreación del container. Sin él, eliminar el container borra los datos.

¿Cuál es “la red de Takuto”? Esta es la parte que más despista. Cuando el sidecar de Docker-in-Docker está activado, el container takuto no tiene red propia — comparte el namespace de red del container dind (network_mode: service:dind). Así que la red que importa es aquella a la que está conectado el container dind (normalmente la red por defecto del proyecto de Compose, p. ej. takuto-core_default), no una red con el nombre de Takuto. Encuéntrala con:

docker inspect <dind-container> | grep -A8 '"Networks"'

Conecta tu base de datos a esa red y refiérete a ella por su nombre/alias en ella.

¿La base de datos ya corre en otra red? No tienes que recrearla — puéntala a la red de Takuto y dale el alias que espera tu cadena de conexión:

docker network connect --alias takuto_db <takuto-network> <your-db-container>

El --alias takuto_db hace que la base de datos se resuelva como takuto_db en esa red, así que una cadena de conexión como …@takuto_db:5432/… sigue funcionando sin cambios.

Paso 2 — Fija la cadena de conexión en config.toml

Edita la sección [database] de .takuto/config.toml:

[database]
connection = "<CONNECTION_STRING>"
fail_fast = true          # abort startup if the DB is unreachable (recommended)
import_from_sqlite = true # migrate existing local SQLite data on first connect

Usa el esquema y el puerto interno de tu motor, con el nombre del container de la base de datos como host:

MotorCadena de conexión
PostgreSQLpostgresql://takuto:<DB_PASSWORD>@takuto_db:5432/takuto
MariaDBmysql://takuto:<DB_PASSWORD>@takuto_db:3306/takuto
MySQLmysql://takuto:<DB_PASSWORD>@takuto_db:3306/takuto

Tanto MariaDB como MySQL usan el esquema mysql://. Fíjate en los puertos internos (5432 / 3306) — no en los publicados con -p.

Paso 3 — Reinicia Takuto

Takuto lee config.toml al arrancar, así que reinícialo para aplicar el cambio:

takuto restart

Paso 4 — Verifica

Revisa los logs de Takuto. Una conexión correcta registra algo como:

Multi-user database initialized (external backend)  backend="postgres"  url="postgresql://takuto:****@takuto_db:5432/takuto"

Con fail_fast = true, una base de datos mal configurada o inalcanzable hace que el arranque aborte con un error en lugar de recurrir silenciosamente a SQLite — así que un arranque limpio significa que la base de datos externa está en uso. La capa de egress de Takuto también registra Allowing database sidecar: takuto_db:5432 cuando reconoce el host. También puedes conectarte a la base de datos y confirmar que se crearon las tablas de Takuto (users, sessions, credentials, repositories, …).

Conectarte desde tu máquina host (opcional)

Para inspeccionar la base de datos con un cliente local, usa el puerto publicado (-p) y conéctate vía localhost:

postgresql://takuto:<DB_PASSWORD>@localhost:5433/takuto
mysql://takuto:<DB_PASSWORD>@localhost:3306/takuto

Este es el único sitio donde localhost es correcto — porque te conectas desde el host, no desde dentro del container de Takuto.

Solución de problemas

SíntomaCausa probable
pool timed out / connection refused al arrancarLa cadena usa localhost o el puerto publicado en lugar de <nombre-container>:<puerto-interno>; o el container de la BD no está en la red de Takuto.
Database backend unreachable al arrancarDos causas habituales: (1) la base de datos aún no aceptaba conexiones cuando se ejecutó la sonda SELECT 1 de 5 s de Takuto — una carrera en el arranque; o (2) la BD no está en la red de Takuto. Soluciones: usa el overlay incluido (espera al health check de la BD), asegúrate de que la BD está levantada y sana antes de que Takuto arranque, o conecta la BD a la red del container dind (consulta el Paso 1).
El arranque aborta de inmediatofail_fast = true y la BD es inalcanzable o las credenciales son incorrectas — corrige la cadena/las credenciales. (Con fail_fast = false registra un warning y recurre a SQLite en su lugar.)
Los datos desaparecieron tras recrear el container de la BDNo se conectó ningún volumen con nombre; añade uno (Paso 1).
Errores de auth / accesoNo se creó el usuario/la base de datos de la aplicación, o la contraseña de la cadena no coincide con las variables de entorno del container.

Consulta la referencia de [database] para el conjunto completo de claves (tamaño del pool, timeouts, importación desde SQLite).