Running make once yields an error suggesting that $(shell docker run -d $(IMAGE)) is not working as intended.
However running a second time works like a charm.
Seems like make build-image build-api causes the target build-api to not wait for the completion of build-image? Should i introduce a delayed execution? (the infamous sleep :D)
$ cat Makefile
.PHONY: build
IMAGE := tensorflow-serving-grpc
build: build-image build-api
clean:
-docker rmi -f $(IMAGE)
build-image:
docker build -t $(IMAGE) .
build-api: CONTAINER_ID:=$(shell docker run -d $(IMAGE))
build-api:
docker wait $(CONTAINER_ID)
docker cp $(CONTAINER_ID):/usr/src/vendor ./
docker rm -f $(CONTAINER_ID)
If it doesn't wait then it's because you allowed parallel execution with run it from $(shell...). Using $(shell ...) should be avoided unless you know what you do.-jN option
You should also prevent parallel execution of build-image and build-api by declaring a prerequisite.
.ONESHELL:
build-api: build-image
set -e
CONTAINER_ID=`docker run -d $(IMAGE)`
docker wait $$(CONTAINER_ID)
docker cp $$(CONTAINER_ID):/usr/src/vendor ./
docker rm -f $$(CONTAINER_ID)
You have a target specific variable with a side effect, and you're making the incorrect assumption that the variable won't be expanded until the rule is run. I would switch to using a bash variable, and concatenating the recipe to be run in a single shell as follows:
build-api: build-image
CONTAINER_ID=$$(docker run -d $(IMAGE)); \
docker wait $${CONTAINER_ID}; \
docker cp $${CONTAINER_ID}:/usr/src/vendor ./; \
docker rm -f $${CONTAINER_ID};
Another option is to create a target which creates the container id, and stores it in a file. Make build-api dependent on this new target, and then in build-api, have each recipe line read the value from the file.