From 48c77f85a14449128160135307c85b284b02d343 Mon Sep 17 00:00:00 2001 From: Greg Paussa <50457169+gpaussabrcm@users.noreply.github.com> Date: Sat, 13 Jul 2019 15:43:45 -0400 Subject: [PATCH] [build] Add option to avoid Docker base image :latest tag (#3124) Define slave_base_tag_ref variable in Makefile.work containing specific base image tag to use, rather than always defaulting to :latest. Add an ARG command before FROM statement in Dockerfile.user for sonic-slave and sonic-slave-stretch. ARG variable defaults to latest if slave_base_tag_ref not specified in Makefile.work. The presumption to always refer to the :latest tagged Docker base image when creating the user image causes problems in a shared build server environment, where the most recently created base image (i.e. the current :latest tag) may not be compatible with the current build. For example, different users working in different branches may all be sharing the same build server. Signed-off-by: Greg Paussa greg.paussa@broadcom.com - What I did Added a DOCKER_AVOID_BASE_TAG_LATEST build option to rules/config that forces the Docker user image creation to refer to its base image by a specific tag rather than rely on the :latest tag. This is needed in a shared build server environment where builds from different developers and/or different SONiC branches all converge on the same Docker daemon instance running on the build server. The :latest tag is always assigned to the most recent base image built, which might not correspond to the base image needed for a particular build, thus causing various build errors that mostly manifest as missing Debian packages or package version mismatches. NOTE TO REVIEWERS: This PR relies on Docker support of "ARG before FROM," which was first introduced in Docker version 17.05.1-ce. Although there is no mention of a minimum required Docker version for the build server in the SONiC Building Guide pages, please consider whether it is reasonable to assume that Docker 17.05.1-ce or later must be used for SONiC build hosts before approving this PR. - How I did it Added an ARG before the FROM statement at the top of the sonic-slave/Dockerfile.user and sonic-slave-stretch/Dockerfile.user files. The ARG variable defaults to latest, but can be overridden in Makefile.work to reference the SLAVE_BASE_TAG so that it refers to the specific, matching base image for the build. This override is activated by un-commenting the DOCKER_AVOID_BASE_TAG_LATEST = y line in rules/config. --- Makefile.work | 21 +++++++++++++++------ sonic-slave-stretch/Dockerfile.user | 3 ++- sonic-slave/Dockerfile.user | 3 ++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Makefile.work b/Makefile.work index 88780724e..cd867a46e 100644 --- a/Makefile.work +++ b/Makefile.work @@ -42,6 +42,16 @@ ifeq ($(USER), root) $(error Add your user account to docker group and use your user account to make. root or sudo are not supported!) endif +# Check for minimum Docker version on build host +# Note: Using the greater of CE (17.05.0) and EE (17.06.1) versions that support ARG before FROM +docker_min := 17.06.1 +docker_min_ver := $(shell echo "$(docker_min)" | awk -F. '{printf("%d%03d%03d\n",$$1,$$2,$$3);}' 2>/dev/null) +docker_ver := $(shell docker info 2>/dev/null | grep -i "server version" | cut -d' ' -f3 | awk -F. '{printf("%d%03d%03d\n",$$1,$$2,$$3);}' 2>/dev/null) +docker_is_valid := $(shell if [ $(docker_ver) -lt $(docker_min_ver) ] ; then echo "0"; else echo "1"; fi) +ifeq (0,$(docker_is_valid)) +$(error SONiC requires Docker version $(docker_min) or later) +endif + # Remove lock file in case previous run was forcefully stopped $(shell rm -f .screen) @@ -91,21 +101,20 @@ ifeq ($(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD), y) endif DOCKER_BASE_BUILD = docker build --no-cache \ - -t $(SLAVE_BASE_IMAGE) \ + -t $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) \ --build-arg http_proxy=$(http_proxy) \ --build-arg https_proxy=$(https_proxy) \ - $(SLAVE_DIR) && \ - docker tag $(SLAVE_BASE_IMAGE):latest $(SLAVE_BASE_IMAGE):$(SLAVE_BASE_TAG) + $(SLAVE_DIR) DOCKER_BUILD = docker build --no-cache \ --build-arg user=$(USER) \ --build-arg uid=$(shell id -u) \ --build-arg guid=$(shell id -g) \ --build-arg hostname=$(shell echo $$HOSTNAME) \ - -t $(SLAVE_IMAGE) \ + --build-arg slave_base_tag_ref=$(SLAVE_BASE_TAG) \ + -t $(SLAVE_IMAGE):$(SLAVE_TAG) \ -f $(SLAVE_DIR)/Dockerfile.user \ - $(SLAVE_DIR) && \ - docker tag $(SLAVE_IMAGE):latest $(SLAVE_IMAGE):$(SLAVE_TAG) + $(SLAVE_DIR) SONIC_BUILD_INSTRUCTION := make \ -f slave.mk \ diff --git a/sonic-slave-stretch/Dockerfile.user b/sonic-slave-stretch/Dockerfile.user index 0b44faaf4..1e5b91414 100644 --- a/sonic-slave-stretch/Dockerfile.user +++ b/sonic-slave-stretch/Dockerfile.user @@ -1,4 +1,5 @@ -FROM sonic-slave-stretch-base +ARG slave_base_tag_ref=latest +FROM sonic-slave-stretch-base:${slave_base_tag_ref} # Add user ARG user diff --git a/sonic-slave/Dockerfile.user b/sonic-slave/Dockerfile.user index ff01f88a7..253475b21 100644 --- a/sonic-slave/Dockerfile.user +++ b/sonic-slave/Dockerfile.user @@ -1,4 +1,5 @@ -FROM sonic-slave-base +ARG slave_base_tag_ref=latest +FROM sonic-slave-base:${slave_base_tag_ref} # Add user ARG user