Incrementally build Docker image hierarchy with Makefile

In a project of mine I have several Docker images that base on each others, because I don’t need to rebuild basic parts of it every time and just want to incrementally build the upper layers of the hierarchy.

I build the images by means of a Makefile. I do this because I’m admittedly lazy and don’t want to enter the whole docker build commands manually every time. And also because I want to avoid making mistakes in the process.

  • Building docker for the ARM-64 architecture
  • pdf2htmlEX cannot open or read file
  • Errors building two different projects with stack on the same machine
  • Multiple commands for Mongo Docker image
  • .Net - Pushing logs from web application to Docker container running Fluentd
  • Docker Hub Automated Build - Tagging
  • What I would like to do now is make make able to detect whether a Docker image has to be rebuild instead of Docker itself because for the latter the Docker build context has to be sent to the Docker daemon every time. The image is quite large because it is based on ubuntu:xenial and so the “Sending build context to Docker daemon” always takes a lot of time for each individual Docker image, independently of whether they need to be rebuilt or not.

    If make was able to detect whether the docker build command needs to be executed that would help a lot to speed up the process.

    So I would like to know if there’s a way for make to detect if a specific Docker image needs to be rebuilt.

  • Setting up multiple Docker containers and MongoDB to run in CircleCI
  • 100 docker containers vs 100 small machines
  • Mounting host volume for mongo data in docker compose container
  • Is it beneficial to compile Java code directly into native exe in Docker environment
  • Error on Docker Pull - “Layer already being pulled by another client”
  • How to create a volume from a local path in a Dockerfile?
  • One Solution collect form web for “Incrementally build Docker image hierarchy with Makefile”

    Assuming:

    • your docker images are named dia, dib, dic
    • their respective docker files are named dockerfile.dia, dockerfile.dib, dockerfile.dic
    • their corresponding build directories are ./dia.dir/, ./dib.dir/, ./dic.dir/
    • dia depends on files foo, bar in ./dia.dir/
    • dib depends on file cuz in ./dib.dir/ and the docker image dia
    • dic depends on file baz in ./dic.dir/ and the docker image dib

    you can try something like (not tested):

    DOCKERIMAGES := dia dib dic
    TAGS := $(patsubst %,.%.tag,$(DOCKERIMAGES))
    diaDEPS := foo bar
    dibDEPS := cuz
    dicDEPS := baz
    
    all: $(TAGS)
    
    $(TAGS): .%.tag: dockerfile.%
        docker build -f $< -t $* $*.dir && \
        echo '$* image built' && \
        touch $@
    
    define DEPS_rule
    .$(1).tag: $$(addprefix $(1).dir/,$$($(1)DEPS))
    endef
    
    $(foreach d,$(DOCKERIMAGES),$(eval $(call DEPS_rule,$(d))))
    
    .dib.tag: .dia.tag
    .dic.tag: .dib.tag
    
    clean:
        rm -f $(TAGS)
    

    It should rebuild the docker images only if their docker file changed, or the files they depend on in their directories changed, or the docker image they depend on, changed.

    Docker will be the best open platform for developers and sysadmins to build, ship, and run distributed applications.