ruby-docker
ruby-docker copied to clipboard
Reuse gems from previous version
I noticed that every time I run gcloud app deploy
, bundle install
will be execute, and it will refeching gems and install them again, even the ruby version and Gemfile.lock
are not updated.
Wondering if there is a way for us to reuse the gems we fetched before, so that it can speed up the deployments.
+1
I can do it via cloud build by adding following docker file in my repo as ruby-base.dockerfile:
# This file is generated base on generate-dockerfile from follow repo:
# https://github.com/GoogleCloudPlatform/ruby-docker/tree/master/ruby-generate-dockerfile
ARG ruby_version=2.6.4
ARG prebuilt_image=gcr.io/gcp-runtimes/ruby/ubuntu16/prebuilt/ruby-2.6.4:latest
FROM $prebuilt_image as prebuilt-ruby
FROM gcr.io/gcp-runtimes/ruby/ubuntu16:latest AS augmented-base
ARG ruby_version=2.6.4
ARG bundler_version=2.0.2
ARG rails_env=production
## Commonly installed gems (e.g. bundler) are available from this image.
COPY --from=gcr.io/gcp-runtimes/ruby/ubuntu16/build-tools:latest /opt/gems/ /opt/gems/
## Install Ruby ${ruby_version} from a prebuilt image. If a prebuilt image
## is not available, use the alternate installation method commented below.
COPY --from=prebuilt-ruby \
/opt/rbenv/versions/${ruby_version} \
/opt/rbenv/versions/${ruby_version}
RUN echo "This is the ruby version ${ruby_version}"
RUN rbenv global $ruby_version \
&& rbenv rehash \
&& (gem install /opt/gems/bundler-${bundler_version}.gem ; \
rbenv rehash);
## Alternate installation for Ruby versions that have no prebuilt image.
# RUN if [ ! -x ${RBENV_ROOT}/versions/${ruby_version}/bin/ruby ]; \
# then \
# cd ${RBENV_ROOT}/plugins/ruby-build \
# && git pull \
# && rbenv install -s ${ruby_version} \
# && rbenv global ${ruby_version} \
# && rbenv rehash \
# && (gem install /opt/gems/bundler-${bundler_version}.gem ; \
# rbenv rehash); \
# fi
COPY ./Gemfile /app/
COPY ./Gemfile.lock /app/
RUN bundle install --deployment && rbenv rehash
ENTRYPOINT []
Then in cloudbuild.yml
file, I added this step:
- name: 'gcr.io/cloud-builders/docker'
id: preinstall-gems
entrypoint: 'bash'
args:
- '-c'
- |
docker build -t gcr.io/${PROJECT_ID}/ruby-base/${COMMIT_SHA} \
--file ruby-base.dockerfile \
--build-arg ruby_version=$(cat .ruby-version) \
--build-arg prebuilt_image=gcr.io/gcp-runtimes/ruby/ubuntu16/prebuilt/ruby-$(cat .ruby-version):latest \
.
docker push gcr.io/${PROJECT_ID}/ruby-base/${COMMIT_SHA}
# Generate dockerfile for app engine
- name: 'gcr.io/gcp-runtimes/ruby/ubuntu16/generate-dockerfile'
id: generate-dockerfile
env: [
'PROJECT_ID=${PROJECT_ID}'
]
args: [
'--base-image','gcr.io/${PROJECT_ID}/ruby-base/${COMMIT_SHA}:latest',
'--build-tools-image', 'gcr.io/gcp-runtimes/ruby/ubuntu16/build-tools:latest'
]
# Build docker image for app engine
- name: 'gcr.io/cloud-builders/gcloud'
id: deploy-appengine
entrypoint: /bin/bash
args:
- '-c'
- |
gcloud config set app/cloud_build_timeout 1200
gcloud app deploy ./app.yaml ${_TRAFFIC}
waitFor: ['generate-dockerfile', 'preinstall-gems']
timeout: 1200s
timeout: 1200s
But of course, we still reinstall the gems when Gemfile.lock
is not changed. Might need to take idea from this blogpost for yarn cache:
https://medium.com/hackernoon/using-yarn-with-docker-c116ad289d56