Просмотр исходного кода

Makefile,Dockerfile: add multi-arch images

This commit changes the build-system for Kilo to create container images
for multiple architectures. This will enable running Kilo on Arm
devices, e.g. Raspberry Pis. This is accomplished using Docker
manifests.
Lucas Servén Marín 7 лет назад
Родитель
Сommit
adb09ce620
5 измененных файлов с 112 добавлено и 40 удалено
  1. 1 0
      .gitignore
  2. 6 2
      .travis.yml
  3. 5 3
      Dockerfile
  4. 86 21
      Makefile
  5. 14 14
      vendor/modules.txt

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 .cache/
 .container*
+.manifest*
 .push*
 bin/

+ 6 - 2
.travis.yml

@@ -1,5 +1,7 @@
 sudo: required
 
+dist: xenial
+
 language: go
 
 services:
@@ -9,7 +11,7 @@ go:
   - 1.12.1
 
 env:
-  - GO111MODULE=on
+  - GO111MODULE=on DOCKER_CLI_EXPERIMENTAL=enabled
 
 install: true
 
@@ -18,10 +20,12 @@ before_install:
 
 script:
   - make
+  - make vendor
   - make unit
   - make lint
   - make container
 
 after_success:
   - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
-  - make push && make push-latest
+  - docker run --rm --privileged multiarch/qemu-user-static:register
+  - make manifest && make manifest-latest

+ 5 - 3
Dockerfile

@@ -1,12 +1,14 @@
+ARG FROM=alpine
 FROM alpine AS cni
 RUN apk add --no-cache curl && \
     curl -Lo cni.tar.gz https://github.com/containernetworking/plugins/releases/download/v0.7.5/cni-plugins-amd64-v0.7.5.tgz && \
     tar -xf cni.tar.gz
 
-FROM alpine
-MAINTAINER squat <lserven@gmail.com>
+FROM $FROM
+LABEL maintainer="squat <lserven@gmail.com>"
 RUN echo "@testing http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
     apk add --no-cache ipset iptables wireguard-tools@testing
 COPY --from=cni bridge host-local loopback portmap /opt/cni/bin/
-COPY bin/kg /opt/bin/
+ARG GOARCH
+COPY bin/$GOARCH/kg /opt/bin/
 ENTRYPOINT ["/opt/bin/kg"]

+ 86 - 21
Makefile

@@ -1,7 +1,11 @@
 export GO111MODULE=on
-.PHONY: all push container clean container-name container-latest push-latest fmt lint test unit vendor header generate client deepcopy informer lister openapi
+.PHONY: push container clean container-name container-latest push-latest fmt lint test unit vendor header generate client deepcopy informer lister openapi manifest manfest-latest manifest-annotate manifest manfest-latest manifest-annotate
 
-BINS := $(addprefix bin/,kg kgctl)
+ARCH ?= amd64
+ALL_ARCH := amd64 arm arm64
+DOCKER_ARCH := "" arm "arm64 armv8"
+IMAGE_ARCH := amd64 armhf arm64
+BINS := $(addprefix bin/$(ARCH)/,kg kgctl)
 PROJECT := kilo
 PKG := github.com/squat/$(PROJECT)
 REGISTRY ?= index.docker.io
@@ -33,10 +37,33 @@ OPENAPI_GEN_BINARY:=$(GOPATH)/bin/openapi-gen
 
 BUILD_IMAGE ?= golang:1.12.1-alpine
 
-all: build
-
 build: $(BINS)
 
+build-%:
+	@$(MAKE) --no-print-directory ARCH=$* build
+
+container-latest-%:
+	@$(MAKE) --no-print-directory ARCH=$* container-latest
+
+container-%:
+	@$(MAKE) --no-print-directory ARCH=$* container
+
+push-latest-%:
+	@$(MAKE) --no-print-directory ARCH=$* push-latest
+
+push-%:
+	@$(MAKE) --no-print-directory ARCH=$* push
+
+all-build: $(addprefix build-, $(ALL_ARCH))
+
+all-container: $(addprefix container-, $(ALL_ARCH))
+
+all-push: $(addprefix push-, $(ALL_ARCH))
+
+all-container-latest: $(addprefix container-latest-, $(ALL_ARCH))
+
+all-push-latest: $(addprefix push-latest-, $(ALL_ARCH))
+
 generate: client deepcopy informer lister openapi
 
 client: pkg/k8s/clientset/versioned/typed/kilo/v1alpha1/peer.go
@@ -107,7 +134,7 @@ pkg/k8s/apis/kilo/v1alpha1/openapi_generated.go: pkg/k8s/apis/kilo/v1alpha1/type
 	go fmt $@
 
 $(BINS): $(SRC) go.mod
-	@mkdir -p bin
+	@mkdir -p bin/$(ARCH)
 	@echo "building: $@"
 	@docker run --rm \
 	    -u $$(id -u):$$(id -g) \
@@ -115,6 +142,7 @@ $(BINS): $(SRC) go.mod
 	    -w /$(PROJECT) \
 	    $(BUILD_IMAGE) \
 	    /bin/sh -c " \
+	        GOARCH=$(ARCH) \
 	        GOOS=linux \
 	        GOCACHE=/$(PROJECT)/.cache \
 		CGO_ENABLED=0 \
@@ -174,29 +202,66 @@ header: .header
 		exit 1; \
 	fi
 
-container: .container-$(VERSION) container-name
-.container-$(VERSION): $(BINS) Dockerfile
-	@docker build -t $(IMAGE):$(VERSION) .
-	@docker images -q $(IMAGE):$(VERSION) > $@
+container: .container-$(ARCH)-$(VERSION) container-name
+.container-$(ARCH)-$(VERSION): $(BINS) Dockerfile
+	@i=0; for a in $(ALL_ARCH); do [ "$$a" = $(ARCH) ] && break; i=$$((i+1)); done; \
+	ia=""; \
+	j=0; for a in $(IMAGE_ARCH); do [ "$$i" -eq "$$j" ] && ia="$$a" && break; j=$$((j+1)); done; \
+	docker build -t $(IMAGE):$(ARCH)-$(VERSION) --build-arg FROM=multiarch/alpine:$$ia-v3.9 --build-arg GOARCH=$(ARCH) .
+	@docker images -q $(IMAGE):$(ARCH)-$(VERSION) > $@
 
-container-latest: .container-$(VERSION)
-	@docker tag $(IMAGE):$(VERSION) $(IMAGE):latest
-	@echo "container: $(IMAGE):latest"
+container-latest: .container-$(ARCH)-$(VERSION)
+	@docker tag $(IMAGE):$(ARCH)-$(VERSION) $(IMAGE):$(ARCH)-latest
+	@echo "container: $(IMAGE):$(ARCH)-latest"
 
 container-name:
-	@echo "container: $(IMAGE):$(VERSION)"
-
-push: .push-$(VERSION) push-name
-.push-$(VERSION): .container-$(VERSION)
-	@docker push $(REGISTRY)/$(IMAGE):$(VERSION)
-	@docker images -q $(IMAGE):$(VERSION) > $@
+	@echo "container: $(IMAGE):$(ARCH)-$(VERSION)"
+
+manifest: .manifest-$(VERSION) manifest-name
+.manifest-$(VERSION): Dockerfile $(addprefix push-, $(ALL_ARCH))
+	@docker manifest create --amend $(IMAGE):$(VERSION) $(addsuffix -$(VERSION), $(addprefix squat/$(PROJECT):, $(ALL_ARCH)))
+	@$(MAKE) --no-print-directory manifest-annotate
+	@docker manifest push $(IMAGE):$(VERSION) > $@
+
+manifest-latest: .manifest-$(VERSION) $(addprefix push-latest-, $(ALL_ARCH))
+	@docker manifest create --amend $(IMAGE):latest $(addsuffix -latest, $(addprefix squat/$(PROJECT):, $(ALL_ARCH)))
+	@$(MAKE) --no-print-directory manifest-annotate
+	@docker manifest push $(IMAGE):latest
+	@echo "manifest: $(IMAGE):latest"
+
+manifest-annotate:
+	@i=0; \
+	for a in $(ALL_ARCH); do \
+	    annotate=; \
+	    j=0; for da in $(DOCKER_ARCH); do \
+		if [ "$$j" -eq "$$i" ] && [ -n "$$da" ]; then \
+		    annotate="docker manifest annotate $(IMAGE):$(VERSION) $(IMAGE):$$a-$(VERSION) --os linux --arch"; \
+		    k=0; for ea in $$da; do \
+			[ "$$k" = 0 ] && annotate="$$annotate $$ea"; \
+			[ "$$k" != 0 ] && annotate="$$annotate --variant $$ea"; \
+			k=$$((k+1)); \
+		    done; \
+		    $$annotate; \
+		fi; \
+		j=$$((j+1)); \
+	    done; \
+	    i=$$((i+1)); \
+	done
+
+manifest-name:
+	@echo "manifest: $(IMAGE_ROOT):$(VERSION)"
+
+push: .push-$(ARCH)-$(VERSION) push-name
+.push-$(ARCH)-$(VERSION): .container-$(ARCH)-$(VERSION)
+	@docker push $(REGISTRY)/$(IMAGE):$(ARCH)-$(VERSION)
+	@docker images -q $(IMAGE):$(ARCH)-$(VERSION) > $@
 
 push-latest: container-latest
-	@docker push $(REGISTRY)/$(IMAGE):latest
-	@echo "pushed: $(IMAGE):latest"
+	@docker push $(REGISTRY)/$(IMAGE):$(ARCH)-latest
+	@echo "pushed: $(IMAGE):$(ARCH)-latest"
 
 push-name:
-	@echo "pushed: $(IMAGE):$(VERSION)"
+	@echo "pushed: $(IMAGE):$(ARCH)-$(VERSION)"
 
 clean: container-clean bin-clean
 	rm -r .cache

+ 14 - 14
vendor/modules.txt

@@ -194,48 +194,48 @@ k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextension
 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
 k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme
 # k8s.io/apimachinery v0.0.0-20190313205120-d7deff9243b1
+k8s.io/apimachinery/pkg/apis/meta/v1
+k8s.io/apimachinery/pkg/runtime
+k8s.io/apimachinery/pkg/runtime/schema
+k8s.io/apimachinery/pkg/runtime/serializer/json
 k8s.io/apimachinery/pkg/api/errors
 k8s.io/apimachinery/pkg/labels
 k8s.io/apimachinery/pkg/types
 k8s.io/apimachinery/pkg/util/strategicpatch
-k8s.io/apimachinery/pkg/apis/meta/v1
-k8s.io/apimachinery/pkg/runtime
-k8s.io/apimachinery/pkg/runtime/schema
 k8s.io/apimachinery/pkg/runtime/serializer
 k8s.io/apimachinery/pkg/util/runtime
 k8s.io/apimachinery/pkg/watch
 k8s.io/apimachinery/pkg/util/errors
 k8s.io/apimachinery/pkg/util/validation
-k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
 k8s.io/apimachinery/pkg/api/resource
-k8s.io/apimachinery/pkg/util/intstr
 k8s.io/apimachinery/pkg/conversion
-k8s.io/apimachinery/pkg/util/json
-k8s.io/apimachinery/pkg/util/validation/field
+k8s.io/apimachinery/pkg/fields
 k8s.io/apimachinery/pkg/selection
+k8s.io/apimachinery/pkg/util/intstr
+k8s.io/apimachinery/pkg/conversion/queryparams
+k8s.io/apimachinery/pkg/util/json
+k8s.io/apimachinery/pkg/util/naming
 k8s.io/apimachinery/pkg/util/sets
+k8s.io/apimachinery/pkg/runtime/serializer/recognizer
+k8s.io/apimachinery/pkg/util/framer
+k8s.io/apimachinery/pkg/util/yaml
+k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
+k8s.io/apimachinery/pkg/util/validation/field
 k8s.io/apimachinery/pkg/util/mergepatch
 k8s.io/apimachinery/third_party/forked/golang/json
 k8s.io/apimachinery/pkg/api/meta
-k8s.io/apimachinery/pkg/fields
 k8s.io/apimachinery/pkg/util/cache
 k8s.io/apimachinery/pkg/util/clock
 k8s.io/apimachinery/pkg/util/diff
-k8s.io/apimachinery/pkg/util/naming
 k8s.io/apimachinery/pkg/util/wait
-k8s.io/apimachinery/pkg/conversion/queryparams
 k8s.io/apimachinery/pkg/version
 k8s.io/apimachinery/pkg/runtime/serializer/streaming
 k8s.io/apimachinery/pkg/util/net
-k8s.io/apimachinery/pkg/runtime/serializer/json
 k8s.io/apimachinery/pkg/runtime/serializer/protobuf
-k8s.io/apimachinery/pkg/runtime/serializer/recognizer
 k8s.io/apimachinery/pkg/runtime/serializer/versioning
 k8s.io/apimachinery/third_party/forked/golang/reflect
 k8s.io/apimachinery/pkg/apis/meta/v1beta1
 k8s.io/apimachinery/pkg/apis/meta/internalversion
-k8s.io/apimachinery/pkg/util/framer
-k8s.io/apimachinery/pkg/util/yaml
 # k8s.io/client-go v11.0.0+incompatible
 k8s.io/client-go/kubernetes
 k8s.io/client-go/tools/clientcmd