Initial multi-arch image commit (#86)

Adding multi-arch image support for `arm64` and `amd64`. This uses dockers new `buildx` feature, to enable further architectures more work will be required to update the `runner/Dockerfile` file to pull architecture-specific releases.

The Makefile targets really should only be used for local testing and not for release, additional work to appropriately tag the release images may need to be added but for now, I've not added that logic.

Fixes: #86 

Signed-off-by: Michael Fornaro <20387402+xUnholy@users.noreply.github.com>
This commit is contained in:
MIℂHΛΞL FѲRИΛRѲ 2020-10-05 11:26:46 +11:00 committed by GitHub
parent e8a7733ee7
commit a309eb1687
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 213 additions and 93 deletions

View File

@ -1,22 +1,34 @@
on: on:
push: push:
branches: branches:
- master - master
paths: paths:
- 'runner/**' - 'runner/**'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Build runner name: Build runner
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Build container image
run: make docker-build - name: Set up Docker Buildx
working-directory: runner id: buildx
- name: Docker Login uses: crazy-max/ghaction-docker-buildx@v1
run: docker login -u summerwind -p ${{ secrets.DOCKER_ACCESS_TOKEN }} with:
- name: Push container image buildx-version: latest
run: make docker-push
working-directory: runner - name: Login to GitHub Docker Registry
run: echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
env:
DOCKERHUB_USERNAME: summerwind
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build Container Image
working-directory: runner
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag summerwind/actions-runner:latest \
-f Dockerfile . --push

View File

@ -3,28 +3,43 @@ name: Build
on: on:
push: push:
branches: branches:
- master - master
paths-ignore: paths-ignore:
- 'runner/**' - 'runner/**'
- '.github/**' - '.github/**'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Build name: Build
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install kubebuilder
run: | - name: Install kubebuilder
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz run: |
tar zxvf kubebuilder_2.2.0_linux_amd64.tar.gz curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz
sudo mv kubebuilder_2.2.0_linux_amd64 /usr/local/kubebuilder tar zxvf kubebuilder_2.2.0_linux_amd64.tar.gz
- name: Run tests sudo mv kubebuilder_2.2.0_linux_amd64 /usr/local/kubebuilder
run: make test
- name: Build container image - name: Run tests
run: make docker-build run: make test
- name: Docker Login
run: docker login -u summerwind -p ${{ secrets.DOCKER_ACCESS_TOKEN }} - name: Set up Docker Buildx
- name: Push container image id: buildx
run: make docker-push uses: crazy-max/ghaction-docker-buildx@v1
with:
buildx-version: latest
- name: Login to GitHub Docker Registry
run: echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
env:
DOCKERHUB_USERNAME: summerwind
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build Container Image
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag summerwind/actions-runner-controller:latest \
-f Dockerfile . --push

View File

@ -7,27 +7,43 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Release name: Release
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Install tools
run: | - name: Install tools
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz run: |
tar zxvf kubebuilder_2.2.0_linux_amd64.tar.gz curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.2.0/kubebuilder_2.2.0_linux_amd64.tar.gz
sudo mv kubebuilder_2.2.0_linux_amd64 /usr/local/kubebuilder tar zxvf kubebuilder_2.2.0_linux_amd64.tar.gz
curl -s https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh | bash sudo mv kubebuilder_2.2.0_linux_amd64 /usr/local/kubebuilder
sudo mv kustomize /usr/local/bin curl -s https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh | bash
curl -L -O https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz sudo mv kustomize /usr/local/bin
tar zxvf ghr_v0.13.0_linux_amd64.tar.gz curl -L -O https://github.com/tcnksm/ghr/releases/download/v0.13.0/ghr_v0.13.0_linux_amd64.tar.gz
sudo mv ghr_v0.13.0_linux_amd64/ghr /usr/local/bin tar zxvf ghr_v0.13.0_linux_amd64.tar.gz
- name: Set version sudo mv ghr_v0.13.0_linux_amd64/ghr /usr/local/bin
run: echo "::set-env name=VERSION::$(cat ${GITHUB_EVENT_PATH} | jq -r '.release.tag_name')"
- name: Upload artifacts - name: Set version
env: run: echo "::set-env name=VERSION::$(cat ${GITHUB_EVENT_PATH} | jq -r '.release.tag_name')"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: make github-release - name: Upload artifacts
- name: Build container image env:
run: make docker-build GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Login run: make github-release
run: docker login -u summerwind -p ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Push container image - name: Set up Docker Buildx
run: make docker-push id: buildx
uses: crazy-max/ghaction-docker-buildx@v1
with:
buildx-version: latest
- name: Login to GitHub Docker Registry
run: echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
env:
DOCKERHUB_USERNAME: summerwind
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build Container Image
run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag summerwind/actions-runner-controller:${{ env.VERSION }} \
-f Dockerfile . --push

View File

@ -1,28 +1,37 @@
# Build the manager binary # Build the manager binary
FROM golang:1.13 as builder FROM golang:1.13 as builder
ARG TARGETPLATFORM
WORKDIR /workspace WORKDIR /workspace
ENV GO111MODULE=on \
CGO_ENABLED=0
# Copy the Go Modules manifests # Copy the Go Modules manifests
COPY go.mod go.mod COPY go.mod go.sum ./
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much # cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer # and so that source changes don't invalidate our downloaded layer
RUN go mod download RUN go mod download
# Copy the go source # Copy the go source
COPY main.go main.go COPY . .
COPY api/ api/
COPY controllers/ controllers/
COPY github/ github/
# Build # Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go RUN export GOOS=$(echo ${TARGETPLATFORM} | cut -d / -f1) && \
export GOARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) && \
GOARM=$(echo ${TARGETPLATFORM} | cut -d / -f3 | cut -c2-) && \
go build -a -o manager main.go
# Use distroless as minimal base image to package the manager binary # Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details # Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot FROM gcr.io/distroless/static:nonroot
WORKDIR / WORKDIR /
COPY --from=builder /workspace/manager . COPY --from=builder /workspace/manager .
USER nonroot:nonroot USER nonroot:nonroot
ENTRYPOINT ["/manager"] ENTRYPOINT ["/manager"]

View File

@ -11,6 +11,23 @@ else
GOBIN=$(shell go env GOBIN) GOBIN=$(shell go env GOBIN)
endif endif
# default list of platforms for which multiarch image is built
ifeq (${PLATFORMS}, )
export PLATFORMS="linux/amd64,linux/arm64"
endif
# if IMG_RESULT is unspecified, by default the image will be pushed to registry
ifeq (${IMG_RESULT}, load)
export PUSH_ARG="--load"
# if load is specified, image will be built only for the build machine architecture.
export PLATFORMS="local"
else ifeq (${IMG_RESULT}, cache)
# if cache is specified, image will only be available in the build cache, it won't be pushed or loaded
# therefore no PUSH_ARG will be specified
else
export PUSH_ARG="--push"
endif
all: manager all: manager
# Run tests # Run tests
@ -62,6 +79,18 @@ docker-build: test
docker-push: docker-push:
docker push ${NAME}:${VERSION} docker push ${NAME}:${VERSION}
docker-buildx:
export DOCKER_CLI_EXPERIMENTAL=enabled
@if ! docker buildx ls | grep -q container-builder; then\
docker buildx create --platform ${PLATFORMS} --name container-builder --use;\
fi
docker buildx build --platform ${PLATFORMS} \
--build-arg RUNNER_VERSION=${RUNNER_VERSION} \
--build-arg DOCKER_VERSION=${DOCKER_VERSION} \
-t "${NAME}:${VERSION}" \
-f Dockerfile \
. ${PUSH_ARG}
# Generate the release manifest file # Generate the release manifest file
release: manifests release: manifests
cd config/manager && kustomize edit set image controller=${NAME}:${VERSION} cd config/manager && kustomize edit set image controller=${NAME}:${VERSION}

View File

@ -1,7 +1,8 @@
FROM ubuntu:18.04 FROM ubuntu:18.04
ARG RUNNER_VERSION ARG TARGETPLATFORM
ARG DOCKER_VERSION ARG RUNNER_VERSION=2.272.0
ARG DOCKER_VERSION=19.03.12
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
RUN apt update -y \ RUN apt update -y \
@ -9,46 +10,55 @@ RUN apt update -y \
&& add-apt-repository -y ppa:git-core/ppa \ && add-apt-repository -y ppa:git-core/ppa \
&& apt update -y \ && apt update -y \
&& apt install -y --no-install-recommends \ && apt install -y --no-install-recommends \
build-essential \ build-essential \
curl \ curl \
ca-certificates \ ca-certificates \
dnsutils \ dnsutils \
ftp \ ftp \
git \ git \
iproute2 \ iproute2 \
iputils-ping \ iputils-ping \
jq \ jq \
libunwind8 \ libunwind8 \
locales \ locales \
netcat \ netcat \
openssh-client \ openssh-client \
parallel \ parallel \
rsync \ rsync \
shellcheck \ shellcheck \
sudo \ sudo \
telnet \ telnet \
time \ time \
tzdata \ tzdata \
unzip \ unzip \
upx \ upx \
wget \ wget \
zip \ zip \
zstd \ zstd \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN curl -L -o docker.tgz https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& curl -L -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_${ARCH} \
&& chmod +x /usr/local/bin/dumb-init
# Docker download supports arm64 as aarch64 & amd64 as x86_64
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ]; then export ARCH=x86_64 ; fi \
&& curl -L -o docker.tgz https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz \
&& tar zxvf docker.tgz \ && tar zxvf docker.tgz \
&& install -o root -g root -m 755 docker/docker /usr/local/bin/docker \ && install -o root -g root -m 755 docker/docker /usr/local/bin/docker \
&& rm -rf docker docker.tgz \ && rm -rf docker docker.tgz \
&& curl -L -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.2/dumb-init_1.2.2_amd64 \
&& chmod +x /usr/local/bin/dumb-init \
&& adduser --disabled-password --gecos "" --uid 1000 runner \ && adduser --disabled-password --gecos "" --uid 1000 runner \
&& usermod -aG sudo runner \ && usermod -aG sudo runner \
&& echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers && echo "%sudo ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers
RUN mkdir -p /runner \ # Runner download supports amd64 as x64
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "amd64" ]; then export ARCH=x64 ; fi \
&& mkdir -p /runner \
&& cd /runner \ && cd /runner \
&& curl -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \ && curl -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${ARCH}-${RUNNER_VERSION}.tar.gz \
&& tar xzf ./runner.tar.gz \ && tar xzf ./runner.tar.gz \
&& rm runner.tar.gz \ && rm runner.tar.gz \
&& ./bin/installdependencies.sh \ && ./bin/installdependencies.sh \

View File

@ -4,9 +4,38 @@ TAG ?= latest
RUNNER_VERSION ?= 2.273.4 RUNNER_VERSION ?= 2.273.4
DOCKER_VERSION ?= 19.03.12 DOCKER_VERSION ?= 19.03.12
# default list of platforms for which multiarch image is built
ifeq (${PLATFORMS}, )
export PLATFORMS="linux/amd64,linux/arm64"
endif
# if IMG_RESULT is unspecified, by default the image will be pushed to registry
ifeq (${IMG_RESULT}, load)
export PUSH_ARG="--load"
# if load is specified, image will be built only for the build machine architecture.
export PLATFORMS="local"
else ifeq (${IMG_RESULT}, cache)
# if cache is specified, image will only be available in the build cache, it won't be pushed or loaded
# therefore no PUSH_ARG will be specified
else
export PUSH_ARG="--push"
endif
docker-build: docker-build:
docker build --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:${TAG} -t ${NAME}:v${RUNNER_VERSION} . docker build --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:${TAG} -t ${NAME}:v${RUNNER_VERSION} .
docker-push: docker-push:
docker push ${NAME}:${TAG} docker push ${NAME}:${TAG}
docker push ${NAME}:v${RUNNER_VERSION} docker push ${NAME}:v${RUNNER_VERSION}
docker-buildx:
export DOCKER_CLI_EXPERIMENTAL=enabled
@if ! docker buildx ls | grep -q container-builder; then\
docker buildx create --platform ${PLATFORMS} --name container-builder --use;\
fi
docker buildx build --platform ${PLATFORMS} \
--build-arg RUNNER_VERSION=${RUNNER_VERSION} \
--build-arg DOCKER_VERSION=${DOCKER_VERSION} \
-t "${NAME}:latest" \
-f Dockerfile \
. ${PUSH_ARG}