Deploy Rails: Suba seu APP para a Digital Ocean facilmente

Deploy Rails: Suba seu APP para a Digital Ocean facilmente

Fala, galera! Hoje vamos apresentar um assunto que tem fervilhado de pedidos da galera: como fazer um Deploy Rails na Digital Ocean. E aqui utilizaremos um grande aliado: o Capistrano.

Então segue o passo a passo logo a baixo para deixar seu APP no ar (de forma automatizada) e não se esqueça de fazer o download do bônus no final desse artigo: [PDF] Checklist completo de deploy

 

 

Estrutura do tutorial \o/

  • Conceitos importantes: Deploy
    • O que é VPS
    • O que é Deploy
    • Porque automatizar
  • Passo a passo do Deploy
    • Projeto de exemplo
    • Criando VPS
    • Configurando o Postgres
    • Instalando o Capistrano e Configurando o App
    • Configurando o Capistrano para o Deploy
  • Conceitos importantes: Capistrano
    • Roles? Variáveis? Arquivos e Diretórios Linkados?
      • Arquivos e Diretórios ‘Linkados’
      • Roles
      • Tudo é Task
  • Executando o Deploy
  • [PDF bônus] Checklist completo de deploy

 

Ferramentas

  • Git
  • Capistrano
  • Ubuntu Server na Digital Ocean
  • Rails 5.2


Conceitos importantes: Deploy

O que é VPS?

VPS significa Virtual Private Server, ou Servidor Virtual Privado. Nada mais é do que uma máquina virtual que compartilha, com outras máquinas virtuais, os recursos de uma máquina física como memória, processador, disco etc.
Esta máquina virtual é também um servidor dedicado, pois existe uma camada de virtualização que fica abaixo do Sistema Operacional.
Exemplos de empresas que fornecem VPS são Amazon, Google, Azure e outras menores como a Digital Ocean, Locaweb e Umbler (entre outras milhares).

 

O que é Deploy?

Deploy é simplesmente entregar um sistema para ser utilizado, seja num ambiente de testes ou produção, simples assim.

Por que automatizar?

Bem, no deploy de uma aplicação, nós seguimos uma sequência de passos para entregar o app em qualquer ambiente. Precisamos, por exemplo num app Rails, baixar o código, executar os migrations, restartar o app server e tudo mais que sua aplicação pode exigir.

Nós, seres humanos criadores (e falhos), não seguimos um script tão bem quanto uma máquina que foi programada pra fazer aquilo. E esse é o interessante de automatizar.
Conseguimos entregar um trabalho que requer um passo a passo às vezes minucioso (e por vezes até chato) para o computador fazer enquanto nos preocupamos em criar as soluções.

 



[PDF] Checklist completo de deploy \o/

Para você não esquecer nenhum detalhe na hora de subir seu APP 😁




Passo a passo do Deploy Rails

Projeto de exemplo

Neste post vamos seguir passos bem curtos, desde a instalação das dependências, configurações de banco de dados e configurações iniciais do próprio Capistrano até o sucesso no deploy.

Nós vamos utilizar uma aplicação que construímos num post anterior: “ActiveStorage: Usando na prática a nova ferramenta de upload do Rails”.

Este app utiliza Rais 5.2 e sua nova ferramenta, o Active Storage. Nós informaremos nos passos que forem específicos para utilização do Active Storage para que você use somente se for necessário pra você. 🙂

Então partiu pra tela!

 

Servidor e Dependências do App

Vamos começar configurando nosso servidor do zero e instalar as dependências do nosso app.

1- Criar uma conta na DO (caso você não possua uma conta na DO, crie uma com o link a baixo e ganhe $10)

bônus na Digital Ocean

2 – Agora vamos criar o nosso Droplet (VPS):

a) No seu menu da Digital Ocean (logado) clique em “Create” e escolha droplets.

digital ocean
b) Escolha a imagem Ubuntu:

ubuntu
c) Escolha o tamanho:

d) Escolha uma região:


e) Defina uma chave ssh para se conectar ao seu VPS caso queira (ou deixe em branco para usar com senha como no exemplo)

ssh

f) Escolha um nome e mande criar \o/

deploy

g) Pronto, agora você vai receber no seu email o ip e senha da VPS criada.

3- Depois de criado, vamos logar no servidor com as credenciais do root.

4- Agora vamos digitar a senha fornecida pela DO (que foi enviada para você por email)

5- No primeiro login, vai solicitar mudança de senha do usuário root. Escolha uma nova e confirme.

6- Vamos criar um novo usuário de aplicação chamado deploy:

7- Digite e confirme a senha deste novo usuário

8- Agora vamos adicionar este usuário no grupo root e admin

9- Agora vamos acessar o arquivo Sudoers para poder dar permissão para o usuário deploy executar comandos com sudo sem senha. Vamos adicionar na ultima linha do arquivo sudoers (/etc/sudoers):

10- Vamos deslogar do servidor como root e logar novamente com o usuário deploy

11- Feito isso, vamos começar a instalar as ferramentas que precisaremos utilizar

12- Vamos começar instalando o GIT

13- Agora vamos instalar o NGINX (servidor)

14- Vamos mudar o dono do diretório /var/www para deploy. Este é o diretório onde ficará nossa aplicação.

15- Agora é a vez o RVM. Para instalar, vamos executar o comando:

16- Seguindo as instruções de instalação do RVM, para que ele possa começar a ser utilizado, executaremos:

17- Vamos aproveitar e instalar a versão 2.4.2 do Ruby, a mesma que está lockada no nosso Gemfile:

18- Agora vamos instalar o Bundler

19- Vamos instalar o nodejs

20- Agora o Postgres

21- Agora vamos instalar uma dependência para a gem Postgresql (Banco de dados) que adicionaremos daqui a pouco:

22- Instalar o ImageMagick (dependência comum de gems do ruby para processar imagens):

O passo a cima é obrigatório pra quem estiver utilizando o Rails 5.2 e o Active Storage

 

Configurando o Postgres

Após instalar o postgres, vamos criar um usuário para aplicação no banco de dados também. Mas para isso, primeiro precisamos acessar o banco de dados com o usuário postgres e criar este usuário.
Como acabamos de instalar o Postgres e não sabemos a senha, vamos seguir alguns passos para acessarmos o banco sem senha, alterarmos a senha do usuário postgres e depois logar com esta senha e criar nosso usuário da aplicação.

1- Vamos abrir o arquivo chamado pg_hba.conf do Postgres. Como instalamos a versão 9.5 no Postgres, que é a versão que está no repositório do Ubuntu, este arquivo está no caminho:

2- Aberto o arquivo, vamos procurar a linha que contém o seguinte conteúdo:

3- Agora vamos substituir a palavra “peer” por “trust“, ficando deste jeito:

O que fizemos aqui foi setar uma configuração dizendo que é permitido logar localmente em todos os banco de dados com o usuário postgres sem senha.

4- Feito isso, vamos reiniciar o Postgres para que as configurações tenham efeito:

5- Agora vamos conectar no Postgres com o usuário postgres sem senha:

6- Agora vamos executar um comando SQL para podemos configurar a senha do usuário postgres:

Não esqueça de trocar <sua senha> pela sua senha 😉

7- Feito isso, vamos sair do Postgres e abrir novamente o arquivo pg_hba.conf  (/etc/postgresql/9.5/main/pg_hba.conf)

8- Agora vamos substituir a linha abaixo que alteramos anteriormente:

Pelo seguinte conteúdo:

Agora estamos reconfigurando o Postgres para que o login (com o usuário postgres ) seja feito com uma senha encriptada em MD5, por isso que ao alterarmos a senha, nós utilizamos “WITH ENCRYPTED PASSWORD”, para que a senha seja salva em MD5

9- Agora vamos reiniciar novamente o Postgres

10- Logar no Postgres com o usuário postgres digitando a senha que foi configurada anteriormente:

11- Agora vamos criar um novo usuário no banco para a aplicação:

12- Agora vamos conceder privilégios de super usuário para ele:

13- Por último, vamos criar o banco de dados do nosso app:

Com o Postgres configurado e todas as nossas dependências instaladas, agora vamos instalar e configurar o Capistrano numa aplicação que já temos pronta e foi feita num Post anterior. Então, vamos para os próximos passos.

 

Instalando o Capistrano e Configurando o App

Nesta parte nós vamos configurar o Capistrano com o Plugin adicional para o Rails, Puma e RVM. Como exemplo, vamos pegar o código de um Post anterior que fizemos, adaptar para o Capistrano e depois subiremos num novo repositório.

Vamos utilizar o app que construímos no post “ActiveStorage: Usando na prática a nova ferramenta de upload do Rails”. O link do repositório é https://github.com/OneBitCodeBlog/awesome_bucket (é só baixar)

Lembrando que o que faremos aqui não é exclusivo para esse sistema e pode ser utilizado em diversas outras aplicações.

Então partiu código 🙂

 

1- Como nosso projeto inicialmente estava com Sqlite3, primeiro vamos adicionar a gem do Postgres.

Vamos remover do nosso Gemfile:

E adicionar:

2- Vamos executar o bundle

3- Após instalado a gem pg, nós não vamos configurar o database.yml e isso graças ao Capistrano. Mas daqui há pouco vamos ver 😉

4- Agora vamos adicionar no nosso Gemfile as gems que utilizaremos para o Capistrano. Lembre-se de adicionar no grupo :development do Gemfile, afinal só precisamos do Capistrano no ambiente de dev:

Adicionamos um require: false nas gems para que elas não sejam carregadas na aplicação. O Capistrano funcionará fora do contexto da aplicação.

5- Executar o bundle:

6- Com a gem instalada, vamos instalar o capistrano no nosso projeto apenas para produção:

Por padrão, o Capistrano traz arquivos de configuração para staging e production, mas com este parâmetro STAGES no comando cap install nós podemos escolher que arquivos de configuração vamos querer. Como o nosso foco neste post é produção, criei um apenas para production.

Com este comando que executamos, foram criados os arquivos:
• Capify que é responsável pela importação dos plugins para o Capistrano;
• um arquivo config/deploy.rb que é 
utilizada para adicionar as configurações de deploy que serão válidas para todos os ambinentes;
• e o arquivo config/deploy/production.rb que é onde colocaremos as
configurações de deploy exclusivas para produção.

Se fôssemos usar mais ambientes, mais um arquivo para cada ambiente seria criado dentro do diretório config/deploy.

7- Como adicionamos a gem pg e precisaremos dela no repositório, não podemos esquecer de comitar e subir a branch master.

8 – Crie um novo repositório no github e suba o seu projeto atualizado 🙂


Configurando o Capistrano para o Deploy

Com o Capistrano instalado e inicializado, agora podemos fazer as configurações para o Deploy Rails.

1- Vamos abrir o arquivo Capfile e adicionar e instalar os plugins. O nosso arquivo Capfile ficará desse jeito:

O que fizemos neste arquivo foi adicionar os requires dos plugins para o Capistrano do Rails, RMV e Puma. E depois instalamos 3 recursos do plugin do Puma: o suporte para o Puma, seus Workers e o Nginx.

2- Agora vamos adicionar algumas configurações globais para os nossos deploys, começando pelo nome da aplicação e o link do repositório (config/deploy.rb):

O capistrano já vem com alguns valores padrão, então onde estiver:

Vamos substituir por:

No Capistrano, utilizamos a função set para pode inserir um valor numa variável do próprio Capistrano.

3- Ainda no arquivo deploy.rb, vamos adicionar mais estas linhas e explicar o que significam (config/deploy.rb):

No Capistrano, utilizamos a função append para podermos adicionar um valor numa variável do Capistrano que seja do tipo Array. Se quisermos sobrescrever o valor desse array, podemos usar o set.

Na linha com deploy_to estamos configurando o caminho que ficará o nosso app no servidor. Na liked_files e linked_dirs, estamos configurando os diretórios e arquivos que serão linkados na nossa aplicação. No keep_releases é a quantidade de versões do app que será armazenada no servidor. E no migration_role, que é específico para o Capistrano-Rails, estamos informando com que role o Capistrano vai executar as migrations do banco de dados.

Se você estiver utilizando o arquivo de secrets.yml que vem em versões anteriores ao Rails 5.2, adicione-o no linked_files no lugar do master.keyremova o storage.yml caso não esteja utilizando o ActiveStorage.

Mais pra frente vamos explicar o que é uma Role e o que significa aqueles linked_files e linked_dirs no Capistrano.

 

4- Agora adicionaremos alguns últimos itens ainda no nosso arquivo deploy.rb (config/deploy.rb):

Adicionamos algumas configuração do plugin Capistrano-Puma. A variável shared_path é um padrão do Capistrano para mapear uma pasta onde podemos colocar os arquivos compartilhados ou que precisamos linkar com a aplicação (no próximo tópico vamos falar sobre isso). E na última linha, estamos utilizando uma configuração do Capistrano-RVM para informar a versão do Ruby que queremos usar. Repare que é a mesma versão que temos lockada no Gemfile.

 

5- Agora vamos adicionar as seguintes linhas no deploy.rb (config/deploy.rb)

Criamos duas tasks customizadas: uma chamada puma:create_dirs e outra chamada puma:nginx_restart e fizemos a chamada delas no final.

As tasks são responsáveis por criar os diretórios tmp/pidstmp/sockets e por enviar um comando para restart do Nginx.

 

6- Agora vamos ao arquivo de configuração específico para Produção adicionar as seguintes linhas (config/deploy/production.rb):

Na primeira linha, estamos informando qual branch do Git o Capistrano deve usar para baixar nossa aplicação, no nosso caso é a master mas você pode configurar conforme o seu fluxo de desenvolvimento ou ambiente.

Na segunda linha, estamos configurando uma variável nossa com o endereço do servidor.

Na terceira linha, estamos utilizando a função ask do Capistrano, que abre um prompt para input do usuário durante a execução e o valor digitado é armazenado na variável password. No nosso caso estamos solicitando que o usuário digite a senha de acesso ao servidor, que utilizaremos na linha de baixo.

Na quarta linha, estamos configurando um servidor com o endereço, o usuário (nosso caso é o deploy), a senha e as roles desse servidor.

Na quinta linha, estamos informando um server_name que será utilizando pelo Nginx.

E na última linha, estamos configurando o Puma para pré-carregar o aplicativo para que ele não precise carregar toda vez que uma requisição chegar.

Para que possamos pegar o valor de uma variável do Capistrano, utilizamos a função fetch. Na linha que configuramos o servidor, por exemplo, estamos passando a senha que armazenamos na variável password.

 

Conceitos importantes: Capistrano

Roles? Variáveis? Arquivos e Diretórios Linkados?

Estes são três conceitos do Capistrano que as vezes podem confundir um pouco.
Bem, então vamos por partes (um olá para o Jack).

1. Variáveis

O Capistrano possui variáveis internas que são utilizadas durante a configuração do deploy.
Estas variáveis podem ser padrão, como a variável :branch, e podem ser variáveis que nós criamos, como a :server_address. Para acessar essas variáveis, o Capistrano possui algumas funções:

  • set: atribui um valor a uma variável
  • append: utilizada para acrescentar um valor numa variável do tipo Array
  • fetch: resgata o valor de uma variável
  • ask: é parecida com a set. Porém o valor atribuído vem de prompt com o usuário

 

2. Arquivos e Diretórios Linkados

O Capistrano possui duas variáveis padrão, a linked_files e a linked_dirs. Estas duas variáveis armazena os arquivos e os diretórios que queremos linkar com a nossa aplicação.

Ok, mas o que é isso? No momento do deploy, o Capistrano cria no diretório da nossa aplicação, umas pasta chamada releases e outra chamada shared. Na pasta releases ficam as versões do app e na shared ficam os arquivos e diretórios que queremos linkar com a nossa aplicação. Colocamos nesse diretório tudo que achamos que deve ser algo exclusivo do ambiente e que não pode ou não precisa ser comitado.

Por exemplo, podemos colocar um link com a pasta tmp e outro com o arquivo config/database.yml e no momento do deploy o Capistrano vai remover esses dois diretórios do app e adicionar um link com a pasta shared.

 

3. Roles

Este é um conceito que não veremos profundamente nesse post, mas é um conceito muito legal do Capistrano.

Uma Role no Capistrano é um grupo de servidores. Um servidor pode ter diversas roles e uma role pode ter diversos servidores. É um relacionamento N x N.

Anteriormente nós declaramos um server e nele colocamos roles: %w{app db web}. Podemos fazer o contrário também, declarar uma role e nela colocar uma lista de servers. E o interessante: não há um impedimento para um server estar em duas ou mais roles e vice-versa.

Este conceito é muito útil quando estamos lidando com deploy em diversos servidores diferentes e podemos fazer um agrupamento lógico e aplicar determinadas tarefas a roles específicas.

O Capistrano possui três roles padrão que são appwebdb. Como estamos lidando com apenas um servidor, nós declaramos estas três roles para um único server.

 

4. Tudo é Task

Tudo que é executado no Capistrano é uma sequencia de rake tasks que vai seguindo um fluxo padrão de deploy.

O fluxo padrão do Capistrano possui diversas fases bem divididas. Mais fases podem ser acrescentadas, assim como o plugin Capistrano-Puma o faz.

Assim como o Rails possui os before_actionafter_action o Capistrano também possui um before e um after para que tasks customizadas sejam executadas entre uma fase e outra do fluxo de deploy, nos tornando capaz de agir sobre o fluxo padrão dele e customizar como precisarmos.

 

Executando o Deploy Rails

Com tudo configurado e alguns pontos esclarecidos, vamos agora voltar para o nosso deploy. Não se preocupe, falta pouco para completarmos a nossa jornada 😀

1- Para ver se falta algo que precisamos fazer, vamos executar o comando:

Este comando verifica se os arquivos e diretórios obrigatórios para rodar o Deploy estão lá. No nosso caso, estamos vendo para o deploy em produção (production).

2- Digite a senha

3- Olha o retorno que o Capistrano trouxe:

O Capistrano está nos informando que o arquivo que queremos criar, chamado database.yml na pasta shared/config ainda não existe. Pois bem, vamos criar os arquivos que serão linkados.

4- Vamos acessar o servidor com o usuário deploy e digitar a senha:

5- Agora vamos até o diretório /var/www/awesome_bucket

6- Perceba que os diretórios releases e shared foram criados, como dissemos anteriormente. Basta digitar o comando:

7- Agora vamos criar database.ym, storage.yml e master.yml dentro no shared/config:

Se você não estiver utilizando o ActiveStorage, não se preocupe com storage.yml.

Se estiver utilizando alguma versão do Rails anterior ao 5.2 que utilize o secrets.yml ou o arquivo pertinente à versão. Não se esqueça de criá-lo neste diretório e adicioná-lo ao linked_files.

8- Agora vamos acrescentar o conteúdo do database.yml:

9- Agora acrescente o conteúdo de configuração do storage.yml e o master.key (Se você estiver em uma aplicação rails >= 5.2).

10- Se executarmos o check novamente, não teremos mais nenhum erro

11- Agora vamos executar as configurações do Puma:

12- Agora as configurações do Nginx:

13- E por fim, vamos executar o nosso deploy:

Com este último deploy, agora podemos verificar o endereço do servidor no navegador e ver que o deploy foi um sucesso! =D



[PDF] Checklist completo de deploy \o/

Para você não esquecer nenhum detalhe na hora de subir seu APP 😁



Conclusão

Neste artigo nós realizamos o deploy completo na Digital Ocean com Rails + Nginx + Postgresql e automatizamos tudo isto com o Capistrano \o/

Siga o passo a passo adaptando às suas necessidades e se possível deixa aí em baixo nos comentários o link para a sua aplicação no ar, ficaremos felizes em ver tudo funcionando.

Não se esqueça de criar seu VPS usando esse link para ganhar os $10 na Digital Ocean e de baixar o Checklist de deploy logo a cima, valeu \o/

 


Você é novo por aqui?

Primeira vez no OneBitCode? Curtiu esse conteúdo? O OneBitCode tem muito mais para você!

O OneBitCode traz conteúdos de qualidade e em português sobre programação com foco em Ruby on Rails e outras tecnologias como Angular, Ionic, React, desenvolvimento de Chatbots e etc.

Se você deseja aprender mais, de uma forma natural e dentro de uma comunidade ativa, visite nosso Facebook e nosso Twitter, veja os screencasts e talks no Youtube, alguns acontecimentos no Instagram, ouça os Podcasts e faça parte de nossa Newsletter.

Além disso, também estamos com alguns e-Books muito interessantes para quem deseja se aprimorar como programador e também como freelancer (os e-Books são gratuitos!):

Espero que curta nossos conteúdos e sempre que precisar de ajuda com os tutoriais, fala com a gente! Seja por Facebook ou e-mail, estamos aqui para você 🙂

Bem-vindo à família OneBitCode \o/

abril 27, 2018

12
Deixe um comentário

avatar
6 Comment threads
6 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
8 Comment authors
Tobias Andre EggersFelipe SerpeloniLeonardo ScorzaFrancisco Felipe de LimaDaniel Moreto Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Joathan Francisco da Silva Souza
Visitante

Show de bola essa postagem, ainda não a fiz por completo, mas como fiquei em duvida, estou aqui para perguntar. 🙂
Em um determinado servidor, observei que o mesmo tem varias aplicações em ruby on rails e todas elas estão sendo executadas ao mesmo tempo e na mesma porta (80). A diferença é no dominio (ex: app1.example.com, app2.example.com, app3.example.com), cada aplicação tem um dominio diferente! Existe alguma configuração especifica para ser feita, qual seria?

Leonardo Scorza

E ai cara, beleza?
Fico feliz que esteja acompanhando o tutorial, pega o final de semana pra terminar ele 🙂
Sobre essa configuração de domínio você pode ver mais aqui: http://do.co/2plOfqu
Abraço

Tiago
Membro

Show de bola… Em pouco tempo consegui colocar a aplicação no ar!

Leonardo Scorza

Opa, que bom que deu certo Tiago 🙂
Você viu esse post pela comunidade ou google?
Abraço

Gustavo Araújo
Visitante
Gustavo Araújo

Segui o tutorial certinho. Mas quando eu tento acessar a url, ele dá um erro 500.
Quando eu vou ver o log de erro do nginx, ele diz isso:shared/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream

Gustavo Araújo
Visitante
Gustavo Araújo

Já sei o que está ocorrendo, mas ainda não sei como resolver. xD Acontece que eu organizei os meus shared files de forma diferente que o do tutorial. Ao invés de colocar o database e o secrets.yml, eu coloco um arquivo de configuração de ambiente. (Assim eu teria um por ambiente) e seto as varíaveis lá.
Logo, minha estrtura é essa: var/www/app/enviroment/shared ao invés de var/www/app/shared. Quando eu fui olhar o arquivo de configuração que ele gera no meu ngnx, ele espera da segunda forma. estou vendo onde posso mudar isso. 🙂

Leonardo Scorza

Participa da nossa comunidade aqui -> https://onebitcodeslack.herokuapp.com/ e chama a gente lá se precisar de um help 🙂
Abraço

Francisco Felipe de Lima
Visitante

Fala galera, bem bacana o tutorial. Vai ajudar bastante gente. Acho que seria bacana complementar com um passo para desativar o login de root do servidor (premissa básica de segurança).
Também acho legal para configuração em produção mudar o Puma para o Passenger ou até mesmo para o Unicorn. Eu particularmente já tive problemas com o Puma, porém, isso vai de dev para dev.

Abração, continuem com o bom trabalho.

Leonardo Scorza

Valeu pela contribuição Francisco 🙂

Felipe Serpeloni
Membro
Felipe Serpeloni

Bom dia

Fiz o deploy de uma aplicação e funcionou corretamente. Mas em vez de ser um dominio, ele está em um subdominio (ex: http://www.site.com.br/app1).

Tentei fazer o deploy de uma segunda app, no mesmo servidor, com um outro subdominio, mas não consegui fazer funcionar. O deploy não mostra erro, entretanto ao acessar o app no navegador, ele não é encontrado.

Existe alguma configuração especial no nginx para o caso de mais de um app no mesmo servidor, onde cada um é um subdominio do servidor?

Obrigado.

Tobias Andre Eggers
Visitante
Tobias Andre Eggers

E ai pessoal, beleza?
Excelente artigo.
Tentei utiliza-lo com um projeto meu, e estou tendo o seguinte problema:

00:34 deploy assets precompile:
01 ~/.rvm/bin/rvm 2.5.1 do bundle exec rake assets:precompile
01 rake aborted!
01 ActiveSupport::MessageEncryptor::InvalidMessage: ActiveSupport::MessageEncryptor::InvalidMessage::

O Estranho eh que rodando esse comando la direto na VPS ele da o mesmo erro, mas se eu substituir o ‘rake assets:precompile’ por ‘rails assets:precompile’ funciona. =/

Meu projeto usa rails 5.2.1 e Ruby 2.5.1.. sera algum problema com versao? é possivel alterar esse comando assets:precompile no projeto?

Feito com s2 por OneBitCode
%d blogueiros gostam disto: