DEV Community

Beto Sardinha
Beto Sardinha

Posted on

Booksica-01: Criando uma API Rails com Postgres e Docker

Olá você que está lendo este post por algum motivo!

Eu mostrando a API criada funcionando

Não sei como iniciar um diário de desenvolvimento corretamente, creio que seja a primeira vez que faço algo assim e também é a primeira vez que escrevo um artigo completo aqui no site. Portanto, peço desculpas se o formato ficar estranho.

Mas acho que você está aqui porque talvez queira criar um pequeno projeto em Rails e aprender um pouco mais sobre Docker. E é exatamente isso que eu também quero! Portanto, esta entrada no diário é minha tentativa de construir uma base para projetos e um passo a passo para você construir também.

Então vamos lá!

Sobre o projeto

Estou em período de mudança e ainda não comprei uma estante para guardar meus livros, que estão todos jogados pelo chão do escritório. Como está tudo bagunçado não sei quantos livros são, quais são, se perdi algum na mudança, e não consigo definir uma lista do que irei ler.

Então a ideia é simples (na verdade extremamente complicada pois poderia usar uma planilha), construir uma API que converse com um banco de dados e guarde informações dos livros que tenho.

Instalando Ruby e Rails na sua máquina

A primeira coisa é baixar e instalar o Ruby, você pode usar a instalação padrão ou algum gerenciador de versões. No meu caso estou usando rbenv, e se você estiver usando linux recomendo também, é simples e gosto bastante.

Para este projeto estou usando ruby ​​3.2.0, mas fique à vontade para usar a versão mais estável/recente disponível.

Depois de instalar o Ruby, instalei a gem de Rails e mais algumas relacionadas ao rubocop para lint direto no meu editor de código (eu estou usando vscode com as extensões ruby ​​e ruby-rubocop).

gem install rails
gem install rubocop
gem install rubocop-rails
gem install rubocop-performance
Enter fullscreen mode Exit fullscreen mode

Criando uma API Rails com Postgres

Onde trabalho e em vários outros projetos geralmente utilizo PostgreSQL, estou acostumado com o comportamento e a interface de gerenciamento, configurei ele para ser o banco de dados principal. E como esse projeto será uma API, configurei a flag do Rails para não criar arquivos front-end (criarei um projeto separado para consumir a API mais tarde, provavelmente em VueJS).

Fui em um gerador de nomes que me retornou algumas opções de nome do projeto, coloquei o nome como booksica.

rails new booksica-api --api --database=postgresql
Enter fullscreen mode Exit fullscreen mode

Também criei o arquivo de licença como MIT para especificar o direito de qualquer pessoa de baixar, usar e modificar o projeto.

Usando Docker para executar o projeto

Apesar de estar acostumado com o Postgres, não quero instalá-lo na minha máquina, nem usar o Rails diretamente. E por motivos de compatibilidade com outros computadores (e até para você mesmo baixar e executar esse projeto) resolvi usar containers Docker. Se quiser, basta seguir este passo a passo da instalação.

Criei meu Dockerfile com as configurações necessárias para um projeto Rails, e um entrypoint.sh, que exclui o arquivo server.pid pois às vezes ele não é removido caso o container não seja desligado corretamente (gerando um erro ao executá-lo novamente).

Outro ponto a ser mencionado é a configuração BUNDLE_FROZEN, que sempre força uma comparação entre o Gemfile e o Gemfile.lock, e se as versões forem diferentes o projeto não inicia (mais uma configuração de segurança).

Dockerfile

# syntax = docker/dockerfile:1

# Versão do ruby que será usada
FROM ruby:3.2.0

# Instalação de dependências
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y postgresql-client

# Configuração do BUNDLE_FROZEN
RUN bundle config --global frozen 1

# Criação do diretório de trabalho
WORKDIR /booksica-api

# Cópia dos arquivos e instalação das gems
COPY Gemfile Gemfile.lock ./
RUN bundle install

# Rodar o arquivo de entrypoint para deletar o server.pid
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# Escutar porta 3000 e rodar o servidor
EXPOSE 3000
CMD ["./bin/rails", "server", "-b", "0.0.0.0"]
Enter fullscreen mode Exit fullscreen mode

entrypoint.sh

#!/bin/bash
set -e

rm -f /booksica-api/tmp/pids/server.pid

exec "$@"
Enter fullscreen mode Exit fullscreen mode

Configurando variáveis ​​do banco de dados

Antes de rodar o projeto, corrigi algumas configurações para que o ele pudesse se conectar ao banco de dados. Coloquei host, username e password como variáveis ​​de ambiente, que serão passadas tanto pelo arquivo de configuração do container, quanto em um arquivo .env caso precise ser executado localmente em algum momento. As variáveis ​​estão no escopo default, portanto, o banco de dados de desenvolvimento e de teste tem as mesmas credenciais.

config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: <%= ENV['DBHOST'] %>
  username: <%= ENV['DBUSER'] %>
  password: <%= ENV['DBPASS'] %>

development:
  <<: *default
  database: booksica_api_development

test:
  <<: *default
  database: booksica_api_test


production:
  <<: *default
  database: booksica_api_production
  username: booksica_api
  password: <%= ENV["BOOKSICA_API_DATABASE_PASSWORD"] %>
Enter fullscreen mode Exit fullscreen mode

.env

DBHOST=localhost
DBUSER=postgres
DBPASS=password
Enter fullscreen mode Exit fullscreen mode

Criando um arquivo docker compose

Por fim, para poder executar o projeto, criei um arquivo docker-compose.yml contendo os seguintes serviços:

  • Um serviço de banco de dados utilizando a imagem do Postgres;
  • Um serviço administrador de banco de dados com a imagem pgAdmin (opcional);
  • Um serviço rails executando meu projeto pelo Dockerfile;

docker-compose.yml

version: '3.8'

services:
  booksica-db:
    image: postgres
    container_name: booksica-db
    volumes:
      - postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: "booksica_api_development"
      POSTGRES_USER: "postgres"
      POSTGRES_PASSWORD: "password"
    ports:
      - "5432:5432"
    networks:
      - booksica-api-network

  booksica-pgadmin:
    image: dpage/pgadmin4
    container_name: booksica-pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: "user@booksica.com"
      PGADMIN_DEFAULT_PASSWORD: "password"
    ports:
      - "15432:80"
    depends_on:
      - booksica-db
    networks:
      - booksica-api-network

  booksica-api:
    image: booksica-api
    container_name: booksica-api
    build: .
    environment:
      - DBHOST=booksica-db
      - DBUSER=postgres
      - DBPASS=password
    volumes:
      - .:/booksica-api
    ports:
      - "3000:3000"
    depends_on:
      - booksica-db
    networks:
      - booksica-api-network

networks:
  booksica-api-network:
    driver: bridge

volumes:
  postgres:
Enter fullscreen mode Exit fullscreen mode

Alguns pontos são interessantes de falar, todos os serviços possuem variáveis de ambiente definidas, as variáveis do booksica-db e booksica-api são de acesso ao banco de dados, e as do booksica-pgadmin credenciais de acesso ao painel do administrador. Os serviços API e pgAdmin dependem do banco de dados, portanto, se você subir qualquer um deles, o serviço de banco de dados será carregado automaticamente.

Outro ponto é que criei uma network separada para os serviços se comunicarem, só acho mais fácil encontrá-la dando um nome específico. Se você quiser saber mais sobre as tags do docker compose eu recomendo a documentação oficial, o Docker é apenas assustador no começo, com o tempo você se acostuma.

Rodando o projeto

Por fim, depois de tantas configurações, montei os containers do projeto e subi os serviços:

docker compose build
docker compose up
Enter fullscreen mode Exit fullscreen mode

Em outro terminal entrei no container principal do projeto (booksica-api) com o comando bash para realizar a migração do banco de dados:

docker compose exec booksica-api bash
rails db:create
rails db:migrate
Enter fullscreen mode Exit fullscreen mode

E logo após reiniciar os serviços tenho a confirmação de que está tudo funcionando.

Página inicial do projeto em Rails

Também acessei o serviço pgAdmin para testar se o banco de dados foi criado corretamente.

pgAdmin com os bancos criados

Conclusão

Por hoje é isso! O projeto está funcionando e pronto para as próximas mudanças, depois farei uma nova entrada aqui mostrando o processo de criação de um fluxo de trabalho de CI com Github Actions.

Se você tiver alguma dúvida ou dica sobre como posso melhorar o projeto (ou mesmo este post), fique à vontade para me enviar! Minha ideia é que esse diário de desenvolvimento seja periódico e não leve muito tempo (por mais que eu suma vez ou outra).

Eu falando pra você o quanto esse diário de desenvolvimento irá demorar

Link para o projeto

https://github.com/betosardinha/booksica-api

Música aleatória para você escutar

Top comments (0)