Receita de API Rails com Docker
Tags: rails, docker, api, dockercompose
Published: 2023-03-04 16:05:10

Criar uma API Ruby on Rails do zero nunca foi complexo, mas com [docker](https://docs.docker.com/engine/install/) e [docker compose](https://docs.docker.com/compose/) fica ainda mais simples pois não se depende de instação de dependências locais, como rvm ou rbenv, ruby, bundler, banco, redis ou qualquer outra coisa que sua aplicação precise.

As únicas dependências serão realmente o [docker](https://docs.docker.com/engine/install/) e o [docker compose](https://docs.docker.com/compose/), portanto, se não tiver instalado em sua máquina, precisará fazê-lo.

Vamos à receita:

## Crie o dockerfile

Esse é o cara que vai criar a sua imagem docker(tipo a máquina virtual) para rodar a sua aplicação:

```
FROM ruby:3.1.2-slim

RUN apt-get update -qq && apt-get install -yq --no-install-recommends \
    build-essential \
    gnupg2 \
    less \
    git \
    libpq-dev \
    postgresql-client \
    libvips42 \
  && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

ENV LANG=C.UTF-8 \
  BUNDLE_JOBS=4 \
  BUNDLE_RETRY=3
  
RUN gem update --system && gem install bundler

WORKDIR /usr/src/app

ENTRYPOINT ["./entrypoint.sh"]

EXPOSE 3001

CMD ["bundle", "exec", "rails", "s", "-b", "0.0.0.0"]
```

## Crie o entrypoint.sh

Esse cara vai dizer o que o seu container precisa fazer depois que ele for inicializado:

```
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /usr/src/app/tmp/pids/server.pid

echo "bundle install..."
bundle check || bundle install --jobs 4

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```
Vai, nem é tão difícil assim de entender...

Agora adicione permissão de execução desse arquivo:
`chmod +x entrypoint.sh`

## Crie o Gemfile
Inicialmente só precisa disso mesmo. Depois que gerar o app, o rails injeta o restante.

```
source "https://rubygems.org"
gem "rails", "~> 7.0.4", ">= 7.0.4.2"
```

## Crie um arquivo vazio Gemfile.lock
`touch Gemfile.lock`
Dont worry, você não vai precisar alterar isso

## Crie o docker-compose.yml
Esse arquivo conecta todos os serviços que a sua aplicação vai precisar: banco, redis, rede, armazenamento, e por aí vai...

```
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bin/rails s -p 3001 -b '0.0.0.0'"
    volumes:
      - .:/usr/src/app
      - bundle:/usr/local/bundle
    ports:
      - "3001:3001"
    env_file:
      - .env
    environment:
      - HISTFILE=/usr/src/app/log/.bash_history
      - ENVIRONMENT=local
    depends_on:
      - db
  db:
    image: postgres:13
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_PASSWORD=123123
    volumes:
      - pg_data:/var/lib/postgresql/data
volumes:
  pg_data:
  redis_data:
  bundle:
```

## Crie o seu .env
para armazenar qualquer informação para sua aplicação:

```
PGHOST=db
PGUSER=postgres
PGPASSWORD=123123
```

## Gere uma nova aplicação a partir desta receita de container:

`docker compose run web rails new . --force --database=postgresql --api`

## Receita pronta

Agora que a receita está pronta, resta servir: `docker compose up`

Para executar qualquer comando da aplicação:
`docker compose exec web rails db:create`
outro, como exemplo: `docker compose exec web rails g scaffold user name`

Agora, ao acessar http://localhost:3001/users você já tem a sua rota de usuários prontinha...