Empacotador de cache ao construir uma imagem de aplicativo ruby ​​/ rails com docker

Mecanismo de cache do Docker

O Docker tem um mecanismo de cache automático para acelerar bastante as coisas após a primeira compilação de um Dockerfile. Cada etapa (cada instrução docker do arquivo) é armazenada em cache separadamente. Se você alterar uma instrução docker, o Docker puxará os resultados do cache de sua etapa anterior. Pode ser muito útil, especialmente se você está construindo ruby ​​a partir de fontes ou tem muitas dependências enormes como o Nokogiri.

Advertência de Bundler

Com um aplicativo Rails, uma advertência óbvia aparece logo após algumas reconstruções de uma imagem:

Você tem que sentar e esperar que o Bundler termine de instalar todas as dependências, mesmo que Gemfile / Gemfile.lock não tenha mudado em nada.

Não é uma solução viável mantê-lo assim, Bundler pode levar muito tempo e, por exemplo, se
você executar seu conjunto de testes dentro de um contêiner e estiver desenvolvendo um novo teste, precisará reconstruir a imagem com muita frequência , esperando nervosamente na frente de sua mesa que Bundler terminou seu trabalho.

Como podemos armazenar em cache a etapa de instalação do pacote?

É muito simples usar o mecanismo de cache automático do docker para armazenar em cache a instalação do pacote.

Começaremos com este Dockerfile baseado no repositório oficial de linguagem que adiciona todo o aplicativo Rails dentro da imagem:

FROM ruby:2.1.2

# Install bundler.
RUN gem install bundler


# Now copy the app into the image.
COPY
. /rails

# Install ruby gems.
RUN cd
/rails && bundle install

# Set the final working dir to the Rails app's location.
WORKDIR
/rails

Só precisamos adicionar Gemfile / Gemfile.lock dentro da imagem antes da instalação do pacote:

FROM ruby:2.1.2

# Install bundler.
RUN gem install bundler


# Install ruby gems.
RUN cd
/rails && bundle install

# Copy the Gemfile and Gemfile.lock into the image.
COPY
Gemfile /rails/Gemfile
COPY
Gemfile.lock /rails/Gemfile.lock

# Install ruby gems.
RUN cd $APP
&& bundle install

# Everything up to here was cached. This includes
# the bundle install, unless the Gemfiles changed.

# Now copy the app into the image.
COPY
. /rails

# Set the final working dir to the Rails app's location.
WORKDIR
/rails

Agora, a reconstrução desta imagem não executará Bundler novamente se você modificar um arquivo em seu aplicativo, a menos que
você esteja alterando algo no Gemfile ou Gemfile.lock (ou no próprio Dockerfile).

Feliz hackeamento!