From c242f619358cc3f74be290c8560dc7c31e727cae Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Wed, 30 Nov 2016 14:25:24 -0500 Subject: [PATCH] [BUILD] Make docker-image building more reliable We need to create a tighter coupling between the build system and the resulting docker images to prevent make from over-optimizing steps away. Fixes FAB-1145 Change-Id: I50c7cdf98e173c88ff6722d6c28aeade7395428e Signed-off-by: Greg Haskins --- Makefile | 20 ++++++++++---------- docker-env.mk | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index bad7614d604..86eadcd52cd 100644 --- a/Makefile +++ b/Makefile @@ -89,20 +89,20 @@ membersrvc-image: .PHONY: peer peer: build/bin/peer -peer-docker: build/image/peer/.dummy +peer-docker: build/image/peer/$(DUMMY) .PHONY: orderer orderer: build/bin/orderer -orderer-docker: build/image/orderer/.dummy +orderer-docker: build/image/orderer/$(DUMMY) -testenv: build/image/testenv/.dummy +testenv: build/image/testenv/$(DUMMY) unit-test: peer-docker testenv cd unit-test && docker-compose up --abort-on-container-exit --force-recreate && docker-compose down unit-tests: unit-test -docker: $(patsubst %,build/image/%/.dummy, $(IMAGES)) +docker: $(patsubst %,build/image/%/$(DUMMY), $(IMAGES)) native: peer orderer behave-deps: docker peer build/bin/block-listener @@ -152,12 +152,12 @@ build/docker/busybox: make -f busybox/Makefile install BINDIR=$(@D) # Both peer and peer-docker depend on ccenv and javaenv (all docker env images it supports). -build/bin/peer: build/image/ccenv/.dummy build/image/javaenv/.dummy -build/image/peer/.dummy: build/image/ccenv/.dummy build/image/javaenv/.dummy +build/bin/peer: build/image/ccenv/$(DUMMY) build/image/javaenv/$(DUMMY) +build/image/peer/$(DUMMY): build/image/ccenv/$(DUMMY) build/image/javaenv/$(DUMMY) # Both peer-docker and orderer-docker depend on the runtime image -build/image/peer/.dummy: build/image/runtime/.dummy -build/image/orderer/.dummy: build/image/runtime/.dummy +build/image/peer/$(DUMMY): build/image/runtime/$(DUMMY) +build/image/orderer/$(DUMMY): build/image/runtime/$(DUMMY) build/bin/%: $(PROJECT_FILES) @mkdir -p $(@D) @@ -185,8 +185,8 @@ build/image/%/payload: mkdir -p $@ cp $^ $@ -build/image/%/.dummy: Makefile build/image/%/payload - $(eval TARGET = ${patsubst build/image/%/.dummy,%,${@}}) +build/image/%/$(DUMMY): Makefile build/image/%/payload + $(eval TARGET = ${patsubst build/image/%/$(DUMMY),%,${@}}) @echo "Building docker $(TARGET)-image" @cat images/$(TARGET)/Dockerfile.in \ | sed -e 's/_BASE_TAG_/$(BASE_DOCKER_TAG)/g' \ diff --git a/docker-env.mk b/docker-env.mk index 7476d83061e..07941c1a4e5 100644 --- a/docker-env.mk +++ b/docker-env.mk @@ -56,5 +56,32 @@ BASE_DOCKER_TAG=$(ARCH)-$(BASEIMAGE_RELEASE) DOCKER_GO_LDFLAGS += $(GO_LDFLAGS) DOCKER_GO_LDFLAGS += -linkmode external -extldflags '-static -lpthread' +# +# What is a .dummy file? +# +# Make is designed to work with files. It uses the presence (or lack thereof) +# and timestamps of files when deciding if a given target needs to be rebuilt. +# Docker containers throw a wrench into the works because the output of docker +# builds do not translate into standard files that makefile rules can evaluate. +# Therefore, we have to fake it. We do this by constructioning our rules such +# as +# my-docker-target/.dummy: +# docker build ... +# touch $@ +# +# If the docker-build succeeds, the touch operation creates/updates the .dummy +# file. If it fails, the touch command never runs. This means the .dummy +# file follows relatively 1:1 with the underlying container. +# +# This isn't perfect, however. For instance, someone could delete a docker +# container using docker-rmi outside of the build, and make would be fooled +# into thinking the dependency is statisfied when it really isn't. This is +# our closest approximation we can come up with. +# +# As an aside, also note that we incorporate the version number in the .dummy +# file to differentiate different tags to fix FAB-1145 +# +DUMMY = .dummy-$(DOCKER_TAG) +