docker / build-push-action

GitHub Action to build and push Docker images with Buildx
https://github.com/marketplace/actions/build-and-push-docker-images
Apache License 2.0
4.24k stars 541 forks source link

Multistage build: using builder image before it is built #927

Closed fragkakis closed 1 year ago

fragkakis commented 1 year ago

Behaviour

I have a multistage docker build with 2 images: a builder image and a production image. The builder image contains additional things that I don't need in production. I am only using it to do some groundwork and copy the results to the production image. Pretty much the default scenario builder images are used for. My dockerfile is functional, it is being used in production for years. I am migrating its building to Github Actions.

I am seeing that the production image step that copies things from the builder image is being executed while the builder image is still being built. Notice below the first line vs the last two lines.

2023-08-10T18:45:02.0757808Z #16 [production  4/11] COPY --from=Builder /usr/local/bundle/ /usr/local/bundle/
2023-08-10T18:45:02.0758390Z #16 CACHED
2023-08-10T18:45:02.0759068Z 
2023-08-10T18:45:02.0759339Z #17 [production  5/11] WORKDIR /home/workable/app
2023-08-10T18:45:02.0759850Z #17 CACHED
2023-08-10T18:45:02.0760077Z 
2023-08-10T18:45:02.0763047Z #18 [builder 6/6] RUN gem install bundler:2.4.10 &&     bundle config set without 'development test integration' &&     bundle config set deployment 'true' &&     bundle config set path vendor/bundle &&     bundle install --jobs=4 &&     rm -rf /usr/local/bundle/cache/*.gem &&     rm -rf vendor/bundle/ruby/3.2.0/cache/*.gem &&     find vendor/bundle/ruby/3.2.0/gems/ -name "*.c" -delete &&     find vendor/bundle/ruby/3.2.0/gems/ -name "*.o" -delete &&     find vendor/bundle/ruby/3.2.0/gems/ -mindepth 2 -maxdepth 2 -type d ( -name spec -o -name test ) -exec rm -rf *** +
2023-08-10T18:45:02.0764396Z #18 CACHED

Steps to reproduce this issue

  1. Create a multistage Dockerfile
  2. Build it using the build-push-action

Expected behaviour

I would expect that the builder image is built first, and only then would the steps from the production image using it should appear.

Actual behaviour

I am seeing that the production image step that copies things from the builder image is being executed while the builder image is still being built.

Configuration

FROM gcr.io/staging-artifacts-... as Builder

ENV ...

# OS dependencies
USER root
RUN apk add --update --no-cache \
    ...

WORKDIR $APP_HOME

# Only copy the Gemfiles without any other source code so that we can install the gems
COPY Gemfile $APP_HOME/Gemfile
COPY Gemfile.lock $APP_HOME/Gemfile.lock

# Bundle install
RUN gem install bundler:2.4.10 && \
    ...

###############################
# Stage Final
###############################

FROM gcr.io/staging-artifacts-... as Production

ENV ...

USER root

RUN ...

# copy app with gems from former build stage
COPY --from=Builder /usr/local/bundle/ /usr/local/bundle/

WORKDIR $APP_HOME

# copy the app's source code
COPY --chown=my_project . $APP_HOME
# copy the gems from the builder image
COPY --from=Builder --chown=my_project $APP_HOME/vendor/bundle/ $APP_HOME/vendor/bundle/

USER my_project

Logs

Unfortunately I can't share the logs as they may contain sensitive information. If the snippet from the logs I pasted above is not enough, I will try to redact it and attach it.

crazy-max commented 1 year ago

I don't think this is related to the action but your Dockerfile. I can move this to the buildx repo as a discussion if this is something you don't repro locally.

fragkakis commented 1 year ago

OK, I started a discussion for now, and will create a spinoff issue there if I don't figure this out. Thanks!