5

I have an application with a production Dockerfile that copies our source code into the container, i.e:

COPY . /app

I would like to make this copy conditional, so that passing in a CONTEXT= environment variable prevents/allows this line to execute. Is that possible?

I saw related posts on here but no clear answer. Thanks!

dylanized
  • 3,765
  • 6
  • 32
  • 44
  • ...how does the non-production Dockerfile get code into the image? Why are the production and non-production images different? – David Maze Sep 03 '20 at 20:21
  • The development container gets launched via Docker-Compose, which mounts a volume at `/app` and then (hopefully) loads this Dockerfile – dylanized Sep 03 '20 at 22:30
  • @DavidMaze has a point, as the production and development container should be built the same. You could use a volume at `/app` without any problems, as it would override the image's content. – Gustavo Kawamoto Sep 04 '20 at 00:52
  • 1
    Thanks Gusavo, I did not know the volumes would override copied folders! Although that's not a perfect solution because the COPY command takes time to run, 20sec in my case... – dylanized Sep 04 '20 at 17:08

2 Answers2

5

From this post I discovered that Docker-Compose 3.7 supports targeting individual build stages.

So I created a Dockerfile with 2 stages, a base layer that sets up the container, then a deploy that copies in the codebase:

# BUILD STAGE 1 - BASE
FROM webdevops/php-apache:7.2-alpine as base

# Do stuff

# BUILD STAGE 2 - DEPLOY
FROM base as deploy

# Add project
COPY . /app

# Do other stuff

Then I configured my dev docker-compose.yml to target only the base layer, and to mount a volume for the code.

version: "3.7"

services:
  app.base.img:
    build:
      context: .
      target: base
    volumes:
      - ./:/app
    container_name: app.base

My production pipeline builds the image normally (with both layers).

Note the version 3.7 declaration, apparently it's required.

This does what I want, thanks for all the comments and suggestions on this! If you think this is unwise feel free to comment.

dylanized
  • 3,765
  • 6
  • 32
  • 44
2

No. You should pre-process your project before building the final image.

Multistage builds might help you do that:

FROM debian AS builder
ARG CONTEXT
WORKDIR /final
COPY . /app
RUN bash -c "[ '$CONTEXT' = '1' ] || cp -rfv /app/* /final/"

FROM debian
COPY --from=builder /final /app

In this example, passing --build-arg CONTEXT=1 prevents it from filling the /app folder in the final image, thus removing it from the final image.

Gustavo Kawamoto
  • 2,665
  • 18
  • 27
  • 1
    Thanks for this example, this is a creative solution. I didn't know about the `COPY --from` feature! I'm going to keep the question open for now to see if anyone else has ideas – dylanized Sep 04 '20 at 17:19