Ver Fonte

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 há 7 anos atrás
pai
commit
adb09ce620
5 ficheiros alterados com 112 adições e 40 exclusões
  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