Aprende a implementar una aplicación de Rails de muestra en Cloud Run y a integrar bases de datos administradas, almacenamiento de objetos, secretos encriptados y canalizaciones de compilación con procesamiento sin servidores.
La implementación de aplicaciones de Rails implica integrar varios servicios para formar un proyecto cohesivo. En este instructivo, se supone que estás familiarizado con el desarrollo web de Rails.
Para este instructivo debes tener Ruby 3.0 o posterior (también se admite Ruby 2.7. Consulta la sección Comprende el código) y Rails 6 o posterior.
Objetivos
- Crear y conectar una base de datos de Cloud SQL a Active Record
- Crea y usa Secret Manager para almacenar y acceder de forma segura a una clave maestra de Rails
- Aloja archivos multimedia subidos por el usuario en Cloud Storage desde Active Storage
- Usa Cloud Build para automatizar las migraciones de compilación y base de datos
- Implementa una app de Rails en Cloud Run
Costos
Antes de comenzar
- Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.
-
Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.
-
Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
- Asegúrate de otorgarle los permisos suficientes a la cuenta que se usa en este instructivo.
Prepara tu entorno
Configura el proyecto predeterminado
Establece la configuración predeterminada del proyecto para la CLI de gcloud mediante la ejecución del siguiente comando:
gcloud config set project PROJECT_ID
Reemplaza PROJECT_ID
por el ID del proyecto de Google Cloud recién creado.
Clona la app de Rails
El código de la app de muestra de Rails está en el repositorio GoogleCloudPlatform/ruby-docs-samples
en GitHub.
Clone el repositorio:
git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples.git
Ve al directorio que contiene el código de muestra y ejecuta los siguientes comandos para asegurarte de que la aplicación esté configurada correctamente con las gemas y las dependencias requeridas:
Linux/macOS
cd ruby-docs-samples/run/rails bundle install
Windows
cd ruby-docs-samples\run\rails bundle install
Prepara los servicios de copia de seguridad
En este instructivo, se usan varios servicios de Google Cloud para proporcionar la base de datos, el almacenamiento multimedia y el almacenamiento secreto que admiten el proyecto de Rails implementado. Estos servicios se implementan en una región específica. Para la eficiencia entre servicios, es mejor que todos los servicios se implementen en la misma región. Para obtener más información sobre la región más cercana a tu ubicación, consulta Productos disponibles por región.
Configura una instancia de Cloud SQL para PostgreSQL
Rails admite varias bases de datos relacionales, incluidas varias que ofrece Cloud SQL. En este instructivo, se usa PostgreSQL, una base de datos de código abierto que las apps de Rails usan con frecuencia.
En las siguientes secciones, se describe la creación de una instancia de PostgreSQL, una base de datos y un usuario de base de datos para tu app de Rails.
Crear una instancia de PostgreSQL
Console
En Google Cloud Console, ve a la página Instancias de Cloud SQL.
Haga clic en Crear instancia.
Haz clic en Elegir PostgreSQL.
En el campo ID de instancia, ingresa un nombre para la instancia (
INSTANCE_NAME
).En el campo Contraseña, ingresa una contraseña para el usuario de postgres.
Usa los valores predeterminados en los otros campos.
Haga clic en Crear instancia.
gcloud
Crea la instancia de PostgreSQL:
gcloud sql instances create INSTANCE_NAME \ --database-version POSTGRES_12 \ --tier db-f1-micro \ --region REGION
Reemplaza lo siguiente:
INSTANCE_NAME
: Es el nombre de la nueva instancia de Cloud SQL.REGION
: Es la región de Google Cloud.
La instancia demora unos minutos en crearse y estar lista para su uso.
Crea una base de datos
Console
En Google Cloud Console, ve a la página Instancias de Cloud SQL.
Selecciona la instancia INSTANCE_NAME.
Ve a la pestaña Bases de datos.
Haga clic en Create database.
En el diálogo Nombre de la base de datos, ingresa
DATABASE_NAME
.Haga clic en Crear.
gcloud
Crea la base de datos dentro de la instancia recién creada:
gcloud sql databases create DATABASE_NAME \ --instance INSTANCE_NAME
Reemplaza
DATABASE_NAME
por un nombre para la base de datos dentro de la instancia.
Crea un usuario
Genera una contraseña aleatoria para el usuario de la base de datos y escríbela en un archivo llamado dbpassword
:
cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n1 > dbpassword
Console
En Google Cloud Console, ve a la página Instancias de Cloud SQL.
Selecciona la instancia INSTANCE_NAME.
Ve a la pestaña Usuarios.
Haz clic en Agregar cuenta de usuario.
En el cuadro de diálogo Autenticación integrada, realiza lo siguiente:
- Ingresa el nombre de usuario
DATABASE_USERNAME
. - Ingresa el contenido del archivo
dbpassword
como contraseñaPASSWORD
.
- Ingresa el nombre de usuario
Haga clic en Agregar.
gcloud
Crea el usuario en la instancia creada recientemente y establece su contraseña para que sea el contenido de dbpassword:
gcloud sql users create DATABASE_USERNAME \ --instance=INSTANCE_NAME --password=$(cat dbpassword)
Reemplaza
DATABASE_USERNAME
por un nombre para el usuario dentro de la instancia.
Configure un bucket de Cloud Storage
Puedes alojar elementos estáticos de Rails y medios subidos por el usuario en el almacenamiento de objetos con alta disponibilidad a través de Cloud Storage.
Console
- In the Google Cloud console, go to the Cloud Storage Buckets page.
- Click Create bucket.
- On the Create a bucket page, enter your bucket information. To go to the next
step, click Continue.
- For Name your bucket, enter a name that meets the bucket naming requirements.
- For Location, select the following: us-central1
- For Choose a default storage class for your data, select the following: Standard.
- For Choose how to control access to objects, select an Access control option.
- For Advanced settings (optional), specify an encryption method, a retention policy, or bucket labels.
- Click Create.
gcloud
La herramienta de línea de comandos de gsutil
se instaló como parte de la instalación de la CLI de gcloud.
Crear un bucket de Cloud Storage Para crear un nombre de depósito único de Cloud Storage, usa el PROJECT_ID y un sufijo de tu elección,
MEDIA_BUCKET_SUFFIX
. En Cloud Storage, los nombres de los depósitos deben ser únicos a nivel global.gsutil mb -l REGION gs://PROJECT_ID-MEDIA_BUCKET_SUFFIX
Después de crear un bucket, cambia los permisos de los objetos de imagen para que todos los usuarios puedan leerlos con el fin de hacer públicas las imágenes.
Console
- En Google Cloud Console, ve a la página Depósitos de Cloud Storage.
En la lista de bucket s, haz clic en el nombre del bucket que deseas hacer público.
Selecciona la pestaña Permisos cerca de la parte superior de la página.
Haz clic en el botón Agregar miembros.
Aparece el cuadro de diálogo Agregar miembros.
En el campo Miembros nuevos, ingresa
allUsers
.En el menú desplegable Seleccionar una función, selecciona el submenú Cloud Storage y haz clic en la opción Visualizador de objetos de almacenamiento.
Haz clic en Guardar.
Una vez que se comparte de forma pública, aparece un ícono de vínculo para cada objeto en la columna de acceso público. Puedes hacer clic en este ícono para obtener la URL del objeto.
Para obtener información detallada sobre los errores en las operaciones de Ruby con errores en Google Cloud Console, consulta Solución de problemas.
gcloud
Usa el comando
gsutil iam ch
para hacer públicos todos los objetos. Usa el valor deMEDIA_BUCKET_SUFFIX
que usaste cuando creaste el depósito.gsutil iam ch allUsers:objectViewer gs://PROJECT_ID-MEDIA_BUCKET_SUFFIX
Almacena valores secretos en el Secret Manager
Ahora que los servicios de copia de seguridad están configurados, Rails necesita información segura, como contraseñas, para acceder a estos servicios. En lugar de colocar estos valores directamente en el código fuente de Rails, en este instructivo se usan credenciales de Rails y Secret Manager para almacenar esta información de forma segura.
Crea un archivo de credenciales encriptado y almacena la clave como secreto del administrador de secretos
Rails almacena los secretos en un archivo encriptado llamado 'config/credentials.yml.enc'.
El archivo se puede desencriptar con el config/master.key
local o la variable de entorno ENV[“RAILS_MASTER_KEY”]
. En el archivo de credenciales, puedes almacenar la contraseña de la base de datos de la instancia de Cloud SQL y otras claves de acceso para las API externas.
Puedes almacenar esta clave de forma segura en Secret Manager. Luego, puedes otorgar a la clave y Cloud Run acceso a la clave si otorgas acceso a sus respectivas cuentas de servicio. Las cuentas de servicio se identifican mediante una dirección de correo electrónico que contiene el número de proyecto.
Genera el archivo
config/credentials.yml.enc
con el siguiente comando:bin/rails credentials:edit
El comando creará un
config/master.key
si no se define una clave maestra y creará un archivoconfig/credentials.yml.enc
si el archivo no existe. Se abrirá un archivo temporal en tu$EDITOR
predeterminado con el contenido desencriptado para agregar los secretos.Copia y pega la contraseña de la base de datos de la instancia de PostgreSQL recién creada del archivo
dbpassword
al archivo de credenciales:secret_key_base: GENERATED_VALUE gcp: db_password: PASSWORD
Se puede acceder a los secretos con
Rails.application.credentials
. Por ejemplo,Rails.application.credentials.secret_key_base
debe mostrar la base de clave secreta de la aplicación yRails.application.credentials.gcp[:db_passsword]
debe mostrar la contraseña de la base de datos.config/credentials/yml.enc
se almacena encriptado, peroconfig/master.key
se puede almacenar en Secret Manager.Console
En Google Cloud Console, ve a la página Secret Manager.
Haz clic en Crear Secreto.
En el campo Nombre, ingresa un nombre para el secreto
RAILS_SECRET_NAME
.En el cuadro de diálogo Valor del secreto, pega el valor mater.key en el cuadro.
Haz clic en Crear secreto.
En la página de detalles de Secret de tu secreto, toma nota del número del proyecto:
projects/PROJECTNUM/secrets/RAILS_SECRET_NAME
En la pestaña Permisos, haz clic en Agregar miembro.
En el campo Miembros nuevos, ingresa
PROJECTNUM-compute@developer.gserviceaccount.com
y, luego, presionaEnter
.En el campo Miembros nuevos, ingresa
PROJECTNUM@cloudbuild.gserviceaccount.com
y, luego, presionaEnter
.En el menú desplegable Función, selecciona Descriptor de acceso a secretos de Secret Manager.
Haz clic en Guardar.
gcloud
Crea un secreto nuevo con el valor de config/master.key:
gcloud secrets create RAILS_SECRET_NAME --data-file config/master.key
Reemplaza
RAILS_SECRET_NAME
por un nombre para el secreto nuevo.Para confirmar la creación del secreto, revísalo:
gcloud secrets describe RAILS_SECRET_NAME gcloud secrets versions access latest --secret RAILS_SECRET_NAME
Obtén el valor del número de proyecto:
gcloud projects describe PROJECT_ID --format='value(projectNumber)'
Otorga acceso al secreto a la cuenta de servicio de Cloud Run:
gcloud secrets add-iam-policy-binding RAILS_SECRET_NAME \ --member serviceAccount:PROJECTNUM-compute@developer.gserviceaccount.com \ --role roles/secretmanager.secretAccessor
Reemplaza
PROJECTNUM
por el valor del número de proyecto anterior.Otorga acceso al secreto a la cuenta de servicio de Cloud Build:
gcloud secrets add-iam-policy-binding RAILS_SECRET_NAME \ --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \ --role roles/secretmanager.secretAccessor
En el resultado, confirma que
bindings
enumere las dos cuentas de servicio como miembros.
Conecta la app de Rails a la base de datos de producción y al almacenamiento
En este instructivo, se usa una instancia de PostgreSQL como la base de datos de producción y Cloud Storage como el backend de almacenamiento. Para que Rails se conecte a la base de datos y al depósito de almacenamiento recién creados, debes especificar toda la información necesaria a fin de acceder a ellos en el archivo .env
. El archivo .env
contiene la configuración de las variables de entorno de la aplicación. La aplicación leerá este archivo con la gema de puntoenv. Debido a que los secretos se almacenan en credentials.yml.enc
y Secret Manager, no es necesario que .env
se encripte porque no contiene credenciales sensibles.
- Para configurar la app de Rails para que se conecte con la base de datos y el bucket de almacenamiento, abre el archivo
.env
. Modifica la configuración del archivo
.env
de la siguiente manera. Usa el valor deMEDIA_BUCKET_SUFFIX
que usaste cuando creaste el depósito.PRODUCTION_DB_NAME: DATABASE_NAME PRODUCTION_DB_USERNAME: DATABASE_USERNAME CLOUD_SQL_CONNECTION_NAME: PROJECT_ID:REGION:INSTANCE_NAME GOOGLE_PROJECT_ID: PROJECT_ID STORAGE_BUCKET_NAME: PROJECT_ID-MEDIA_BUCKET_SUFFIX
La app de Rails ahora está configurada para usar Cloud SQL y Cloud Storage cuando se implementa en Cloud Run.
Otorga a Cloud Build acceso a Cloud SQL
A fin de que Cloud Build aplique las migraciones de bases de datos, debes otorgar permisos para que Cloud Build acceda a Cloud SQL.
Console
En Google Cloud Console, ve a la página Administración de identidades y accesos.
Para editar la entrada del miembro de
PROJECTNUM@cloudbuild.gserviceaccount.com
, haz clic en Editar miembro.Haz clic en Agregar otra función.
En el diálogo Selecciona una función, elija Cliente de Cloud SQL.
Haga clic en Guardar.
gcloud
Otorga permiso para que Cloud Build acceda a Cloud SQL:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \ --role roles/cloudsql.client
Implementa la app en Cloud Run
Con los servicios de copia de seguridad configurados, ahora puedes implementar la app como un servicio de Cloud Run.
Con el
cloudbuild.yaml
proporcionado, usa Cloud Build para compilar la imagen, ejecutar las migraciones de la base de datos y propagar los elementos estáticos:gcloud builds submit --config cloudbuild.yaml \ --substitutions _SERVICE_NAME=SERVICE_NAME,_INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION,_SECRET_NAME=RAILS_SECRET_NAME
Reemplaza
SERVICE_NAME
por el nombre de tu servicio. Esta primera compilación tarda unos minutos en completarse. Si se agotó el tiempo de espera de la compilación, aumenta el tiempo de espera mediante la inserción de --timeout=2000s en el comando de compilación anterior.Cuando la compilación sea exitosa, implementa el servicio de Cloud Run por primera vez y configura la región de servicio, la imagen base y la instancia conectada de Cloud SQL:
gcloud run deploy SERVICE_NAME \ --platform managed \ --region REGION \ --image gcr.io/PROJECT_ID/SERVICE_NAME \ --add-cloudsql-instances PROJECT_ID:REGION:INSTANCE_NAME \ --allow-unauthenticated
Debería ver un resultado que muestre que la implementación se realizó de forma correcta, con una URL de servicio:
Service [SERVICE_NAME] revision [SERVICE_NAME-00001-tug] has been deployed and is serving 100 percent of traffic at https://SERVICE_NAME-
HASH
-uc.a.run.appPara ver el servicio implementado, ve a la URL del servicio.
Intenta subir una foto nueva. Si la foto se carga correctamente, la aplicación de Rails se implementó correctamente.
Actualizar la aplicación
Si bien los pasos iniciales de implementación y evaluación fueron complejos, realizar actualizaciones es un proceso más simple:
Ejecuta la compilación de Cloud Build y la secuencia de comandos de migración:
gcloud builds submit --config cloudbuild.yaml \ --substitutions _SERVICE_NAME=SERVICE_NAME,_INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION,_SECRET_NAME=RAILS_SECRET_NAME
Implementa el servicio y especifica solo la región y la imagen:
gcloud run deploy SERVICE_NAME \ --platform managed \ --region REGION \ --image gcr.io/PROJECT_ID/SERVICE_NAME
Comprende el código
La app de muestra de Rails se creó con los comandos estándar de Rails. Los siguientes comandos crean la app cat_album y usan el comando scaffold para generar un modelo, un controlador y vistas para el recurso de foto:
rails new cat_album
rails generate scaffold Photo caption:text
Conexión a base de datos
El archivo config/database.yml
contiene la configuración necesaria para acceder a tus bases de datos en diferentes entornos (desarrollo, prueba y producción). Por ejemplo, la base de datos de producción está configurada para ejecutarse en Cloud SQL para PostgreSQL. El nombre y el nombre de usuario de la base de datos se establecen a través de variables de entorno en el archivo .env
, mientras que la contraseña de la base de datos se almacena dentro del archivo config/credentials.yml.enc
, que requiere la desencriptación RAILS_MASTER_KEY
.
Cuando la app se ejecuta en Cloud Run (completamente administrado), se conecta a la instancia de PostgreSQL mediante un socket proporcionado por el entorno de Cloud Run. Cuando la aplicación se ejecuta en tu máquina local, se conecta a la instancia de PostgreSQL mediante el proxy de autenticación de Cloud SQL.
Contenido multimedia subido por el usuario almacenado en la nube
Rails usa Active Storage para subir archivos a proveedores de almacenamiento en la nube. Los archivos config/storage.yml
y config/environments/production.rb
especifican Cloud Storage como el proveedor de servicios en el entorno de producción.
Automatización con Cloud Build
El archivo cloudbuild.yaml realiza no solo los pasos típicos de compilación de imágenes (crear la imagen del contenedor y enviarla a Container Registry), sino también las migraciones de la base de datos de Rails. Esto requiere acceso a la base de datos, que se realiza mediante el app-engine-exec-wrapper, un auxiliar para el proxy de autenticación de Cloud SQL.
En esta configuración, se usan variables de sustitución. Si se cambian directamente los valores del archivo, se puede descartar la marca --substitutions
en el momento de la migración.
En esta configuración, solo se aplican las migraciones existentes en el directorio db/migrate
. Para crear archivos de migración, consulta Migraciones de registros activas.
Para compilar la imagen y aplicar migraciones, la configuración de Cloud Build necesita acceder al secreto RAILS_MASTER_KEY
desde Secret Manager. El campo availableSecrets
establece la versión del secreto y las variables de entorno que se usarán para el secreto. El secreto de clave maestra se pasa como argumento en el paso de compilación de la imagen y, luego, se establece como RAILS_MASTER_KEY
en el Dockerfile cuando se compila la imagen.
A fin de extender la configuración de Cloud Build para incluir la implementación en la configuración única sin tener que ejecutar dos comandos, consulta Implementación continua desde Git con Cloud Build. Esto requiere cambios de IAM, como se describe.
Asistencia para Ruby 2.7
Si bien en este instructivo se usa Ruby 3.0, también es compatible con Ruby 2.7. Para usar Ruby 2.7, cambia la imagen base de Ruby en Dockerfile a 2.7
Limpieza
- En la consola de Google Cloud, ve a la página Administrar recursos.
- En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
- En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.