Ambientes de Desarrollo Docker (Rails + Postgres)

Vamos a darle vuelta más de tuerca a nuestro ambiente de desarrollo de Ruby on Rails.

Algo más que común, es el uso de una base de datos en una aplicación web. Es algo que en la mayoría de los proyectos vamos a usar.

Como vimos en el post anterior, armamos un ambiente de desarrollo, usando la extension Remote Containers de Visual Studio Code. Pero solo teníamos el container que tiene la aplicación y usábamos SQLite como base de datos.

En este post vamos a ir un paso más y crear un ambiente con múltiples containers. La aplicación y la base de datos. Esto mismo se puede usar en caso que necesitemos Redis, o cualquier otro servicio corriendo en nuestra aplicación.

Al momento de escribir este post hay un pull request en el proyecto de los templates de Remote Containers con una configuración parecida a la que te voy a mostrar.

Probablemente cuando esto se integre al proyecto va a ser más fácil elegir este template en la lista como elegimos el de Ruby on Rails.

Manos a la obra

Para arrancar vamos a necesitar todo lo mismo que les conté en el post anterior.

Ahora, en lugar de elegir el template Ruby on Rails, vamos a elegir Docker from Docker Compose.

Esto nos va a agregar varios archivos, que vamos a cambiar casi todos y borrar algunos.

La carpeta library-scripts la borramos y el resto de los archivos los vamos a modificar.

devcontainer.json

En este archivo lo que cambio es:

  • name: Ponerle un nombre más representativo en este caso Ruby on Rails + Postgres
  • extensions: Poner rebornix.Ruby
  • fowardPorts: Agregar el 3000 que es donde corre Rails.
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.158.0/containers/docker-from-docker-compose
{
"name": "Ruby on Rails + Postgres",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"rebornix.Ruby"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3000],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "docker –version",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}

Dockerfile

Lo modifico totalmente, uso en su lugar el que se creó cuando armamos el ambiente de Ruby on Rails sin base de datos.

# [Choice] Ruby version: 2, 2.7, 2.6, 2.5
ARG VARIANT=2
FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}
# Install Rails
RUN gem install rails webdrivers
ARG NODE_VERSION="lts/*"
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install –no-install-recommends <your-package-list-here>
# [Optional] Uncomment this line to install additional gems.
# RUN gem install <your-gem-names-here>
# [Optional] Uncomment this line to install global node packages.
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
view raw Dockerfile hosted with ❤ by GitHub

docker-compose.yml

En este archivo es donde pasa la magia :).

Vamos a agregar 2 servicios:

  • App: Este es el mismo container que usábamos antes, que está definido en el Dockerfile, acá vamos a correr nuestra aplicación.
  • Db: Este es el container de la base de datos.

Nota: Como te decía más arriba aca podrias poner los servicios que quisieras, Redis, adminer, etc.

version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
VARIANT: "2.7"
NODE_VERSION: "lts/*"
volumes:
# Update this to wherever you want VS Code to mount the folder of your project
..:/workspace:cached
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
network_mode: service:db
db:
image: postgres:latest
restart: unless-stopped
volumes:
postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres
volumes:
postgres-data:

Turn on the engines

Ahora estamos listos para arrancar los motores, nuevamente buscamos en la opciones de Remote Container, Reopen in Container.

Ahora vamos a crear una aplicación de rails, pero usando postgres

rails new myapp --database=postgresql

En el archivo de configuración de la base de datos (config/database.yml), agregamos el host, user y password a la sección default.

default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: db
user: postgres
password: postgres
view raw database.yml hosted with ❤ by GitHub

Nota: Dentro de Docker para comunicarnos con otros servicios, la URL que usamos es el nombre del servicio. En este caso el host que vamos a usar en nuestra aplicación va a ser db.

Probemos la DB

Para poder probar la base de datos, vamos a crear algo en Rails para usarla. Para eso usamos el generator de Rails, para crear un CRUD, en este caso de Clientes.

rails g scaffold Customer name:string address:string

Ahora si , tenemos migraciones, entonces ejecutamos

rails db:create db:migrate

Ahora si podemos entrar a http://localhost:3000/customers y probar nuestra app, creando, editando y borrando clientes.

Espero que les sirva y lo puedan usar.

Nos leemos!

Ambientes de desarrollo en Docker + VSCode

Hace unos meses que estuve probando y usando un poco una extensión de Visual Studio Code que se llama Remote Containers. La verdad que me pareció super simple, cómodo y muy potente.

Remote Containers te ayuda a tener un ambiente de desarrollo para muchísimas tecnologías en 5 minutos.

Para este ejemplo voy a usar una aplicación de Ruby on Rails default.

¿Qué necesitamos?

Para seguir este mini tutorial necesitas tener instalado:

Setup

Para empezar abrimos VSCode, en una carpeta nueva y vamos a la parte de Extensions, ahí tenemos que instalar la extensión Remote Containers.

Una vez instalada, vamos a poder usarla:

  • Haciendo click en el icono de abajo a la izquierda.
  • Abriendo la consola de comandos (Command Palette) en el menú View o con el comando CMD + Shift + p (en Mac).

Crear el container

Sabemos que vamos a estar trabajando en un proyecto de Ruby on Rails, entonces abrimos la consola de comandos y buscamos: Remote-Container: Add development container…

Una vez dentro de ese menu, buscamos Ruby on Rails y luego la versión de Ruby que queramos usar, al momento de este post, la última disponible es 2.7, aunque ya salió Ruby 3.0.

Esto nos va a crear una carpeta con 2 archivos:

  • devcontainer.json: Donde esta toda la configuración del ambiente.
  • Dockerfile: Es la imagen de Docker que vamos a usar.

Ambos archivos estan muy bien documentados y tienen secciones que se pueden descomentar para poder hacer que se instalen gemas adicionales, paquetes de Node, etc.

En principio, lo único que vamos a hacer, es descomentar en devcontainer.json la parte de forwardPorts. Así vamos a poder conectarnos desde el browser (en nuestra máquina) a la aplicación que va a estar corriendo en Docker. Entonces configuramos el puerto 3000 que es el default en las apps de Rails.

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.158.0/containers/ruby-rails
{
"name": "Ruby on Rails",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update 'VARIANT' to pick a Ruby version: 2, 2.7, 2.6, 2.5
"VARIANT": "2.7",
"NODE_VERSION": "lts/*"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"rebornix.Ruby"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [3000],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "ruby –version",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}

Probando el ambiente

Ahora vamos a probar el ambiente, para eso, usando la consola de comandos buscamos Remote-Containers: Reopen in Container

Esto nos va a re-abrir Visual Studio Code y nos va a indicar, donde esta el icono de Remote Containers, si estamos viendo el código dentro de un container.

Ahora si, abrimos la terminal (Ctrl + ` o desde el menu Terminal) desde donde vamos a poder ejecutar comandos dentro del container. Por ejemplo podemos ver que versión de Ruby y de Rails tenemos instalado.

Ahora podemos ejecutar, en esa consola, el comando de Rails para crear una app.

rails new MyApp

O si, como yo, preferís que el proyecto quede al nivel de la carpeta que creaste, anda un nivel para arriba y ejecuta.

rails new [nombre-de-la-carpeta]

Una vez que terminó, entramos a la carpeta del proyecto y ejecutamos rails s para poner a andar el web server.

Entramos en nuestro browser a http://localhost:3000 y voilà, nuestra app de Rails está corriendo dentro del container y podemos usarla desde nuestro browser.

El próximo paso será poder configurar el ambiente para que no use SQLite, sino Postgres o alguna otra base de datos. Pero eso es para otro post.

Espero que lo puedan usar en sus proyectos.

Nos estamos leyendo.