Desplegar una app de Rails
Rails 7.1 y posteriores generan un Dockerfile de producción, y Lizard (lizard.build) lo compila tal cual: la imagen instala las gems, precompila los assets y ejecuta bin/rails db:prepare cada vez que arranca el servidor. Define RAILS_MASTER_KEY y las URL de las bases de datos y luego ejecuta lizard up --port 8080 para Rails 8 (con HTTP_PORT=8080 para Thruster) o lizard up --port 3000 para Rails 7.1 y 7.2. Sin Dockerfile, lizardpack compila una imagen de Ruby básica en el puerto 3000.
Estado de las pruebas: revisamos el Dockerfile, bin/docker-entrypoint, config/puma.rb y database.yml que genera Rails, las reglas de compilación y de puertos de Lizard y el plan de lizardpack para una app de Rails sin Dockerfile. Todavía no hemos desplegado una app de Rails de principio a fin con esta guía.
Antes de empezar
- Una app de Rails 7.1 o posterior que use PostgreSQL (la gem
pg) y que conserve elDockerfiley elbin/docker-entrypointgenerados. Una app más antigua puede obtenerlos con la gem dockerfile-rails:bundle add dockerfile-rails --group developmenty luegobin/rails generate dockerfile. config/master.keyen tu equipo, o elSECRET_KEY_BASEde la app.- Un
Gemfile.lockque incluya la plataformax86_64-linux. Añádela conbundle lock --add-platform x86_64-linuxy haz commit del archivo. - Lizard CLI, con la sesión iniciada mediante
lizard login, en Pro o en la prueba de Pro de 7 días (se requiere tarjeta). Consulta los precios.
Cómo compila Lizard una app de Rails
| Tu app tiene | Lizard compila | Puerto del servicio |
|---|---|---|
El Dockerfile de Rails 8 (EXPOSE 80, CMD ["./bin/thrust", "./bin/rails", "server"]) | Tu Dockerfile, tal cual | 8080, con HTTP_PORT=8080 |
El Dockerfile de Rails 7.1 o 7.2 (EXPOSE 3000) | Tu Dockerfile, tal cual | 3000 |
| Ningún Dockerfile | La imagen de Ruby de lizardpack; consulta más abajo | 3000 |
Deja vacíos los comandos de compilación e inicio del servicio. Si defines cualquiera de los dos, Lizard escribe su propio Dockerfile a partir de esos comandos en lugar de usar el tuyo, y esa imagen trae Node.js, no Ruby. Un comando de inicio también sustituye el entrypoint de la imagen, así que db:prepare no se ejecutaría. Consulta el orden de decisión de compilación.
Rails 8 inicia Thruster, que escucha en el puerto 80 y ejecuta Puma detrás, en el puerto 3000. La imagen se ejecuta como usuario sin privilegios de root (USER 1000:1000), y un proceso sin root puede no tener permiso para abrir un puerto por debajo de 1024. HTTP_PORT=8080 mueve Thruster a un puerto que siempre puede abrir.
Crear el proyecto y la base de datos
Desde el directorio raíz de la app:
lizard init --name rails-app
lizard add --service web
lizard add postgresManaged Postgres se conecta como el superusuario postgres, así que db:prepare puede crear las bases de datos que pide Rails.
Configurar los secretos y desplegar (Rails 8)
El database.yml de producción de Rails 8 define cuatro bases de datos: primary, cache, queue y cable. DATABASE_URL solo sustituye a primary. Para las demás, Rails lee CACHE_DATABASE_URL, QUEUE_DATABASE_URL y CABLE_DATABASE_URL. Apunta las cuatro al mismo Postgres con distintos nombres de base de datos:
PG='postgresql://postgres:${{postgres.PGPASSWORD}}@${{postgres.LIZARD_PRIVATE_DOMAIN}}:5432'
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
CACHE_DATABASE_URL="$PG/rails_cache" \
QUEUE_DATABASE_URL="$PG/rails_queue" \
CABLE_DATABASE_URL="$PG/rails_cable" \
HTTP_PORT=8080 \
SOLID_QUEUE_IN_PUMA=true \
--service web
lizard up --service web --port 8080- Las comillas simples evitan que tu shell interprete
${{…}}. Lizard resuelve estas referencias al desplegar y usa la red privada del proyecto. SOLID_QUEUE_IN_PUMA=truehace que Puma ejecute el worker de Solid Queue, así que los trabajos de Active Job se ejecutan dentro del servicio web. Sin esta variable, los trabajos en cola esperan para siempre.- Usa
SECRET_KEY_BASEen lugar deRAILS_MASTER_KEYsolo si la app no lee ninguna otra credencial cifrada.
Configurar los secretos y desplegar (Rails 7.1 y 7.2)
Estas versiones usan una sola base de datos:
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
--service web
lizard up --service web --port 3000Qué ocurre en cada despliegue
lizard up sube el directorio. Dentro de un repositorio git omite lo que aparece en .gitignore, y tanto el .gitignore como el .dockerignore de Rails excluyen config/master.key y los archivos .env*. La compilación precompila los assets con SECRET_KEY_BASE_DUMMY=1, porque Lizard no pasa ninguna variable a una compilación con Dockerfile salvo COMMIT_SHA.
Al arrancar, bin/docker-entrypoint ejecuta ./bin/rails db:prepare: crea las bases de datos que faltan, carga el esquema en las nuevas y ejecuta las migraciones pendientes. Se ejecuta en cada arranque del contenedor, incluidos los reinicios. Asegúrate de que las migraciones funcionen tanto con el código antiguo como con el nuevo.
Para usar git push to deploy, sube la app a GitHub y conecta el repositorio en lugar de ejecutar lizard up. Configura los mismos secretos y el mismo puerto (lizard port 8080 --service web). El Dockerfile generado tiene un paso bundle install, así que Lizard lo usa tal cual.
Comprobar que funciona
lizard logs --build --service web
lizard logs --service web --tail 100
lizard domain --service webRails 7.1 y posteriores responden a /up con HTTP 200 en cuanto la app arranca. Abre https://<your-domain>/up y luego una página que lea de la base de datos. El log de ejecución debería mostrar la salida de db:prepare y después el arranque de Puma.
Sin Dockerfile
lizardpack compila una app de Ruby cuando encuentra un Gemfile:
- Versión de Ruby:
.ruby-version; si no, la línearubydelGemfile; si no,3.4. Solo cuentan las versiones principal y secundaria:3.4.1se compila sobreruby:3.4-slim. - Instala
build-essentialylibpq-devy luego ejecutabundle install. - Inicio: la línea
web:del Procfile; si no,bundle exec rails server -b 0.0.0.0cuando existenconfig.ruyRakefile. Puerto3000.
Esta imagen no define RAILS_ENV, no precompila los assets ni prepara la base de datos, así que encaja mejor con apps pequeñas y APIs que con un sitio Rails completo. Escribe .ruby-version como un número sin más, por ejemplo 3.4.1. rails new escribe ruby-3.4.1, y lizardpack lo convierte en un nombre de imagen que no existe. Consulta versiones del entorno de ejecución.
Problemas comunes
| Síntoma | Solución |
|---|---|
bundle install falla: el bundle solo admite otras plataformas | Ejecuta bundle lock --add-platform x86_64-linux y haz commit de Gemfile.lock. |
Missing secret_key_base o las credenciales no se descifran | Define RAILS_MASTER_KEY a partir de config/master.key en el servicio web. |
La conexión de caché, cola o cable va a un socket local como /var/run/postgresql | Define CACHE_DATABASE_URL, QUEUE_DATABASE_URL y CABLE_DATABASE_URL. |
Los logs muestran bind: permission denied para el puerto 80 | Define HTTP_PORT=8080 y pon el puerto del servicio en 8080. |
| El despliegue nunca alcanza el estado healthy | Comprueba que el puerto del servicio coincide con la tabla de arriba: lizard port --service web. Consulta el servicio nunca alcanza el estado healthy. |
| Los trabajos se quedan en cola | Define SOLID_QUEUE_IN_PUMA=true. Para ejecutar los trabajos fuera del proceso web, añade un segundo servicio en modo worker con dockerfilePath=Dockerfile y startCommand=./bin/jobs. |
| Los archivos subidos desaparecen tras un despliegue | El servicio local de Active Storage escribe dentro del contenedor. Usa Managed Object Storage, que es compatible con S3, con el servicio amazon. |
Si la app usa Sidekiq o un adaptador de Redis para Action Cable, añade Managed Redis y define REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' en cada servicio que lo necesite.
Relacionado
- Desplegar un contenedor Docker desde un Dockerfile
- Variables y secretos
- Managed Postgres
- Pipeline de compilación
- Almacenamiento y recuperación
Actualizado