fly-apps/dockerfile-rails

vendor directory is empty in CI

Opened this issue · 1 comments

Hello, I am trying to use this dockerfile in a rails 6.1 project to run tests in Gitlab CI.

The build step runs fine with kaniko, but the test step fails with bundler: command not found: rails. When I check what the vendor directory contains, it looks OK in the build step, but empty in the test step.

This is my dockerfile.yml

# generated by dockerfile-rails

---
options:
  cache: true
  ci: true
  jemalloc: true
  mysql: true
  redis: true
  root: true
  packages:
    build:
    - git
    - ruby-dev
    - gcc
    - make
    - g++
    - libffi-dev
    - libmariadb-dev-compat

This is the Dockerfile

# syntax = docker/dockerfile:1

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.1.4
FROM ruby:$RUBY_VERSION-slim as base

# Rails app lives here
WORKDIR /rails

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_WITHOUT="development" \
    BUNDLE_DEPLOYMENT="1"

# Update gems and bundler
RUN gem update --system --no-document && \
    gem install -N bundler


# Throw-away build stage to reduce size of final image
FROM base as build

# Install packages needed to build gems and node modules
RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
    --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
    apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential curl default-libmysqlclient-dev g++ gcc git libffi-dev libmariadb-dev-compat make node-gyp pkg-config python-is-python3 ruby-dev

# Install Node.js
ARG NODE_VERSION=17.6.0
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    rm -rf /tmp/node-build-master

# Install application gems
COPY --link Gemfile Gemfile.lock ./
RUN --mount=type=cache,id=bld-gem-cache,sharing=locked,target=/srv/vendor \
    bundle config set app_config .bundle && \
    bundle config set path /srv/vendor && \
    bundle install && \
    bundle exec bootsnap precompile --gemfile && \
    bundle clean && \
    mkdir -p vendor && \
    bundle config set path vendor && \
    cp -ar /srv/vendor .

# Install node modules
COPY --link package.json package-lock.json ./
RUN --mount=type=cache,id=bld-npm-cache,target=/root/.npm \
    npm install

# Copy application code
COPY --link . .

# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/


# Final stage for app image
FROM base

# Install packages needed for deployment
RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
    --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
    apt-get update -qq && \
    apt-get install --no-install-recommends -y curl default-mysql-client imagemagick libjemalloc2

# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails

# Deployment options
ENV LD_PRELOAD="libjemalloc.so.2" \
    MALLOC_CONF="dirty_decay_ms:1000,narenas:2,background_thread:true" \
    RAILS_LOG_TO_STDOUT="1" \
    RAILS_SERVE_STATIC_FILES="true"

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD ["./bin/rails", "server"]

This is the kaniko command in the build step:

  script:
    - mkdir -p /kaniko/.docker
    - export container=docker
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --force --cache=false --context $CI_PROJECT_DIR --dockerfile Dockerfile --build-arg BUILDKIT_INLINE_CACHE=1 --build-arg RAILS_MASTER_KEY=$MASTER_KEY --destination $CI_REGISTRY_IMAGE:$DESTINATION_TAG

Try without the cache option?

The way dockerfile caches work is that they are on a separate volume that is mounted only for that one step.