<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Beto Sardinha</title>
    <description>The latest articles on Forem by Beto Sardinha (@betosardinha).</description>
    <link>https://forem.com/betosardinha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F998717%2Ff718d7fd-4ad9-439d-9358-69e4ea71c833.png</url>
      <title>Forem: Beto Sardinha</title>
      <link>https://forem.com/betosardinha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/betosardinha"/>
    <language>en</language>
    <item>
      <title>Booksica-01: Criando uma API Rails com Postgres e Docker</title>
      <dc:creator>Beto Sardinha</dc:creator>
      <pubDate>Sat, 14 Oct 2023 13:21:00 +0000</pubDate>
      <link>https://forem.com/betosardinha/booksica-01-criando-uma-api-rails-com-postgres-e-docker-5bhl</link>
      <guid>https://forem.com/betosardinha/booksica-01-criando-uma-api-rails-com-postgres-e-docker-5bhl</guid>
      <description>&lt;h2&gt;
  
  
  Olá você que está lendo este post por algum motivo!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsyf8nrdguu0ayaj678c.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsyf8nrdguu0ayaj678c.jpeg" alt="Eu mostrando a API criada funcionando"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Mas acho que você está aqui porque talvez queira criar um pequeno projeto em &lt;strong&gt;Rails&lt;/strong&gt; e aprender um pouco mais sobre &lt;strong&gt;Docker&lt;/strong&gt;. 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.&lt;/p&gt;

&lt;p&gt;Então vamos lá!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre o projeto
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando Ruby e Rails na sua máquina
&lt;/h2&gt;

&lt;p&gt;A primeira coisa é baixar e instalar o Ruby, você pode usar a &lt;a href="https://www.ruby-lang.org/en/documentation/installation/" rel="noopener noreferrer"&gt;instalação padrão&lt;/a&gt; ou algum &lt;a href="https://www.ruby-toolbox.com/categories/ruby_version_management" rel="noopener noreferrer"&gt;gerenciador de versões&lt;/a&gt;. No meu caso estou usando &lt;a href="https://github.com/rbenv/rbenv" rel="noopener noreferrer"&gt;rbenv&lt;/a&gt;, e se você estiver usando linux recomendo também, é simples e gosto bastante.&lt;/p&gt;

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

&lt;p&gt;Depois de instalar o Ruby, instalei a &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;gem de Rails&lt;/a&gt; e mais algumas relacionadas ao &lt;a href="https://rubocop.org/" rel="noopener noreferrer"&gt;rubocop&lt;/a&gt; para lint direto no meu editor de código (eu estou usando &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;vscode&lt;/a&gt; com as extensões &lt;a href="https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby" rel="noopener noreferrer"&gt;ruby&lt;/a&gt; ​​e &lt;a href="https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop" rel="noopener noreferrer"&gt;ruby-rubocop&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem install rails
gem install rubocop
gem install rubocop-rails
gem install rubocop-performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando uma API Rails com Postgres
&lt;/h2&gt;

&lt;p&gt;Onde trabalho e em vários outros projetos geralmente utilizo &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;, 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 &lt;strong&gt;para não criar arquivos front-end&lt;/strong&gt; (criarei um projeto separado para consumir a API mais tarde, provavelmente em &lt;a href="//https:/%20/vuejs.org/"&gt;VueJS&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Fui em um gerador de nomes que me retornou algumas opções de nome do projeto, coloquei o nome como &lt;em&gt;booksica&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new booksica-api --api --database=postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também criei o arquivo de licença como &lt;a href="https://choosealicense.com/licenses/mit/" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; para especificar o direito de qualquer pessoa de baixar, usar e modificar o projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usando Docker para executar o projeto
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;. Se quiser, basta seguir este &lt;a href="https://docs.docker.com/engine/" rel="noopener noreferrer"&gt;passo a passo da instalação&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Criei meu Dockerfile com as configurações necessárias para um projeto Rails, e um &lt;em&gt;entrypoint.sh&lt;/em&gt;, que exclui o arquivo &lt;em&gt;server.pid&lt;/em&gt; pois às vezes ele não é removido caso o container não seja desligado corretamente (gerando um &lt;a href="https://www.chrisblunt.com/rails-on-docker-using-an-entrypoint-file-containers" rel="noopener noreferrer"&gt;erro&lt;/a&gt; ao executá-lo novamente).&lt;/p&gt;

&lt;p&gt;Outro ponto a ser mencionado é a configuração &lt;strong&gt;BUNDLE_FROZEN&lt;/strong&gt;, que sempre força uma comparação entre o &lt;em&gt;Gemfile&lt;/em&gt; e o &lt;em&gt;Gemfile.lock&lt;/em&gt;, e se as versões forem diferentes o projeto não inicia (mais uma &lt;a href="https://stackoverflow.com/questions/68817050/using-bundle-frozen" rel="noopener noreferrer"&gt;configuração de segurança&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax = docker/dockerfile:1&lt;/span&gt;

&lt;span class="c"&gt;# Versão do ruby que será usada&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ruby:3.2.0&lt;/span&gt;

&lt;span class="c"&gt;# Instalação de dependências&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; postgresql-client

&lt;span class="c"&gt;# Configuração do BUNDLE_FROZEN&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle config &lt;span class="nt"&gt;--global&lt;/span&gt; frozen 1

&lt;span class="c"&gt;# Criação do diretório de trabalho&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /booksica-api&lt;/span&gt;

&lt;span class="c"&gt;# Cópia dos arquivos e instalação das gems&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; Gemfile Gemfile.lock ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Rodar o arquivo de entrypoint para deletar o server.pid&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; entrypoint.sh /usr/bin/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/bin/entrypoint.sh
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["entrypoint.sh"]&lt;/span&gt;

&lt;span class="c"&gt;# Escutar porta 3000 e rodar o servidor&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./bin/rails", "server", "-b", "0.0.0.0"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;entrypoint.sh&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /booksica-api/tmp/pids/server.pid

&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configurando variáveis ​​do banco de dados
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;config/database.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;default&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
  &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unicode&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBHOST'] %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBUSER'] %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBPASS'] %&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica_api_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica_api_test&lt;/span&gt;


&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica_api_production&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica_api&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV["BOOKSICA_API_DATABASE_PASSWORD"] %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DBHOST&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;DBUSER&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="py"&gt;DBPASS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando um arquivo docker compose
&lt;/h2&gt;

&lt;p&gt;Por fim, para poder executar o projeto, criei um arquivo &lt;em&gt;docker-compose.yml&lt;/em&gt; contendo os seguintes serviços:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um serviço de banco de dados utilizando a imagem do Postgres;&lt;/li&gt;
&lt;li&gt;Um serviço administrador de banco de dados com a imagem pgAdmin (opcional);&lt;/li&gt;
&lt;li&gt;Um serviço rails executando meu projeto pelo Dockerfile;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;booksica-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica-db&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;booksica_api_development"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;booksica-api-network&lt;/span&gt;

  &lt;span class="na"&gt;booksica-pgadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dpage/pgadmin4&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica-pgadmin&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_EMAIL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@booksica.com"&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15432:80"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;booksica-db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;booksica-api-network&lt;/span&gt;

  &lt;span class="na"&gt;booksica-api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica-api&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;booksica-api&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBHOST=booksica-db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBUSER=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBPASS=password&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/booksica-api&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;booksica-db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;booksica-api-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;booksica-api-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alguns pontos são interessantes de falar, todos os serviços possuem variáveis de ambiente definidas, as variáveis do &lt;em&gt;booksica-db&lt;/em&gt; e &lt;em&gt;booksica-api&lt;/em&gt; são de &lt;strong&gt;acesso ao banco de dados&lt;/strong&gt;, e as do &lt;em&gt;booksica-pgadmin&lt;/em&gt; &lt;strong&gt;credenciais de acesso&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;Outro ponto é que criei uma &lt;strong&gt;network&lt;/strong&gt; 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 &lt;a href="https://docs.docker.com/compose/gettingstarted/" rel="noopener noreferrer"&gt;documentação oficial&lt;/a&gt;, o Docker é apenas assustador no começo, com o tempo você se acostuma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rodando o projeto
&lt;/h2&gt;

&lt;p&gt;Por fim, depois de tantas configurações, montei os containers do projeto e subi os serviços:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose build
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose exec booksica-api bash
rails db:create
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E logo após reiniciar os serviços tenho a confirmação de que está tudo funcionando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukvit2pux6fz9m2r6fyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukvit2pux6fz9m2r6fyv.png" alt="Página inicial do projeto em Rails"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Também acessei o serviço pgAdmin para testar se o banco de dados foi criado corretamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wo7qp97kx5yeu58nog3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wo7qp97kx5yeu58nog3.png" alt="pgAdmin com os bancos criados"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3euoewbllfzefgf0auo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3euoewbllfzefgf0auo4.png" alt="Eu falando pra você o quanto esse diário de desenvolvimento irá demorar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Link para o projeto
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/betosardinha/booksica-api" rel="noopener noreferrer"&gt;https://github.com/betosardinha/booksica-api&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Música aleatória para você escutar
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oHsGr6RYpJA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>rails</category>
      <category>docker</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>DJ-1: Creating a Rails API with Postgres and Docker</title>
      <dc:creator>Beto Sardinha</dc:creator>
      <pubDate>Fri, 13 Jan 2023 00:13:21 +0000</pubDate>
      <link>https://forem.com/betosardinha/dj-1-creating-a-rails-api-with-postgres-and-docker-2fgn</link>
      <guid>https://forem.com/betosardinha/dj-1-creating-a-rails-api-with-postgres-and-docker-2fgn</guid>
      <description>&lt;h2&gt;
  
  
  Hello there to you who are reading this post for some reason!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0dbz2le2uyodkkq5tmc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0dbz2le2uyodkkq5tmc.png" alt="Me showing my code" width="470" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't know how to start a development journal properly, it's the first time I've done something like this and it's also the first time I've written a full article in English. So I apologize for future language mistakes.&lt;/p&gt;

&lt;p&gt;But I think you're here because maybe you want to create a small &lt;strong&gt;Rails&lt;/strong&gt; project and learn a little more about &lt;strong&gt;Docker&lt;/strong&gt;. And that's exactly what I want too! So this journal entry is my attempts to build a foundation for projects, and a step by step for you to build one to.&lt;/p&gt;

&lt;p&gt;So let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Ruby and Rails on your machine
&lt;/h2&gt;

&lt;p&gt;First thing is to download and install ruby, you can either use the &lt;a href="https://www.ruby-lang.org/en/documentation/installation/" rel="noopener noreferrer"&gt;default installation&lt;/a&gt; or some &lt;a href="https://www.ruby-toolbox.com/categories/ruby_version_management" rel="noopener noreferrer"&gt;version manager&lt;/a&gt;. In my case I'm using &lt;a href="https://github.com/rbenv/rbenv" rel="noopener noreferrer"&gt;rbenv&lt;/a&gt;, and if you're using linux I recommend it too, it's simple and I like it a lot.&lt;/p&gt;

&lt;p&gt;For this project I'm using &lt;strong&gt;ruby ​​3.2.0&lt;/strong&gt;, but feel free to use the most stable/latest version available.&lt;/p&gt;

&lt;p&gt;After installing ruby, I installed the &lt;a href="https://rubyonrails.org/" rel="noopener noreferrer"&gt;rails gem&lt;/a&gt; and a few more &lt;a href="https://rubocop.org/" rel="noopener noreferrer"&gt;rubocop-related&lt;/a&gt; ones to lint right into my code editor (I'm using &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;vscode&lt;/a&gt; with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby" rel="noopener noreferrer"&gt;ruby&lt;/a&gt; ​​and &lt;a href="https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop" rel="noopener noreferrer"&gt;ruby-rubocop&lt;/a&gt; extensions).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem install rails
gem install rubocop
gem install rubocop-rails
gem install rubocop-performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a Rails API with Postgres
&lt;/h2&gt;

&lt;p&gt;Where I work and in several other projects I use &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;, I'm used to the behavior and the interface, so when creating this project I configured it to be the database. And since I'm working on an API project I set the flag for Rails &lt;strong&gt;to not create front-end files&lt;/strong&gt; (I'll create a separate project to consume the API later, probably in &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;VueJS&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I put the name as &lt;em&gt;articles-api&lt;/em&gt; for simplicity (since I'm not good with names).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new articles-api --api --database=postgresql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also created the license file as &lt;a href="https://choosealicense.com/licenses/mit/" rel="noopener noreferrer"&gt;MIT&lt;/a&gt; to specify anyone's right to download, use and modify the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker to run the project
&lt;/h2&gt;

&lt;p&gt;Despite being used to Postgres, I don't want to install it on my machine, nor use rails directly. And for many other compatibility reasons with other computers (and even for you to download and run this project) I decided to use &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; containers. If you want, just follow this &lt;a href="https://docs.docker.com/engine/" rel="noopener noreferrer"&gt;installation step by step&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I created my Dockerfile with the necessary settings for the Rails project, and an &lt;em&gt;entrypoint.sh&lt;/em&gt;, which deletes the &lt;em&gt;server.pid&lt;/em&gt; file that sometimes is not removed if the container is not shut down correctly (generating an &lt;a href="https://www.chrisblunt.com/rails-on-docker-using-an-entrypoint-file-containers" rel="noopener noreferrer"&gt;error&lt;/a&gt; when running it again).&lt;/p&gt;

&lt;p&gt;Another point to be mentioned is the &lt;strong&gt;BUNDLE_FROZEN&lt;/strong&gt; configuration, which will always force a comparison between the &lt;em&gt;Gemfile&lt;/em&gt; and the &lt;em&gt;Gemfile.lock&lt;/em&gt;, and if the versions are different the project will not run (more a &lt;a href="https://stackoverflow.com/questions/68817050/using-bundle-frozen" rel="noopener noreferrer"&gt;security&lt;/a&gt; configuration).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Put the ruby ​​version you are using&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ruby:3.2.0&lt;/span&gt;

&lt;span class="c"&gt;# Install the necessary libraries&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="nt"&gt;-qq&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; postgresql-client

&lt;span class="c"&gt;# BUNDLE_FROZEN setting&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle config &lt;span class="nt"&gt;--global&lt;/span&gt; frozen 1

&lt;span class="c"&gt;# Set working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /articles-api&lt;/span&gt;

&lt;span class="c"&gt;# Copy and install the project gems&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; Gemfile /articles-api/Gemfile&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; Gemfile.lock /articles-api/Gemfile.lock&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Run entrypoint.sh to delete server.pid&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; entrypoint.sh /usr/bin/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/bin/entrypoint.sh
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["entrypoint.sh"]&lt;/span&gt;

&lt;span class="c"&gt;# Listen on this specified network port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Run rails server&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["rails", "server", "-b", "0.0.0.0"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;entrypoint.sh&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /articles-api/tmp/pids/server.pid

&lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up database variables
&lt;/h2&gt;

&lt;p&gt;Before building the project, I corrected the database settings so that the project could connect to the database container. I put &lt;em&gt;host&lt;/em&gt;, &lt;em&gt;username&lt;/em&gt; and &lt;em&gt;password&lt;/em&gt; as &lt;strong&gt;environment variables&lt;/strong&gt;, which will be passed both in the container &lt;em&gt;compose file&lt;/em&gt; and in an &lt;em&gt;.env&lt;/em&gt; file in case it needs to be run locally at some point. Variables are in default scope, so development and test database have the same credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;config/database.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;default&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
  &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unicode&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBHOST'] %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBUSER'] %&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV['DBPASS'] %&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles_api_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles_api_test&lt;/span&gt;

&lt;span class="na"&gt;production&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles_api_production&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles_api&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV["ARTICLES_API_DATABASE_PASSWORD"] %&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;DBHOST&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;DBUSER&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="py"&gt;DBPASS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a docker-compose file
&lt;/h2&gt;

&lt;p&gt;Finally, to be able to run the project, I created a &lt;em&gt;docker-compose.yml&lt;/em&gt; file containing the following services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A database using Postgres image;&lt;/li&gt;
&lt;li&gt;A database administrator with the pgAdmin image (optional);&lt;/li&gt;
&lt;li&gt;Rails running my project with the Dockerfile;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;articles-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles-db&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles_api_development"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;articles-api-network&lt;/span&gt;

  &lt;span class="na"&gt;articles-pgadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dpage/pgadmin4&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles-pgadmin&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_EMAIL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@articles.com"&lt;/span&gt;
      &lt;span class="na"&gt;PGADMIN_DEFAULT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15432:80"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;articles-db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;articles-api-network&lt;/span&gt;

  &lt;span class="na"&gt;articles-api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles-api&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;articles-api&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBHOST=articles-db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBUSER=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DBPASS=password&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/articles-api&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;articles-db&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;articles-api-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;articles-api-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some points are interesting to talk about, all services have environment variables defined, with &lt;em&gt;articles-db&lt;/em&gt; and &lt;em&gt;articles-api&lt;/em&gt; &lt;strong&gt;database access&lt;/strong&gt; variables, and &lt;em&gt;articles-pgadmin&lt;/em&gt; &lt;strong&gt;access credentials&lt;/strong&gt; to the administrator panel. Both the API and pgAdmin services are dependent on the database, so if you upload any of them, the database service automatically uploads.&lt;/p&gt;

&lt;p&gt;Another point is that I created a separate &lt;strong&gt;network&lt;/strong&gt; for the services to communicate with, I just find it easier to find it by giving it a specific name. If you want to learn more about compose file tags I recommend the &lt;a href="https://docs.docker.com/compose/gettingstarted/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;, Docker is just scary at first, with time you get used to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the project
&lt;/h2&gt;

&lt;p&gt;Finally, after so many configurations, I assembled the project's containers and loaded the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose build
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I entered the api service bash to perform the database migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose exec articles-api bash
rails db:create
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And right after restarting the services, I have confirmation that everything is working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fdcb8nymkkfujtzuth0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fdcb8nymkkfujtzuth0.png" alt="Rails service" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also accessed the pgAdmin service to test that the database was created correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodup6zk9cluu45kbdtac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodup6zk9cluu45kbdtac.png" alt="pgAdmin service" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it for today! The project is working and ready for the next changes, I think after that I will make a new entry showing the process of creating a CI workflow with Github Actions.&lt;/p&gt;

&lt;p&gt;If you have any questions or tips on how I can improve the project (or even this post), feel free to drop them in! My idea is that this development diary should be periodic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link to the project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/betosardinha/articles-api" rel="noopener noreferrer"&gt;https://github.com/betosardinha/articles-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cursorai</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
