diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..82bd83ad --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +# Git status should be ignored +.git + +# .dockerignore should be ignored +.dockerignore + +# Almost all of the reweave directory +# should be ignored +reweave/build/Dockerfile +reweave/tools/ +reweave/scans/ +reweave/Makefile +reweave/*.md \ No newline at end of file diff --git a/reweave/BUILDING.md b/reweave/BUILDING.md new file mode 100644 index 00000000..10b4a1c5 --- /dev/null +++ b/reweave/BUILDING.md @@ -0,0 +1,95 @@ +# New Build Process + +This new build process is based on a multi-stage Dockerfile, which combines the build image Dockerfile and all the template-generated final image Dockerfiles from the [old build process](BUILDING-OLD.md). + +> NOTE: The new process currently does not build the weave Docker plugin. Nor does it run any tests. This may change in the future. + +## What you need + +* Docker v23.0.1 or later +* An account on an image registry, like the Docker Hub +* [grype](https://github.com/anchore/grype) 0.59.0 or later for image scanning +* The `tools` directory contents. Run `git submodule update --init`. + +## During development + +At the start of each development cycle, edit [reweave/Makefile](Makefile) and set `IMAGE_VERSION` should be set to something later than the currently published version, perhaps with a prerelease suffix. Also, set `REGISTRY_USER` to a your registry user account. + +After you make code or configurations changes, run the following in the `reweave` directory: + +```bash +make +``` + +This will build all weave net images for your local platform, tag them with your repo user name, and load them to your local docker engine. + +Once the images are built, you can scan the `weave-kube` and `weave-npc` images by running: + +```bash +make scan +``` + +This will scan the images and generate reports in the [scans](scans/) directory. + +## To publish images + +1. Change `IMAGE_VERSION` and `REGISTRY_USER` variables in [reweave/Makefile](Makefile) to their final, publishable versions. +2. Build and scan as you would for development. +3. Commit and tag your changes. +4. Login to your registry account using `docker login`. +5. Run the following: + +```bash +make publish +``` + +This will build multi-architecture images, and push them to your registry. + +Don't forget to `docker logout` afterwards. + +## Multi-stage Dockerfile + +The Dockerfile can be found at [reweave/build/Dockerfile](build/Dockerfile). It, and the companion [Makefile](#makefile), build multi-arch images for all weave components. + +### Stage 1 (builderbase) + +The first stage creates a build environment for cross-compiling all weave net executables for all supported architectures. It is built only once for a given build platform. It starts with `golang:1.20.2-bullseye` as a base, and does the following: + +* Installs build essentials and cross-compilers for all supported architectures. +* Adds the Debian buster repositories. This is because the last supported version of `libpcap` that allows static linking (1.8.1) is not present in the Debian bullseye repos. +* Installs `libpcap-dev`, pinned to v1.8.1. + +### Stage 2 (builder) + +The second stage is where the weave net executables are built. It is built once for each target architecture. + +It starts from `builderbase` as the base, and does the following: + +* Sets environment variables indicating the current build and target architectures +* Copies in the source code +* Downloads modules +* Uses the [Makefile](#makefile) to build all weave net executables for the target architecture + +### Stage 3 (alpinebase) + +All weave net images ultimately derive from an Alpine base image. This stage allows customization of an official Alpine image, and using the customized image as the base for the weave net images. Currently, there is no customization required. + +### Subsequent stages + +Each of the subsequent stages builds one image, corresponding to one component of weave net. These start from `alpinebase`, or `weaverimage` (Stage 4) as the base, and add what executables, scripts and configuration they need from `builder`. + +## Makefile + +The [Makefile](build/Makefile) is a distilled version of the [old Makefile](../Makefile). It only builds executables. It invokes the correct C cross-compiler, and picks up the correct static `libpcap`, based on the target architecture. It is meant be used only in Stage 2 of the build process, and not directly. + +## build-images.sh + +This script invokes `docker buildx build` for each stage from stage 4 onwards. By default, it builds for all supported platforms, tags the image as `weaveworks/IMAGENAME:CURRENTVERSION`, and keeps them in the build cache. This behavior can be controlled by setting the following environment variables before invoking the script. + +|Env Var Name|Description|Default Value| +|---|---|---| +|IMAGE_VERSION|The tag part of the name (after `:`) for all weave net images.|*version set in script file*| +|REGISTRY_USER|The account name (with optional registry name in front) used to tag all weave net images.|`weaveworks`| +|PLATFORMS|Comma-separated list of the target platforms for which the weave net images will be built.|`linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x`| +|POSTBUILD|Whether to push the images after build (`--push`) , or load them to the local Docker engine (`--load`). `--load` is only possible if PLATFORMS has the same value as the build platform. If left empty, the images will be built in the build cache only.|| +|ALPINE_BASEIMAGE|The qualified name for the base Alpine image used to build all weave net images.|`alpine:3.17.2`| diff --git a/reweave/CHANGELOG.md b/reweave/CHANGELOG.md index 1d49568b..2bb9e7d8 100644 --- a/reweave/CHANGELOG.md +++ b/reweave/CHANGELOG.md @@ -2,6 +2,22 @@ All changes made to the weave net codebase during the reweave effort will be documented in this file. +## 2.8.2-beta0 + +A new build process was created here. + +### Added + +* Documentation and tools under the `reweave` directory +* .dockerignore in the repository root, to exclude files from the new build process +* Multi-stage Dockerfile, and a Makefile for the second stage, in `reweave/build` + +### Changed +* Included image building targets in Makefile directly under `reweave` +* Changed `IMAGE_VERSION` to `2.8.2-beta0` in Makefile directly under `reweave` +* The Alpine base image for all weave net images was set to `alpine:3.17.2` via the multi-stage Dockerfile +* Re-generated security scan reports after building with the new process + ## 2.8.1 This was the last released version of the weave net images before the reweave effort began. @@ -10,4 +26,4 @@ This was the last released version of the weave net images before the reweave ef * Documentation and tools under the `reweave` directory * Image security scanning tools -* Security scan reports for `weave-kube` and `weave-npc` images. +* Security scan reports for `weave-kube` and `weave-npc` images diff --git a/reweave/Makefile b/reweave/Makefile index 895f8423..239220a4 100644 --- a/reweave/Makefile +++ b/reweave/Makefile @@ -1,15 +1,38 @@ -IMAGE_VERSION ?= 2.8.1 +IMAGE_VERSION ?= 2.8.2-beta0 REGISTRY_USER ?= weaveworks # Targets +.PHONY: build +build: submodule + REGISTRY_USER=${REGISTRY_USER} IMAGE_VERSION=${IMAGE_VERSION} \ + PLATFORMS="$$(docker version -f '{{ .Server.Arch }}')" \ + POSTBUILD=--load \ + tools/build-images.sh + .PHONY: scan scan: REGISTRY_USER=${REGISTRY_USER} IMAGE_VERSION=${IMAGE_VERSION} \ tools/scan-images.sh +.PHONY: publish +publish: submodule + REGISTRY_USER=${REGISTRY_USER} IMAGE_VERSION=${IMAGE_VERSION} \ + POSTBUILD=--push tools/build-images.sh + +.PHONY: clean-images +clean-images: + REGISTRY_USER=${REGISTRY_USER} IMAGE_VERSION=${IMAGE_VERSION} \ + tools/clean-images.sh + .PHONY: clean-scan clean-scan: tools/clean-scans.sh .PHONY: clean -clean: clean-scan +clean: clean-scan clean-images + +.PHONY: submodule +submodule: ../tools/.git + +../tools/.git: + git submodule update --init diff --git a/reweave/README.md b/reweave/README.md index 98c0c37f..5c1ce619 100644 --- a/reweave/README.md +++ b/reweave/README.md @@ -14,8 +14,8 @@ The current focus of this effort is running weave net as a CNI plugin on Kuberne * ~~Document the old build process~~Old build process documented in [BUILDING-OLD.md](BUILDING-OLD.md) * ~~Create a image scanning process and scan current image~~Image scanning process created, scan reports generated for 2.8.1 -* Create a new build process -* Build, generate and test current images +* ~~Create a new build process~~New build process created, documented in [BUILDING.md](BUILDING.md) +* ~~Build, generate and test current images~~Built and scanned v2.8.2-beta0 * Upgrade Go compiler version * Scan images for CVEs * While there are fixable CVEs: diff --git a/reweave/build/Dockerfile b/reweave/build/Dockerfile new file mode 100644 index 00000000..58ca3f15 --- /dev/null +++ b/reweave/build/Dockerfile @@ -0,0 +1,259 @@ +# syntax=docker/dockerfile:1 +ARG ALPINE_BASEIMAGE=alpine:3.17.2 + +######## +# Stage 1: go 1.20 on debian bullseye +# This installs cross-compilation tools for supported architectures. +# It will be built only once for a given build platform. Subsequent +# stages will start from this and cross-compile for each target +# architecture. +FROM --platform=$BUILDPLATFORM golang:1.20.2-bullseye AS builderbase + +# Support Raspberry Pi 2 and newer +ENV GOARM 7 + +# The names of the architectures that we fetch cross-compilers for +# from the Debian packages. +ENV DEB_CROSSPLATFORMS \ + amd64 \ + armhf \ + arm64 \ + ppc64el \ + s390x + +# Install the build-essential and crossbuild-essential-ARCH packages +RUN < /etc/apt/sources.list.d/busters-repos.list +echo "deb-src http://deb.debian.org/debian/ buster main" >> /etc/apt/sources.list.d/busters-repos.list +apt-get update +for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y libpcap0.8:${platform}=1.8.1-6+deb10u1 libpcap0.8-dev:${platform}=1.8.1-6+deb10u1 libpcap-dev:${platform}=1.8.1-6+deb10u1; done +EOBUSTERREPOS +# End Stage 1 +######## + +######## +# Stage 2: Compile weave-net executables. +# This stage builds one image per supported architecture. The +# companion Makefile compiles all executables that make up weave +# net, for the target architecture. Subsequent stages each build +# an image for a single component of weave-net. +FROM builderbase AS builder +ARG BUILDARCH +ARG TARGETARCH +ARG WEAVE_VERSION +ENV ARCH=${TARGETARCH} +ENV BUILDARCH=${BUILDARCH} +# Git hash that will be built into executables +ENV WEAVE_VERSION=${WEAVE_VERSION} + +WORKDIR /root/weave +COPY . . + +RUN go mod download -x +RUN <&2 echo "Please provide valid values for IMAGE_VERSION and REGISTRY_USER." + exit 1 +fi + +# These variables are used to control the build process +# Change with care. +: "${ALPINE_BASEIMAGE:=alpine:3.17.2}" +: "${WEAVE_VERSION=git-$(git rev-parse --short=12 HEAD)}" +: "${GIT_REVISION=$(git rev-parse HEAD)}" +: "${PLATFORMS:=linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x}" +: "${POSTBUILD:=}" + +# These are the names of the images +WEAVER_IMAGE=${REGISTRY_USER}/weave:${IMAGE_VERSION} +WEAVEEXEC_IMAGE=${REGISTRY_USER}/weaveexec:${IMAGE_VERSION} +WEAVEKUBE_IMAGE=${REGISTRY_USER}/weave-kube:${IMAGE_VERSION} +WEAVENPC_IMAGE=${REGISTRY_USER}/weave-npc:${IMAGE_VERSION} +WEAVEDB_IMAGE=${REGISTRY_USER}/weavedb:${IMAGE_VERSION} +NETWORKTESTER_IMAGE=${REGISTRY_USER}/network-tester:${IMAGE_VERSION} + +build_image() { + # Get directory of script file + a="/$0"; a="${a%/*}"; a="${a:-.}"; a="${a##/}/"; BINDIR=$(cd "$a"; pwd) + + cd "$BINDIR/../.." + + # shellcheck disable=SC2086 + docker buildx build \ + ${POSTBUILD} \ + --platform=${PLATFORMS} \ + --target="$1" \ + --build-arg=ALPINE_BASEIMAGE=${ALPINE_BASEIMAGE} \ + --build-arg=WEAVE_VERSION=${WEAVE_VERSION} \ + --build-arg=revision=${GIT_REVISION} \ + --build-arg=imageversion=${IMAGE_VERSION} \ + -f reweave/build/Dockerfile \ + -t "$2" \ + . + + cd - +} + +# shellcheck disable=SC2086 +{ +build_image "weaverimage" ${WEAVER_IMAGE} +build_image "weavexecimage" ${WEAVEEXEC_IMAGE} +build_image "weavekubeimage" ${WEAVEKUBE_IMAGE} +build_image "weavenpcimage" ${WEAVENPC_IMAGE} +build_image "weavedbimage" ${WEAVEDB_IMAGE} +build_image "networktesterimage" ${NETWORKTESTER_IMAGE} +} \ No newline at end of file diff --git a/reweave/tools/clean-images.sh b/reweave/tools/clean-images.sh new file mode 100755 index 00000000..40c833cb --- /dev/null +++ b/reweave/tools/clean-images.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -e + +# These variables are used to tag the images. Change as +# required. +: "${IMAGE_VERSION:=}" +: "${REGISTRY_USER:=}" + +if [ -z "${IMAGE_VERSION}" ] || [ -z "${REGISTRY_USER}" ] ; then + >&2 echo "Please provide valid values for IMAGE_VERSION and REGISTRY_USER." + exit 1 +fi + +# These are the names of the images +WEAVER_IMAGE=${REGISTRY_USER}/weave:${IMAGE_VERSION} +WEAVEEXEC_IMAGE=${REGISTRY_USER}/weaveexec:${IMAGE_VERSION} +WEAVEKUBE_IMAGE=${REGISTRY_USER}/weave-kube:${IMAGE_VERSION} +WEAVENPC_IMAGE=${REGISTRY_USER}/weave-npc:${IMAGE_VERSION} +WEAVEDB_IMAGE=${REGISTRY_USER}/weavedb:${IMAGE_VERSION} +NETWORKTESTER_IMAGE=${REGISTRY_USER}/network-tester:${IMAGE_VERSION} + +docker image rm "${WEAVER_IMAGE}" "${WEAVEEXEC_IMAGE}" "${WEAVEKUBE_IMAGE}" \ + "${WEAVENPC_IMAGE}" "${WEAVEDB_IMAGE}" "${NETWORKTESTER_IMAGE}" +