La aplicación
Podman
Ejecutar estos archivos compose y contenedores con Podman en vez de Docker: la distinción entre podman compose y podman-compose, y las notas sobre rootless
Esta página es una traducción automática de la documentación en inglés.
Cada comando de docker compose y docker run en esta documentación también funciona con Podman. Cambia docker por podman. Esta página documenta la trampa de los nombres y las diferencias en modo rootless una sola vez. Otros documentos enlazan aquí directamente en lugar de repetirlas.
podman compose no es podman-compose
Son dos herramientas distintas. La equivocada ejecuta una implementación menos compatible sin avisar.
podman compose(con espacio) es un subcomando integrado en Podman. Es un envoltorio ligero. Localiza un proveedor de compose externo en tu equipo, ya seadocker-composeopodman-compose, y le delega el comando. Si tienesdocker-composeinstalado, Podman lo usa primero. Es la implementación original de la especificación Compose. Ejecutapodman compose versionpara ver el proveedor impreso en un encabezado.podman-compose(con guion) es una implementación independiente de la especificación Compose basada en Python. Se ejecuta por sí misma sin Docker. Soporta una parte menor de la especificación. Su soporte paradepends_on: condition: service_healthyes más débil y, por omisión, asigna nombres distintos a las redes.
Sin un proveedor, podman compose no hace nada. Una instalación limpia de Ubuntu 24.04 con solo podman responde a cada comando de podman compose con Error: looking up compose provider failed. Instala un proveedor primero:
sudo apt install podman podman-compose
podman compose version # names /usr/bin/podman-compose, version 1.0.6En ese equipo, podman compose y podman-compose ejecutan el mismo programa. Los healthchecks de estos archivos compose funcionan con él. compose.yml y compose.core.yml informaron healthy con podman 4.9.3 y podman-compose 1.0.6, incluida la espera de Postgres. Por este motivo, los healthchecks usan una sola línea directa de shell (wget -q -O /dev/null http://127.0.0.1:3000/...). La sintaxis anterior node -e "fetch(...)" llegaba a podman-compose 1.0.6 como una línea de shell corrupta. En consecuencia, podman ps informaba de unhealthy continuamente mientras la app respondía.
Cada archivo compose que inicia Postgres (compose.core.yml, compose.full.yml y el quickstart de openplate-core compose.yml) usa depends_on: condition: service_healthy para condicionar un servicio al healthcheck de Postgres. Si usas un proveedor distinto, comprueba que soporte esa condición.
Notas sobre rootless
Podman se ejecuta en modo rootless por omisión. Los contenedores corren bajo tu propio usuario, no como root. Esto aporta mayor seguridad. También introduce tres diferencias respecto a Docker que debes conocer antes de hacer el Autoalojamiento.
Etiquetas de volumen en SELinux. En un host con SELinux en modo enforcing, el comportamiento por omisión en Fedora, un contenedor no puede leer ni escribir en un directorio del host montado mediante bind sin una etiqueta de acceso de contenedor. Añade :Z al montaje si solo lo usa un contenedor. Añade :z si lo comparten varios contenedores, por ejemplo -v ./pg-data:/var/lib/postgresql:Z. Ninguno de los archivos compose de estos tres repositorios monta directorios del host con bind. Todos usan volúmenes con nombre, a los que Podman asigna etiquetas automáticamente. Esta nota solo aplica si modificas una entrada de volumes: para usar una ruta del host. Ese cambio afecta a los peldaños de sincronización 2 y 4 para Postgres, y al peldaño de inferencia 3 para los pesos del modelo.
Puertos inferiores a 1024. Un contenedor rootless no puede vincularse a un puerto del host inferior a 1024 sin permisos, por ejemplo mediante sudo sysctl net.ipv4.ip_unprivileged_port_start=80. Ninguno de los puertos por omisión de estos archivos compose (3000, 3001, 8300) necesita esto. Este problema solo surge si reasignas un puerto a 80 o 443 para prescindir de un proxy inverso. Como cada peldaño publica al menos un puerto, esto puede afectar a cualquiera de los 4 peldaños.
Postgres sin permisos de root. El contenedor de Postgres se ejecuta con un usuario que no es root. Ese usuario debe ser propietario de su directorio de datos. Un volumen con nombre resuelve esto de forma automática, y apps/core/docker/compose.yml, compose.core.yml y compose.full.yml ya lo usan. Podman crea el volumen con nombre asignando la propiedad correcta. Si cambias a un directorio del host montado mediante bind, define la propiedad desde el host primero con podman unshare chown -R 70:70 ./pg-data. El ID de usuario 70 corresponde al usuario postgres en la imagen fija postgres:18-alpine; las imágenes de Debian usan 999. Sin este paso, el contenedor falla al iniciar con un error de permisos. Esto afecta a los peldaños 2 y 4.
Unidades de Quadlet
Quadlet no usa ni podman compose ni podman-compose: el propio systemd inicia cada contenedor con podman. Si solo vas a usar Quadlet, omite la instalación del proveedor descrita arriba.
Cada archivo compose anterior se distribuye también como unidades de systemd rootless. Las genera scripts/quadlet.sh y se guardan en docker/quadlet/. Un conjunto de unidades persiste entre reinicios bajo systemctl --user sin un proceso de compose activo. Cada directorio incluye un README con pasos de instalación, los archivos de entorno que lee cada unidad y registros de ejecuciones de prueba:
- app: nivel 1, la app en solitario
- core: nivel 2, Postgres, la app y openplate-core
- inference: nivel 3, openplate-inference y la app
- full: nivel 4, los cuatro
- openplate-core: el servidor central por separado
- openplate-inference: el endpoint de inferencia por separado
Elige una sola vía: compose o Quadlet, nunca ambas. Una unidad personalizada de systemd que ejecute podman compose up y un conjunto de unidades Quadlet realizan la misma tarea. Si instalas ambos, entrarán en conflicto en el arranque por el puerto 3000. Elimina el servicio existente antes de cambiar a Quadlet. Para desinstalar Quadlet, sigue los pasos de desinstalación en el README del escenario.
Dos cosas a tener en cuenta antes de empezar, en cualquier Podman:
- No existe ningún paso de
systemctl --user enable. El generador de Podman crea los servicios. No puedes habilitar unidades generadas. Ejecutar ese comando devuelveFailed to enable unit: Unit /run/user/1000/systemd/generator/app.service is transient or generated.Este comportamiento es normal. El inicio automático depende de la línea[Install] WantedBy=default.targetde cada unidad, junto conloginctl enable-linger "$USER". Ese comando inicia la instancia de systemd de tu usuario en el arranque en lugar de esperar al primer inicio de sesión. - Cualquier ajuste se define en
<unit>.env, nunca en la unidad. Cada unidad lee dos archivos de entorno de su propio directorio:<unit>.defaults.env, que se distribuye con las unidades y contiene los valores por omisión de compose, y después<unit>.env, que es el tuyo. Podman los lee en ese orden, por lo que una línea en el tuyo tiene prioridad. Tu archivo debe existir, aunque esté vacío, o el contenedor no iniciará. Una actualización vuelve a copiar las unidades y los archivos por omisión y deja intacto tu archivo. El README del escenario lista los valores que la gente suele cambiar.
Podman 4.9, la versión de Ubuntu 24.04, difiere de Podman 5 en dos aspectos:
- Ignora
Notify=healthy, que requiere Podman 5.0 o superior. Por ello,systemctl --user starttermina aproximadamente un segundo tras el arranque del contenedor, antes de que se complete el healthcheck. Una unidad conRequires=no esperará al estado de salud dependiente. Comprueba el estado del contenedor manualmente:bashuntil [ "$(podman inspect --format '{{.State.Health.Status}}' systemd-app)" = healthy ]; do sleep 5; done
- No lee ningún directorio drop-in (
app.container.d/*.conf). Los archivos que coloques allí no tienen ningún efecto. Las unidades no necesitan ninguno: cada valor que puedes cambiar se lee desde<unit>.env.