build: revisit caching of images

image caching is now simplified and works based on a single timestamp as the image tag.
This commit is contained in:
Bassam Tabbara committed 2017-06-20 20:57:46 -07:00
1 parent fab106a16c
commit 78c07696b4
17 files changed
+294 -293

No files matched your search

Vendored
+2 -1
View File
@@ -49,6 +49,7 @@ try {
}
stage('Cleanup') {
sh 'make clean'
sh 'make prune PRUNE_KEEP_CACHED=48 PRUNE_KEEP_ORPHANS=48'
deleteDir()
}
@@ -59,7 +60,7 @@ catch (Exception e) {
echo 'Failure encountered'
node("ec2-stateful") {
echo 'Cleaning up workspace'
sh 'make clean'
sh 'make prune PRUNE_KEEP_CACHED=48 PRUNE_KEEP_ORPHANS=48'
deleteDir()
}
+9 -7
View File
@@ -161,6 +161,8 @@ vendor: go.vendor
clean: go.clean
@rm -fr $(WORKDIR) $(RELEASE_DIR) $(BIN_DIR)
@$(MAKE) release.cleanup
@$(MAKE) -C images clean
distclean: go.distclean clean
@rm -fr $(DOWNLOADDIR)
@@ -173,17 +175,18 @@ cross.build.platform.%:
cross.parallel: $(foreach p,$(PLATFORMS), cross.build.platform.$(p))
cross:
build.all:
@$(MAKE) go.init
@$(MAKE) go.validate
@$(MAKE) cross.parallel
release: cross
@$(MAKE) -C images cross
release: build.all
@$(MAKE) -C images build.all
@$(MAKE) release.build
publish:
ifneq ($(filter master alpha beta stable, $(CHANNEL)),)
@$(MAKE) -C images push
@$(MAKE) release.publish
else
@echo skipping publish. invalid channel "$(CHANNEL)"
endif
@@ -199,7 +202,7 @@ prune:
@$(MAKE) -C images prune
.PHONY: build.common cross.build cross.parallel
.PHONY: dev build install test check vet fmt vendor clean distclean cross images release publish promote prune
.PHONY: dev build build.all install test check vet fmt vendor clean distclean release publish promote prune
# ====================================================================================
# Help
@@ -210,13 +213,12 @@ help:
@echo ''
@echo 'Targets:'
@echo ' build Build source code for host platform.'
@echo ' cross Build source code for all platforms.'
@echo ' build.all Build source code for all platforms.'
@echo ' Best done in the cross-build container'
@echo ' due to cross compiler dependencies.'
@echo ' check Runs unit tests.'
@echo ' clean Remove all files that are created '
@echo ' by building.'
@echo ' images Builds container images for host platform.'
@echo ' distclean Remove all files that are created '
@echo ' by building or configuring.'
@echo ' fmt Check formatting of go sources.'
+1 -1
View File
@@ -20,7 +20,7 @@ host=$(hostname)
rootdir=$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd -P)
host_hash=`echo ${host}-${rootdir} | sha256sum | cut -c1-8`
build_registry=build-${host_hash}
container_image=${build_registry}/cross-build
container_image=${build_registry}/cross-build-amd64
container_volume=cross-build-volume
rsync_port=10873
+1 -1
View File
@@ -52,7 +52,7 @@ GITHUB_USER ?= rook
GITHUB_REPO ?= rook
# Optional. Docker registry to publish to
RELEASE_REGISTRY ?= quay.io
RELEASE_REGISTRY ?= quay.io/rook
# Optional. S3 bucket to publish artifacts to
AWS_DEFAULT_REGION ?= us-east-1
+46 -26
View File
@@ -3,7 +3,18 @@
scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source ${scriptdir}/common.sh
registry=${RELEASE_REGISTRY}/
build_registry=${BUILD_REGISTRY}
registry=${RELEASE_REGISTRY}
get_build_image_name() {
local os=$1
local arch=$2
local repo=$3
local image=${repo}-${arch}:latest
echo ${build_registry}/${image}
}
get_image_name() {
local os=$1
@@ -11,12 +22,22 @@ get_image_name() {
local repo=$3
local version=$4
local tag=${repo}-${arch}:${version}
local image=${repo}-${arch}:${version}
if [[ ${arch} == "amd64" ]]; then
tag=${repo}:${version}
image=${repo}:${version}
fi
echo ${tag}
echo ${registry}/${image}
}
build_image() {
local os=$1
local arch=$2
local repo=$3
local build_image=$(get_build_image_name $os $arch $repo)
local image=$(get_image_name $os $arch $repo ${RELEASE_VERSION})
docker tag ${build_image} ${image}
}
build() {
@@ -25,22 +46,22 @@ build() {
[[ ${os} == "linux" ]] || return 0
make -C ${scriptdir}/../../images cross PLATFORMS=${arch} VERSION=${RELEASE_VERSION}
build_image $os $arch rookd
}
publish_artifact() {
publish_image() {
local os=$1
local arch=$2
local repo=$3
local name=${registry}$(get_image_name $os $arch $repo ${RELEASE_VERSION})
local name=$(get_image_name $os $arch $repo ${RELEASE_VERSION})
echo pushing docker container ${name}
docker push ${name}
# we will always tag master builds as latest. i.e. auto-promote master
if [[ "${RELEASE_CHANNEL}" == "master" ]]; then
local dst=${registry}$(get_image_name $os $arch $repo master-latest)
local dst=$(get_image_name $os $arch $repo master-latest)
echo pushing docker container ${dst}
docker tag ${name} ${dst}
docker push ${dst}
@@ -53,22 +74,21 @@ publish() {
[[ ${os} == "linux" ]] || return 0
publish_artifact $os $arch rook/rookd
publish_artifact $os $arch rook/rook
# TODO: publish the toolbox for arm
[[ ${arch} == "amd64" ]] || return 0
publish_artifact $os $arch rook/toolbox
publish_image $os $arch rookd
# disabled for now
# publish_image $os $arch rook
# [[ ${arch} == "amd64" ]] || return 0
# publish_image $os $arch toolbox
}
promote_artifact() {
promote_image() {
local os=$1
local arch=$2
local repo=$3
local src=${registry}$(get_image_name $os $arch $repo ${RELEASE_VERSION})
local dst1=${registry}$(get_image_name $os $arch $repo ${RELEASE_CHANNEL}-latest)
local dst2=${registry}$(get_image_name $os $arch $repo ${RELEASE_CHANNEL}-${RELEASE_VERSION})
local src=$(get_image_name $os $arch $repo ${RELEASE_VERSION})
local dst1=$(get_image_name $os $arch $repo ${RELEASE_CHANNEL}-latest)
local dst2=$(get_image_name $os $arch $repo ${RELEASE_CHANNEL}-${RELEASE_VERSION})
echo promoting container ${src} to ${dst1} and ${dst2}
docker pull ${src}
@@ -84,12 +104,12 @@ promote() {
[[ ${os} == "linux" ]] || return 0
promote_artifact $os $arch rook/rookd
promote_artifact $os $arch rook/rook
promote_artifact $os $arch rook/toolbox
promote_image $os $arch rookd
# promote_image $os $arch rook
# promote_image $os $arch toolbox
}
cleanup_artifact() {
cleanup_image() {
local os=$1
local arch=$2
local repo=$3
@@ -100,7 +120,7 @@ cleanup_artifact() {
${RELEASE_CHANNEL}-latest \
${RELEASE_CHANNEL}-${RELEASE_VERSION} \
; do
img=${registry}$(get_image_name $os $arch $repo ${t})
img=$(get_image_name $os $arch $repo ${t})
if [[ -n "$(docker images -q ${img} 2> /dev/null)" ]]; then
echo removing docker image ${img}
docker rmi ${img} || true
@@ -113,9 +133,9 @@ cleanup() {
local arch=$2
[[ ${os} == "linux" ]] || return 0
cleanup_artifact $os $arch rook/rookd
cleanup_artifact $os $arch rook/rook
cleanup_artifact $os $arch rook/toolbox
cleanup_image $os $arch rookd
# cleanup_image $os $arch rook
# cleanup_image $os $arch toolbox
}
action=$1
+1 -1
View File
@@ -27,7 +27,7 @@ fi
# build the the container if we've not done so already
if [[ -z "$(docker images -q ${container_image})" ]]; then
echo ==== building the cross-build container \(this could take minutes the first time\)
make_cmd="make --no-print-directory -C ${scriptdir}/../images cross-build PULL=0"
make_cmd="make --no-print-directory -C ${scriptdir}/../images cross-build.amd64 PULL=0"
make_output=$($make_cmd 2>&1) || {
cat <<EOF >&2
=== cross build image failed for ${container_image}
+22 -26
View File
@@ -12,40 +12,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build push clean
all: build
include image.mk
PLATFORMS ?= amd64 arm arm64
PLATFORM_IMAGES ?= rookd
HOST_IMAGES ?= cross-build
.PHONY: cross-build
cross-build:
@$(MAKE) -C base GOARCH=amd64
@$(MAKE) -C cross-build-gnu
@$(MAKE) -C cross-build-go
@$(MAKE) -C cross-build
# ====================================================================================
# Image Builds
build.%:
@$(MAKE) -C base build GOARCH=$*
@$(MAKE) -C rookd build GOARCH=$*
base.%:
@$(MAKE) -C base GOARCH=$*
build:
@$(MAKE) -C base GOARCH=amd64
@$(MAKE) -C cross-build-gnu
@$(MAKE) build.$(GOARCH)
cross-build-gnu.%: base.%
@$(MAKE) -C cross-build-gnu GOARCH=$*
push.%:
@$(MAKE) -C rookd push GOARCH=$*
push: $(foreach p,$(PLATFORMS), push.$(p))
cross-build-go.%: cross-build-gnu.%
@$(MAKE) -C cross-build-go GOARCH=$*
clean: clean.build
cross-build.%: cross-build-go.%
@$(MAKE) -C cross-build GOARCH=$*
cross.all: $(foreach p,$(PLATFORMS), build.$(p))
cross:
@$(MAKE) -C base GOARCH=amd64
@$(MAKE) -C cross-build-gnu
@$(MAKE) cross.all
ceph-build.%: cross-build-gnu.$(GOHOSTARCH)
@$(MAKE) -C ceph-build GOARCH=$*
rookd.%: ceph-build.% base.%
@$(MAKE) -C rookd GOARCH=$*
build.all: $(foreach p,$(PLATFORMS), $(foreach i,$(PLATFORM_IMAGES), $(i).$(p))) $(foreach i,$(HOST_IMAGES), $(i).$(GOHOSTARCH))
build.images: $(foreach i,$(PLATFORM_IMAGES) $(HOST_IMAGES), $(i).$(GOHOSTARCH))
# ====================================================================================
# Help
@@ -56,9 +52,9 @@ help:
@echo ''
@echo 'Targets:'
@echo ' build Build images for the host platform.'
@echo ' build.all Build images for all platforms.'
@echo ' clean Remove all images created from the'
@echo ' current build.'
@echo ' cross Build images for all platforms.'
@echo ' prune Prunes orphaned and cached images at the.'
@echo ' host level.'
@echo ' push Pushes public images to registry.'
File renamed without changes.
+18 -28
View File
@@ -12,54 +12,44 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build clean
all: build
include ../image.mk
# ====================================================================================
# Build Options
# the final base image
IMAGE = $(BUILD_REGISTRY)/base-$(GOARCH)
REPO ?= base
IMAGE = $(BUILD_REGISTRY)/$(REPO)-$(GOARCH)
# the full OS image from which we generate a smaller rootfs
ROOTFS_BUILDER_IMAGE := $(BUILD_REGISTRY)/rootfs-builder-$(GOARCH)
# ====================================================================================
# Build rootfs
# the smaller rootfs that will be cached in docker as an image. we use
# the image id of the builder in the image name to chain them, and ensure
# that when the rootfs builder images that this one is invalidated.
ROOTFS_IMAGE := $(BUILD_REGISTRY)/rootfs-$(GOARCH)-$$(docker images -q $(ROOTFS_BUILDER_IMAGE))
ROOTFS_BUILD_IMAGE := $(BUILD_REGISTRY)/rootfs-build-$(GOARCH)
ROOTFS_IMAGE := $(HOST_REGISTRY)/rootfs-$(GOARCH):$$(docker images -q $(ROOTFS_BUILD_IMAGE))
ROOTFS_FILENAME = rootfs.tar
IMAGES = $(IMAGE) $(ROOTFS_BUILDER_IMAGE) $(ROOTFS_IMAGE)
CACHE_IMAGES = $(IMAGES)
TEMP := $(shell mktemp -d)
CLEAN_IMAGES += $(IMAGE) $(ROOTFS_BUILD_IMAGE)
# NOTE: we check if docker build actually built anything (due to changes)
# by comparing the image id before and after calling docker build. If there
# were changes then we proceed with extracting the rootfs and creating the
# final image. This prevents uncessary builds of containers that use this base image.
rootfs-build:
@echo === docker build $(ROOTFS_BUILD_IMAGE)
@cp Dockerfile.rootfs-build $(TEMP)/Dockerfile
@echo === docker build $(ROOTFS_BUILDER_IMAGE)
@cp Dockerfile.rootfs-builder $(TEMP)/Dockerfile
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(OSBASEIMAGE)|g' Dockerfile
@docker build $(BUILD_BASE_ARGS) -t $(ROOTFS_BUILD_IMAGE) $(TEMP)
@[ -n "$$(docker images -q $(ROOTFS_IMAGE))" ] || $(MAKE) rootfs
@docker build $(BUILD_BASE_ARGS) -t $(ROOTFS_BUILDER_IMAGE) $(TEMP)
# lookup the rootfs image from the cache or make it if its not there
@$(MAKE) cache.lookup LOOKUP_IMAGE=$(ROOTFS_IMAGE) MISS_TARGET=rootfs
rootfs:
@echo === docker build $(ROOTFS_IMAGE)
@CID=`docker create $(ROOTFS_BUILD_IMAGE) /bin/bash` &&\
docker export $$CID > $(TEMP)/$(ROOTFS_FILENAME) &&\
@CID=`docker create $(ROOTFS_BUILDER_IMAGE) /bin/bash` &&\
docker export $$CID > $(TEMP)/rootfs.tar &&\
docker rm -f $$CID
@cp Dockerfile.rootfs $(TEMP)/Dockerfile
@docker build $(BUILD_ARGS) -t $(ROOTFS_IMAGE) $(TEMP)
@rm -fr $(TEMP)
build: rootfs-build
build.images: rootfs-build
@echo === docker build $(IMAGE)
@cp Dockerfile $(TEMP)
@cd $(TEMP) && $(SED_CMD) "s|BASEIMAGE|$(ROOTFS_IMAGE)|g" Dockerfile
@docker build $(BUILD_ARGS) -t $(IMAGE) $(TEMP)
@rm -fr $(TEMP)
clean: clean.images
+20 -22
View File
@@ -12,17 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build push
all: build
include ../image.mk
# ====================================================================================
# Options
# the git repo to build from
# the git repo and branch to build from
CEPH_GIT_REPO ?= https://github.com/rook/ceph
CEPH_GIT_BRANCH ?= rook-luminous
# the git commit hash to build
@@ -40,23 +33,29 @@ $(error unsupported memory allocator $(CEPH_ALLOCATOR))
endif
CEPH_CONFIG ?= $(GOARCH)-$(CEPH_ALLOCATOR)-$(CEPH_BUILD_TYPE)
BASEIMAGE := $(BUILD_REGISTRY)/cross-build-gnu
CEPH_BUILD_IMAGE := $(BUILD_REGISTRY)/ceph-build-$(CEPH_CONFIG)
CEPH_IMAGE := $(HOST_REGISTRY)/ceph-$(CEPH_CONFIG):$$(docker images -q $(CEPH_BUILD_IMAGE))
CLEAN_IMAGES = $(CEPH_BUILD_IMAGE)
CEPH_TARBALL = ceph-install.tar
TEMP := $(shell mktemp -d)
CCACHE_DIR_HOST ?= $(HOME)/.ccache
CEPH_BUILDER_IMAGE := $(BUILD_REGISTRY)/ceph-builder-$(CEPH_CONFIG)
CEPH_BUILDER_BASEIMAGE := $(BUILD_REGISTRY)/cross-build-gnu-$(GOHOSTARCH)
CEPH_IMAGE := $(BUILD_REGISTRY)/ceph-$(CEPH_CONFIG)-$$(docker images -q $(CEPH_BUILDER_IMAGE))
IMAGES = $(CEPH_BUILDER_IMAGE) $(CEPH_IMAGE)
CACHE_IMAGES = $(IMAGES)
TEMP := $(shell mktemp -d)
# ====================================================================================
# Targets
build:
@echo === docker build $(CEPH_BUILD_IMAGE)
build.images:
@echo === docker build $(CEPH_BUILDER_IMAGE)
@cp -a . $(TEMP)
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(CEPH_BUILDER_BASEIMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) \
--build-arg ARCH=$(DEBIAN_ARCH) \
--build-arg CEPH_GIT_COMMIT=$(CEPH_GIT_COMMIT) \
@@ -65,17 +64,18 @@ build:
--build-arg CEPH_ALLOCATOR=$(CEPH_ALLOCATOR) \
--build-arg CEPH_BUILD_TYPE=$(CEPH_BUILD_TYPE) \
--build-arg CROSS_TRIPLE=$(CROSS_TRIPLE) \
-t $(CEPH_BUILD_IMAGE) \
-t $(CEPH_BUILDER_IMAGE) \
$(TEMP)
@[ -n "$$(docker images -q $(CEPH_IMAGE))" ] || $(MAKE) ceph
# lookup the rootfs image from the cache or make it if its not there
@$(MAKE) cache.lookup LOOKUP_IMAGE=$(CEPH_IMAGE) MISS_TARGET=ceph
ceph:
@echo === building ceph from $(CEPH_BUILD_IMAGE)
@echo === building ceph from $(CEPH_BUILDER_IMAGE)
@docker run \
-i $(RUN_ARGS) \
--cidfile $(TEMP)/cid \
-v $(CCACHE_DIR_HOST):/root/.ccache \
$(CEPH_BUILD_IMAGE)
$(CEPH_BUILDER_IMAGE)
@docker cp `cat $(TEMP)/cid`:/build/$(CEPH_TARBALL) $(TEMP)/$(CEPH_TARBALL)
@docker rm -f `cat $(TEMP)/cid`
@docker import $(TEMP)/$(CEPH_TARBALL) $(CEPH_IMAGE)
@@ -85,5 +85,3 @@ ceph:
@CID=`docker create $(CEPH_IMAGE) /dev/null` &&\
docker export $$CID > $@ &&\
docker rm -f $$CID
clean: clean.images
+4 -16
View File
@@ -12,31 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build clean
all: build
# cross-build only supported on amd64
override GOARCH := amd64
include ../image.mk
# ====================================================================================
# Build Options
IMAGE = $(BUILD_REGISTRY)/cross-build-gnu-$(GOARCH)
IMAGES := $(IMAGE)
CACHE_IMAGES = $(IMAGES)
REPO ?= cross-build-gnu
IMAGE = $(BUILD_REGISTRY)/$(REPO)
BASEIMAGE = $(BUILD_REGISTRY)/base-$(GOARCH)
# ====================================================================================
# Build image
TEMP := $(shell mktemp -d)
CLEAN_IMAGES := $(IMAGE)
build:
build.images:
@echo === docker build $(IMAGE)
@cp -a . $(TEMP)
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) -t $(IMAGE) $(TEMP)
@rm -fr $(TEMP)
clean: clean.images
+5 -17
View File
@@ -12,31 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build clean
all: build
# cross-build only supported on amd64
override GOARCH := amd64
include ../image.mk
# ====================================================================================
# Build Options
IMAGE = $(BUILD_REGISTRY)/cross-build-go-$(GOARCH)
IMAGES := $(IMAGE)
CACHE_IMAGES = $(IMAGES)
REPO ?= cross-build-go
IMAGE = $(BUILD_REGISTRY)/$(REPO)
BASEIMAGE = $(BUILD_REGISTRY)/cross-build-gnu
# ====================================================================================
# Build image
BASEIMAGE = $(BUILD_REGISTRY)/cross-build-gnu-$(GOARCH)
TEMP := $(shell mktemp -d)
CLEAN_IMAGES := $(IMAGE)
build:
build.images:
@echo === docker build $(IMAGE)
@cp -a . $(TEMP)
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) -t $(IMAGE) $(TEMP)
@rm -fr $(TEMP)
clean: clean.images
+5 -17
View File
@@ -12,31 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build clean
all: build
# cross-build only supported on amd64
override GOARCH := amd64
include ../image.mk
# ====================================================================================
# Build Options
IMAGE = $(BUILD_REGISTRY)/cross-build-$(GOARCH)
IMAGES := $(IMAGE)
CACHE_IMAGES = $(IMAGES)
REPO ?= cross-build
IMAGE = $(BUILD_REGISTRY)/$(REPO)
BASEIMAGE = $(BUILD_REGISTRY)/cross-build-go
# ====================================================================================
# Build image
BASEIMAGE = $(BUILD_REGISTRY)/cross-build-go-$(GOARCH)
TEMP := $(shell mktemp -d)
CLEAN_IMAGES := $(IMAGE)
build:
build.images:
@echo === docker build $(IMAGE)
@cp -a . $(TEMP)
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) -t $(IMAGE) $(TEMP)
@rm -fr $(TEMP)
clean: clean.images
+90 -62
View File
@@ -16,12 +16,11 @@ SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(SELF_DIR)/../build/makelib/cross.mk
# a registry that is scoped to the local host
HOSTNAME := $(shell hostname)
HOST_REGISTRY := host-$(shell echo $(HOSTNAME) | sha256sum | cut -c1-8)
CACHE_REGISTRY := cache
# a registry that is scoped to the current build tree on this host
ifeq ($(origin BUILD_REGISTRY), undefined)
HOSTNAME := $(shell hostname)
ROOTDIR := $(shell cd $(SELF_DIR)/.. && pwd -P)
BUILD_REGISTRY := build-$(shell echo $(HOSTNAME)-$(ROOTDIR) | sha256sum | cut -c1-8)
endif
@@ -84,81 +83,110 @@ export PULL
BUILD_BASE_ARGS += $(BUILD_ARGS)
# =====================================================================================
# Targets
#
.PHONY: all build publish clean
all: build
build: build.images
@$(MAKE) cache.images
push: push.images
clean: clean.build
prune: cache.prune
clean.images:
@for i in $(IMAGES); do \
if [ -n "$$(docker images -q $$i)" ]; then \
for c in $$(docker ps -a -q --no-trunc --filter=ancestor=$$i); do \
if [ "$$c" != "$(SELF_CID)" ]; then \
echo stopping and removing container $${c} referencing image $$i; \
docker stop $${c}; \
docker rm $${c}; \
fi; \
done; \
echo cleaning image $$i; \
docker rmi $$i > /dev/null 2>&1 || true; \
fi; \
done
# this will clean everything for this build
clean.build:
@echo === cleaning images for $(BUILD_REGISTRY)
@$(MAKE) clean.images IMAGES="$(shell docker images | grep -E '^$(BUILD_REGISTRY)/' | awk '{print $$1":"$$2}')"
# =====================================================================================
# Caching
#
# NOTE: in order to reduce built time especially on jenkins, we maintain a cache
# of already built images. This cache contains images that can be used to help speed
# future docker build commands using docker's content addressable schemes. And also
# to avoid running builds like ceph when the contents have not changed.
# All cached images go in in a 'cache/' local registry and we follow an MRU caching
# policy -- keeping images that have been referenced around and evicting images
# that have to been referenced in a while (and according to a policy). Note we can
# not rely on the image's .CreatedAt date since docker only updates then when the
# image is created and not referenced. Instead we keep a date in the Tag.
# prune images that are at least this many hours old
PRUNE_HOURS ?= 48
# prune keeps at least this many images regardless of how old they are
PRUNE_KEEP_CACHED ?= 24
PRUNE_KEEP_ORPHANS ?= 24
PRUNE_KEEP ?= 24
CLEANUP_DATE := $(shell date -u --date="$(PRUNE_HOURS) hours ago" +"%Y-%m-%d %T %z UTC")
PRUNE_DRYRUN ?= 0
# NOTE: docker rmi removes the last image when untagging. instead we switch the tag
# to a small dummy orphaning the original image and then call docker rmi. This approach
# avoids removing the last layer (and having to rebuild it)
CACHE_DATE_FORMAT := "%Y-%m-%d.%H%M%S.%N"
CACHE_PRUNE_DATE := $(shell date -u --date="$(PRUNE_HOURS) hours ago" +"$(CACHE_DATE_FORMAT)")
CACHE_TAG := $(shell date -u +"$(CACHE_DATE_FORMAT)")
DUMMY_IMAGE_BASE ?= tianon/true
DUMMY_IMAGE ?= $(HOST_REGISTRY)/dummy:latest
cache.lookup:
@IMAGE_NAME=$${LOOKUP_IMAGE#*/} ;\
if [ -n "$$(docker images -q $(LOOKUP_IMAGE))" ]; then exit 0; fi; \
if [ -z "$$(docker images -q $(CACHE_REGISTRY)/$${IMAGE_NAME})" ]; then \
$(MAKE) $(MISS_TARGET); \
else \
docker tag $$(docker images -q $(CACHE_REGISTRY)/$${IMAGE_NAME}) $(LOOKUP_IMAGE); \
fi;
clean.init:
@if [ -z "`docker images -q $(DUMMY_IMAGE)`" ]; then \
docker pull $(DUMMY_IMAGE_BASE) > /dev/null 2>&1; \
docker tag $(DUMMY_IMAGE_BASE) $(DUMMY_IMAGE) > /dev/null 2>&1; \
docker rmi $(DUMMY_IMAGE_BASE) > /dev/null 2>&1; \
fi
do.orphan: clean.init
@for i in $(CLEAN_IMAGES); do \
[ "$$i" != "$(DUMMY_IMAGE)" ] || continue; \
for c in $$(docker ps -a -q --no-trunc --filter=ancestor=$$i); do \
if [ "$$c" != "$(SELF_CID)" ]; then \
echo stopping and removing container $${c} referencing image $$i; \
docker stop $${c}; \
docker rm $${c}; \
fi; \
done; \
echo orphaning image $$i; \
docker tag $(DUMMY_IMAGE) $$i > /dev/null 2>&1; \
docker rmi $$i > /dev/null 2>&1; \
cache.images:
@for i in $(CACHE_IMAGES); do \
IMGID=$$(docker images -q $$i); \
if [ -n "$$IMGID" ]; then \
echo === caching image $$i; \
CACHE_IMAGE=$(CACHE_REGISTRY)/$${i#*/}; \
docker tag $$i $${CACHE_IMAGE}:$(CACHE_TAG); \
for r in $$(docker images --format "{{.ID}}#{{.Repository}}:{{.Tag}}" | grep $$IMGID | grep $(CACHE_REGISTRY)/ | grep -v $${CACHE_IMAGE}:$(CACHE_TAG)); do \
docker rmi $${r#*#}; \
done; \
fi; \
done
# this will clean all images in the variable CLEAN_IMAGES
clean.images: do.clean
# this will clean everything for this build
clean.build: clean.init
@$(MAKE) do.orphan CLEAN_IMAGES="$(shell docker images | grep -E '^$(BUILD_REGISTRY)|$(REGISTRY)/' | awk '{print $$1":"$$2}')"
# this will clean everything for this host regardless of prune policy
clean.all: clean.init
@$(MAKE) do.orphan CLEAN_IMAGES="$(shell docker images | grep -E '^$(BUILD_REGISTRY)|$(HOST_REGISTRY)|$(REGISTRY)/' | awk '{print $$1":"$$2}')"
# prune removes old orphaned images and old cached images
prune: clean.build
# prune removes old cached images
cache.prune:
@echo === pruning images older than $(PRUNE_HOURS) hours
@echo === keeping a minimum of $(PRUNE_KEEP_ORPHANS) orphaned images and $(PRUNE_KEEP_CACHED) cached images
@CLEAN_IMAGES="$(shell docker images --format "{{.CreatedAt}}#{{.Repository}}:{{.Tag}}" \
| grep -E '$(HOST_REGISTRY)/' \
| grep -v '$(DUMMY_IMAGE)' \
@echo === keeping a minimum of $(PRUNE_KEEP) images
@EXPIRED=$$(docker images --format "{{.Tag}}#{{.Repository}}:{{.Tag}}" \
| grep -E '$(CACHE_REGISTRY)/' \
| sort -r \
| awk -v i=0 -v cd="$(CLEANUP_DATE)" -F "#" '{if ($$1 <= cd && i >= $(PRUNE_KEEP_CACHED)) print $$2; i++ }')" &&\
$(MAKE) do.orphan CLEAN_IMAGES="$${CLEAN_IMAGES}"
@CLEAN_IMAGES="$(shell docker images -q -f dangling=true --format "{{.CreatedAt}}#{{.ID}}" \
| sort -r \
| awk -v i=0 -v cd="$(CLEANUP_DATE)" -F "#" '{if ($$1 <= cd && i >= $(PRUNE_KEEP_ORPHANS)) print $$2; i++ }')" &&\
for i in $${CLEAN_IMAGES}; do \
echo removing orphaned image $$i; \
docker rmi $$i > /dev/null 2>&1; \
done
prune.all:
| awk -v i=0 -v cd="$(CACHE_PRUNE_DATE)" -F "#" '{if ($$1 <= cd && i >= $(PRUNE_KEEP)) print $$2; i++ }') &&\
for i in $$EXPIRED; do \
echo removing expired cache image $$i; \
[ $(PRUNE_DRYRUN) = 1 ] || docker rmi $$i; \
done
@for i in $$(docker images -q -f dangling=true); do \
echo removing orphaned image $$i; \
echo removing danlging image $$i; \
docker rmi $$i > /dev/null 2>&1; \
done
# nukes all images
nuke:
# =====================================================================================
# Debugging nukes all images
#
debug.nuke:
@for c in $$(docker ps -a -q --no-trunc); do \
if [ "$$c" != "$(SELF_CID)" ]; then \
echo stopping and removing container $${c}; \
-31
View File
@@ -14,37 +14,6 @@
FROM BASEIMAGE
ARG EXTRALIBS
# install runtime dependencies for ceph and rookd
RUN BOOST_VERSION=1.62.0 && \
DEBIAN_FRONTEND=noninteractive apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -yy -q --no-install-recommends \
ca-certificates \
libaio1 \
libboost-context${BOOST_VERSION} \
libboost-coroutine${BOOST_VERSION} \
libboost-date-time${BOOST_VERSION} \
libboost-iostreams${BOOST_VERSION} \
libboost-program-options${BOOST_VERSION} \
libboost-python${BOOST_VERSION} \
libboost-random${BOOST_VERSION} \
libboost-regex${BOOST_VERSION} \
libboost-system${BOOST_VERSION} \
libboost-thread${BOOST_VERSION} \
libcurl3-gnutls \
libexpat1 \
libibverbs1 \
libldap-2.4-2 \
libnss3 \
libpython2.7 \
python-prettytable \
python2.7-minimal \
${EXTRALIBS} && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt-get autoremove -y && \
DEBIAN_FRONTEND=noninteractive apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# add the ceph binaries
ADD ceph-install.tar /
+46
View File
@@ -0,0 +1,46 @@
# Copyright 2016 The Rook Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM BASEIMAGE
ARG EXTRALIBS
# install runtime dependencies for ceph and rookd
RUN BOOST_VERSION=1.62.0 && \
DEBIAN_FRONTEND=noninteractive apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -yy -q --no-install-recommends \
ca-certificates \
libaio1 \
libboost-context${BOOST_VERSION} \
libboost-coroutine${BOOST_VERSION} \
libboost-date-time${BOOST_VERSION} \
libboost-iostreams${BOOST_VERSION} \
libboost-program-options${BOOST_VERSION} \
libboost-python${BOOST_VERSION} \
libboost-random${BOOST_VERSION} \
libboost-regex${BOOST_VERSION} \
libboost-system${BOOST_VERSION} \
libboost-thread${BOOST_VERSION} \
libcurl3-gnutls \
libexpat1 \
libibverbs1 \
libldap-2.4-2 \
libnss3 \
libpython2.7 \
python-prettytable \
python2.7-minimal \
${EXTRALIBS} && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \
DEBIAN_FRONTEND=noninteractive apt-get autoremove -y && \
DEBIAN_FRONTEND=noninteractive apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+24 -37
View File
@@ -12,26 +12,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: all build push
all: build
include ../image.mk
# ====================================================================================
# Image Build Options
REPO ?= rookd
IMAGE = $(REGISTRY)/$(REPO)-$(GOARCH):$(VERSION)
CLEAN_IMAGES = $(IMAGE)
# ====================================================================================
# Ceph Build Options
CEPH_BUILD_TYPE ?= release
CEPH_ALLOCATOR ?= tcmalloc
# ====================================================================================
# Common Build Settings
ROOKD_IMAGE = $(BUILD_REGISTRY)/rookd-$(GOARCH)
ROOKD_BASE_IMAGE = $(BUILD_REGISTRY)/rookd-base-$(GOARCH)
IMAGES = $(ROOKD_IMAGE) $(ROOKD_BASE_IMAGE)
CACHE_IMAGES = $(ROOKD_BASE_IMAGE)
BASEIMAGE = $(BUILD_REGISTRY)/base-$(GOARCH)
@@ -40,6 +29,9 @@ TEMP := $(shell mktemp -d)
# ====================================================================================
# Build Ceph
CEPH_BUILD_TYPE ?= release
CEPH_ALLOCATOR ?= tcmalloc
ifeq ($(CEPH_ALLOCATOR),tcmalloc)
EXTRA_LIBS += libgoogle-perftools4
endif
@@ -54,32 +46,27 @@ CEPH_TARBALL_FILENAME = ceph-install.tar
CEPH_TARBALL = $(TEMP)/$(CEPH_TARBALL_FILENAME)
$(CEPH_TARBALL):
@echo === building ceph for $(IMAGE)
@echo === building ceph for $(ROOKD_IMAGE)
@$(MAKE) -C ../ceph-build GOARCH=$(GOARCH) CEPH_ALLOCATOR=$(CEPH_ALLOCATOR) CEPH_BUILD_TYPE=$(CEPH_BUILD_TYPE) $(CEPH_TARBALL)
# ====================================================================================
# Build Rook
ROOKD = $(TEMP)/rookd
$(ROOKD):
@echo === building rookd for $(IMAGE)
@cp ../../bin/linux_$(GOARCH)/rookd $@
# ====================================================================================
# Build Final Image
EXISTING_IMAGE_ID := $(shell docker images -q $(IMAGE))
build: $(CEPH_TARBALL) $(ROOKD)
@echo === docker build $(IMAGE)
@cp Dockerfile $(TEMP)
rookd-base-image:
@echo === docker build $(ROOKD_BASE_IMAGE)
@cp Dockerfile.base $(TEMP)/Dockerfile
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) --build-arg EXTRALIBS=$(EXTRA_LIBS) -t $(IMAGE) $(TEMP)
@docker rmi $(EXISTING_IMAGE_ID) > /dev/null 2>&1 || true
@docker build $(BUILD_ARGS) --build-arg EXTRALIBS=$(EXTRA_LIBS) -t $(ROOKD_BASE_IMAGE) $(TEMP)
# since this is a leaf image avoid leaving around a lot of dangling images
# by removing the last build of the final rookd image
OLD_IMAGE_ID := $(shell docker images -q $(ROOKD_IMAGE))
build.images: rookd-base-image $(CEPH_TARBALL)
@echo === docker build $(ROOKD_IMAGE)
@cp Dockerfile $(TEMP)
@cp ../../bin/linux_$(GOARCH)/rookd $(TEMP)
@cd $(TEMP) && $(SED_CMD) 's|BASEIMAGE|$(ROOKD_BASE_IMAGE)|g' Dockerfile
@docker build $(BUILD_ARGS) -t $(ROOKD_IMAGE) $(TEMP)
@[ -z "$(OLD_IMAGE_ID)" ] || docker rmi $(OLD_IMAGE_ID)
@rm -fr $(TEMP)
push:
@docker push $(IMAGE)
clean: clean.images