0

I want to create a two step multistage build as follows:

1- Dockerfile -> contains all common tools installed

2.1- Dockerfile.extensionA -> contains tools only used in Application A

2.2- Dockerfile.extensionB -> contains tools only used in Application B

This way, instead of having two huge Dockerfiles, one for A and one for B, which are 90% alike, I have one base big Dockerfile and two (or more) small specialization Dockerfiles, so I can generate two images that share most of the installation, so if only appA is needed, only the extentions for appA are installed:

  • image_appA
  • image_appB
  • ...

The contents might be something like:

Dockerfile
FROM ubuntu:20.04 AS BASE_IMAGE
... base configuration common for all extentions

.

Dockerfile.extensionA
FROM BASE_IMAGE
... specific config for A

.

Dockerfile.extensionB
FROM BASE_IMAGE
... specific config for B

And so I would like to do something like:

$ docker build -t image_appA -f Dockerfile.extensionA .

And get a sequential build Dockerfile and Dockerfile.extensionA

ADD: Before marking as duplicated, I've researched Multistage builds in Docker extensively but all I can find is the idea of picking stuff from the base image. But I want to inherit the full base image, and build on top of it the extension for appA, appB or any other

Sanjo
  • 78
  • 8

1 Answers1

1

You need to manually docker build -t BASE_IMAGE .. There's not any short-cut around this, unfortunately.

The flip side of this is that you don't actually need to rebuild the base image if you haven't changed anything in it, or if you're just going to build the other application. In a larger organization you also might consider putting the base image in its own repository and setting up a CI system for it, so that more teams can use it and you don't have to rebuild it by hand.

docker build -t BASE_IMAGE .
docker build -t image_appA -f Dockerfile.extensionA .

...

$EDITOR appA/some_file.ex
./appA/run_unit_tests

# probably don't need to rebuild BASE_IMAGE
docker build -t image_appA -f Dockerfile.extensionA .

Docker Compose also doesn't support this case at all. Compose doesn't have a way to build an image without starting a corresponding container, and it doesn't have any way to order builds (depends_on: only affects container startup). If you're using Compose, probably the best approach is to only declare the actual application images and containers in the docker-compose.yml file and manually build the base image.

version: '3.8'
services:
  a:
    build:
      context: .
      dockerfile: Dockerfile.extensionA
  b:
    build:
      context: .
      dockerfile: Dockerfile.extensionB
docker build -t BASE_IMAGE .
docker-compose build
docker-compose up -d
David Maze
  • 130,717
  • 29
  • 175
  • 215
  • That's a shame! Now I have both image_base (11.8GB) and image_extA (11.9GB). Does it mean that I have ~24GB used? or does it inherit from image_base? – Sanjo Aug 11 '22 at 15:48
  • It inherits from the base image; there should be only one copy of the base image's layers on disk, even if you've built multiple images `FROM` it. – David Maze Aug 11 '22 at 16:16