@@ -7,6 +7,22 @@ SHELL:=bash
77OWNER? =jupyter
88
99# Need to list the images in build dependency order
10+
11+ # Images supporting the following architectures:
12+ # - linux/amd64
13+ # - linux/arm64
14+ MULTI_IMAGES: = \
15+ base-notebook \
16+ minimal-notebook
17+ # Images that can only be built on the amd64 architecture (aka. x86_64)
18+ AMD64_ONLY_IMAGES: = \
19+ r-notebook \
20+ scipy-notebook \
21+ tensorflow-notebook \
22+ datascience-notebook \
23+ pyspark-notebook \
24+ all-spark-notebook
25+ # All of the images
1026ALL_IMAGES: = \
1127 base-notebook \
1228 minimal-notebook \
@@ -26,7 +42,7 @@ export DOCKER_BUILDKIT:=1
2642help :
2743 @echo " jupyter/docker-stacks"
2844 @echo " ====================="
29- @echo " Replace % with a stack directory name (e.g., make build/minimal-notebook)"
45+ @echo " Replace % with a stack directory name (e.g., make build-multi /minimal-notebook)"
3046 @echo
3147 @grep -E ' ^[a-zA-Z0-9_%/-]+:.*?## .*$$' $(MAKEFILE_LIST ) | sort | awk ' BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
3248
@@ -40,7 +56,59 @@ build/%: ## build the latest image for a stack using the system's architecture
4056 @docker images $(OWNER ) /$(notdir $@ ) :latest --format " {{.Size}}"
4157 @echo " ::endgroup::"
4258build-all : $(foreach I, $(ALL_IMAGES ) , build/$(I ) ) # # build all stacks
43- build-test-all : $(foreach I, $(ALL_IMAGES ) , build/$(I ) test/$(I ) ) # # build and test all stacks
59+
60+ # Limitations on docker buildx build (using docker/buildx 0.5.1):
61+ #
62+ # 1. Can't --load and --push at the same time
63+ #
64+ # 2. Can't --load multiple platforms
65+ #
66+ # What does it mean to --load?
67+ #
68+ # - It means that the built image can be referenced by `docker` CLI, for example
69+ # when using the `docker tag` or `docker push` commands.
70+ #
71+ # Workarounds due to limitations:
72+ #
73+ # 1. We always build a dedicated image using the current system architecture
74+ # named as OWNER/<stack>-notebook so we always can reference that image no
75+ # matter what during tests etc.
76+ #
77+ # 2. We always also build a multi-platform image during build-multi that will be
78+ # inaccessible with `docker tag` and `docker push` etc, but this will help us
79+ # test the build on the different platform and provide cached layers for
80+ # later.
81+ #
82+ # 3. We let push-multi refer to rebuilding a multi image with `--push`.
83+ #
84+ # We can rely on the cached layer from build-multi now even though we never
85+ # tagged the multi image.
86+ #
87+ # Outcomes of the workaround:
88+ #
89+ # 1. We can keep using the previously defined Makefile commands that doesn't
90+ # include `-multi` suffix as before.
91+ #
92+ # 2. Assuming we have setup docker/dockerx properly to build in arm64
93+ # architectures as well, then we can build and publish such images via the
94+ # `-multi` suffix without needing a local registry.
95+ #
96+ # 3. If we get dedicated arm64 runners, we can test everything separately
97+ # without needing to update this Makefile, and if all tests succeeds we can
98+ # do a publish job that creates a multi-platform image for us.
99+ #
100+ build-multi/% : DARGS?=
101+ build-multi/% : # # build the latest image for a stack on both amd64 and arm64
102+ @echo " ::group::Build $( OWNER) /$( notdir $@ ) (system's architecture)"
103+ docker buildx build $(DARGS ) --rm --force-rm -t $(OWNER ) /$(notdir $@ ) :latest ./$(notdir $@ ) --build-arg OWNER=$(OWNER )
104+ @echo -n " Built image size: "
105+ @docker images $(OWNER ) /$(notdir $@ ) :latest --format " {{.Size}}"
106+ @echo " ::endgroup::"
107+
108+ @echo "::group::Build $(OWNER)/$(notdir $@) (amd64,arm64)"
109+ docker buildx build $(DARGS) --rm --force-rm -t build-multi-tmp-cache/$(notdir $@):latest ./$(notdir $@) --build-arg OWNER=$(OWNER) --platform "linux/amd64,linux/arm64"
110+ @echo "::endgroup::"
111+ build-all-multi : $(foreach I, $(MULTI_IMAGES ) , build-multi/$(I ) ) $(foreach I, $(AMD64_ONLY_IMAGES ) , build/$(I ) ) # # build all stacks
44112
45113
46114
@@ -117,6 +185,13 @@ push/%: ## push all tags for a jupyter image
117185 @echo " ::endgroup::"
118186push-all : $(foreach I, $(ALL_IMAGES ) , push/$(I ) ) # # push all tagged images
119187
188+ push-multi/% : DARGS?=
189+ push-multi/% : # # push all tags for a jupyter image that support multiple architectures
190+ @echo " ::group::Push $( OWNER) /$( notdir $@ ) (amd64,arm64)"
191+ docker buildx build $(DARGS ) --rm --force-rm $($(subst -,_,$(notdir $@ ) ) _EXTRA_TAG_ARGS) -t $(OWNER ) /$(notdir $@ ) :latest ./$(notdir $@ ) --build-arg OWNER=$(OWNER ) --platform " linux/amd64,linux/arm64"
192+ @echo " ::endgroup::"
193+ push-all-multi : $(foreach I, $(MULTI_IMAGES ) , push-multi/$(I ) ) $(foreach I, $(AMD64_ONLY_IMAGES ) , push/$(I ) ) # # push all tagged images
194+
120195
121196
122197run/% : DARGS?=
@@ -134,5 +209,4 @@ test/%: ## run tests against a stack (only common tests or common tests + specif
134209 @if [ ! -d " $( notdir $@ ) /test" ]; then TEST_IMAGE=" $( OWNER) /$( notdir $@ ) " pytest -m " not info" test ; \
135210 else TEST_IMAGE=" $( OWNER) /$( notdir $@ ) " pytest -m " not info" test $(notdir $@ ) /test; fi
136211 @echo " ::endgroup::"
137-
138212test-all : $(foreach I, $(ALL_IMAGES ) , test/$(I ) ) # # test all stacks
0 commit comments