Multi arch Dockerfile and CI (#63)

* Modify Dockerfile
- Use rustup from Docker image
- Give up on cross compilation (ring issue)
- Remove useless duplicate cargo install step
- No need to specify target as it is built statically for the docker platform targeted
- Shorten binary path output for shorter COPY

* Github Actions to build for all ARM as well

* Remove unneded musl-dev

* Adapt build for all platforms
- Use Debian based Rust for compilation
- Cross compile on build platform
- Compile static binaries using musl
- Set variables correctly for all Docker supported platforms
- Note: ppc64le, s390x and riscv64 do not support the Rust standard lib
- Persist target platform variables through files
- Define linkers in .cargo/config
- Cache dependencies properly for target platform
- Scratch stage to test the binary for target platform

* Add 386 arch to CI

* Use buildkit for docker build

* Only build for amd64 on branches

* Fix dependencies caching

* Split dependencies fetching and compilation

* Documentation

* Build for all architectures on branch

* Add STATIC build argument

* Documentation
This commit is contained in:
Quentin McGaw 2021-07-08 00:17:51 -07:00 committed by GitHub
parent a07a3d0170
commit 3a74f8b5b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 19 deletions

25
.cargo/config.toml Normal file
View file

@ -0,0 +1,25 @@
# This is used in the Docker build, you might need to adjust it for local usage.
[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"
[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"
[target.armv7-unknown-linux-musleabi]
linker = "armv7m-linux-musleabi-gcc"
[target.arm-unknown-linux-musleabi]
linker = "armv6-linux-musleabi-gcc"
[target.i686-unknown-linux-musl]
linker = "i686-linux-musl-gcc"
[target.powerpc64le-unknown-linux-musl]
linker = "powerpc64le-linux-musl-gcc"
[target.s390x-unknown-linux-musl]
linker = "s390x-linux-musl-gcc"
[target.riscv64gc-unknown-linux-musl]
linker = "riscv64-linux-musl-gcc"

View file

@ -19,6 +19,8 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: "1"
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2

View file

@ -32,7 +32,7 @@ jobs:
run: | run: |
docker buildx build \ docker buildx build \
--progress plain \ --progress plain \
--platform=linux/amd64 \ --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg COMMIT=`git rev-parse --short HEAD` \ --build-arg COMMIT=`git rev-parse --short HEAD` \
--build-arg VERSION=${GITHUB_REF##*/} \ --build-arg VERSION=${GITHUB_REF##*/} \

View file

@ -29,7 +29,7 @@ jobs:
run: | run: |
docker buildx build \ docker buildx build \
--progress plain \ --progress plain \
--platform=linux/amd64 \ --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg COMMIT=`git rev-parse --short HEAD` \ --build-arg COMMIT=`git rev-parse --short HEAD` \
--build-arg VERSION=latest \ --build-arg VERSION=latest \

View file

@ -29,7 +29,7 @@ jobs:
run: | run: |
docker buildx build \ docker buildx build \
--progress plain \ --progress plain \
--platform=linux/amd64 \ --platform=linux/amd64,linux/386,linux/arm64,linux/arm/v6,linux/arm/v7 \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \ --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg COMMIT=`git rev-parse --short HEAD` \ --build-arg COMMIT=`git rev-parse --short HEAD` \
--build-arg VERSION=${GITHUB_REF##*/} \ --build-arg VERSION=${GITHUB_REF##*/} \

View file

@ -1,34 +1,116 @@
ARG ALPINE_VERSION=3.12 ARG BUILDPLATFORM=linux/amd64
ARG RUST_VERSION=1-alpine${ALPINE_VERSION}
FROM rust:${RUST_VERSION} AS build ARG ALPINE_VERSION=3.12
ARG RUST_VERSION=1-slim-bullseye
FROM --platform=${BUILDPLATFORM} rust:${RUST_VERSION} AS build
WORKDIR /usr/src/prometheus_wireguard_exporter WORKDIR /usr/src/prometheus_wireguard_exporter
# Setup # Setup
ARG ARCH=x86_64 RUN apt-get update -y && \
RUN apk add --update -q --no-cache musl-dev apt-get install -y \
RUN rustup target add ${ARCH}-unknown-linux-musl # to cross build with musl
musl-tools \
# to download the musl cross build tool
wget \
# for verifying the binary properties
file
# Download dependencies
RUN mkdir src && \
echo 'fn main() {}' > src/main.rs
COPY Cargo.toml Cargo.lock ./
RUN cargo fetch && \
rm src/main.rs
ARG STATIC=yes
RUN touch /tmp/rustflags && \
if [ "${STATIC}" != "yes" ]; then \
echo "-C target-feature=-crt-static" | tee /tmp/rustflags; \
fi
ARG TARGETPLATFORM
RUN echo "Setting variables for ${TARGETPLATFORM:=linux/amd64}" && \
case "${TARGETPLATFORM}" in \
linux/amd64) \
MUSL="x86_64-linux-musl"; \
RUSTTARGET="x86_64-unknown-linux-musl"; \
break;; \
linux/arm64) \
MUSL="aarch64-linux-musl"; \
RUSTTARGET="aarch64-unknown-linux-musl"; \
break;; \
linux/arm/v7) \
MUSL="armv7m-linux-musleabi"; \
RUSTTARGET="armv7-unknown-linux-musleabi"; \
break;; \
linux/arm/v6) \
MUSL="armv6-linux-musleabi"; \
RUSTTARGET="arm-unknown-linux-musleabi"; \
break;; \
linux/386) \
MUSL="i686-linux-musl"; \
RUSTTARGET="i686-unknown-linux-musl"; \
break;; \
linux/ppc64le) \
MUSL="powerpc64le-linux-musl"; \
RUSTTARGET="powerpc64le-unknown-linux-musl"; \
break;; \
linux/s390x) \
MUSL="s390x-linux-musl"; \
RUSTTARGET="s390x-unknown-linux-musl"; \
break;; \
linux/riscv64) \
MUSL="riscv64-linux-musl"; \
RUSTTARGET="riscv64gc-unknown-linux-musl"; \
break;; \
*) echo "unsupported platform ${TARGETPLATFORM}"; exit 1;; \
esac && \
echo "${MUSL}" | tee /tmp/musl && \
echo "${RUSTTARGET}" | tee /tmp/rusttarget
RUN MUSL="$(cat /tmp/musl)" && \
wget -qO- "https://musl.cc/$MUSL-cross.tgz" | tar -xzC /tmp && \
rm "/tmp/$MUSL-cross/usr" && \
cp -fr /tmp/"$MUSL"-cross/* / && \
rm -rf "/tmp/$MUSL-cross"
RUN rustup target add "$(cat /tmp/rusttarget)"
# Copy .cargo/config for cross build configuration
COPY .cargo ./.cargo
# Install dependencies # Install dependencies
COPY Cargo.toml Cargo.lock ./ RUN echo 'fn main() {}' > src/main.rs && \
RUN mkdir src && \ RUSTFLAGS="$(cat /tmp/rustflags)" \
echo "fn main() {}" > src/main.rs CC="$(cat /tmp/musl)-gcc" \
RUN cargo build --release && \ cargo build --target "$(cat /tmp/rusttarget)" --release
rm -rf target/release/deps/prometheus_wireguard_exporter* RUN rm -r \
target/*-linux-*/release/deps/prometheus_wireguard_exporter* \
target/*-linux-*/release/prometheus_wireguard_exporter* \
src/main.rs
# Build the musl linked binary # Build static binary with musl built-in
COPY . . COPY . .
RUN cargo build --release RUN RUSTFLAGS="$(cat /tmp/rustflags)" \
RUN cargo install --target ${ARCH}-unknown-linux-musl --path . CC="$(cat /tmp/musl)-gcc" \
cargo build --target "$(cat /tmp/rusttarget)" --release && \
mv target/*-linux-*/release/prometheus_wireguard_exporter /tmp/binary
RUN description="$(file /tmp/binary)" && \
echo "$description" && \
if [ "${STATIC}" = "yes" ] && [ ! -z "$(echo $description | grep musl)" ]; then \
echo "binary is not statically built!" && exit 1; \
fi
FROM alpine:${ALPINE_VERSION} FROM alpine:${ALPINE_VERSION}
EXPOSE 9586/tcp EXPOSE 9586/tcp
WORKDIR /usr/local/bin
RUN adduser prometheus-wireguard-exporter -s /bin/sh -D -u 1000 1000 && \ RUN adduser prometheus-wireguard-exporter -s /bin/sh -D -u 1000 1000 && \
mkdir -p /etc/sudoers.d && \ mkdir -p /etc/sudoers.d && \
echo 'prometheus-wireguard-exporter ALL=(root) NOPASSWD:/usr/bin/wg show * dump' > /etc/sudoers.d/prometheus-wireguard-exporter && \ echo 'prometheus-wireguard-exporter ALL=(root) NOPASSWD:/usr/bin/wg show * dump' > /etc/sudoers.d/prometheus-wireguard-exporter && \
chmod 0440 /etc/sudoers.d/prometheus-wireguard-exporter chmod 0440 /etc/sudoers.d/prometheus-wireguard-exporter
RUN apk add --update -q --no-cache wireguard-tools-wg sudo RUN apk add --update -q --no-cache wireguard-tools-wg sudo
USER prometheus-wireguard-exporter USER prometheus-wireguard-exporter
ENTRYPOINT [ "prometheus_wireguard_exporter" ] ENTRYPOINT [ "/usr/local/bin/prometheus_wireguard_exporter" ]
CMD [ "-a" ] CMD [ "-a" ]
COPY --from=build --chown=prometheus-wireguard-exporter /usr/local/cargo/bin/prometheus_wireguard_exporter /usr/local/bin/prometheus_wireguard_exporter COPY --from=build --chown=prometheus-wireguard-exporter /tmp/binary ./prometheus_wireguard_exporter

View file

@ -43,6 +43,20 @@ docker run -it --rm --init --net=host --cap-add=NET_ADMIN mindflavor/prometheus-
docker run -it --rm alpine:3.12 wget -qO- http://localhost:9586/metrics docker run -it --rm alpine:3.12 wget -qO- http://localhost:9586/metrics
``` ```
The Docker image is compatible with `amd64`, `386`, `arm64`, `armv7` and `armv6` CPUs.
To update the image, you can use
```sh
docker pull mindflavor/prometheus_wireguard_exporter
```
You can also build it with:
```sh
docker build -t mindflavor/prometheus_wireguard_exporter https://github.com/MindFlavor/prometheus_wireguard_exporter.git
```
## Compilation ## Compilation
To compile the latest master version: To compile the latest master version: