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!