Search code examples
dockermakefilegnu

GNU make creating Docker container and using Image id


I am trying to create a recipe that will execute my lint results inside my docker container, and copy the results.xml outside the container. Here is my recipe:

lint-results:
    docker build --target lint path_to_my_src_dir -t $(my_lint_image_tag)
    $(eval tmp_lint_container_id:=$(shell docker create $(my_lint_image_tag))) # This step seems to execute too quick
    @echo my lint constainer id is $(tmp_lint_container_id)
    docker cp $(tmp_lint_container_id):/usr/src/app/results.xml ./
    docker rm -v $(tmp_lint_container_id)

The problem I'm having is after it successfully creates the $(my_lint_image_tag) from the docker build and moves on to create the container. The first time around it errors out and the echoed output for $(tmp_lint_container_id) is blank, but if I run it again it works. It seems to only fail the first time around if initially, the image wasn't there, almost like it's running the shell command to quickly after the docker image is built.

Here a snippet if the output of the error:

Removing intermediate container a6f4eb8ac404
 ---> 01cb85644929
Successfully built 01cb85644929
Successfully tagged my-lint-image-1.1.1.1:latest
my lint constainer id is
docker cp :/usr/src/app/results.xml ./
must specify at least one container source
make: *** [lint-results] Error 1

Is there a way to ensure docker image is there before the shell command is ran?


Solution

  • Pro Tip #1: If you are using $(eval ..) or $(shell ...) inside a recipe, you are almost invariably doing something wrong.

    Use shell variables, not make variables, to hold values inside recipes. Like this:

    lint-results:
            docker build --target lint path_to_my_src_dir -t $(my_lint_image_tag)
            tmp_lint_container_id=$$(docker create $(my_lint_image_tag)) && \
            docker cp $$tmp_lint_container_id:/usr/src/app/results.xml ./ && \
            docker rm -v $$tmp_lint_container_id