Multi-arch image support
This commit is contained in:
parent
bbef332e25
commit
4559e85daa
|
@ -9,13 +9,13 @@
|
||||||
{% elif "amd64" in target_file %}
|
{% elif "amd64" in target_file %}
|
||||||
{% set runtime_stage_base_image = "debian:buster-slim" %}
|
{% set runtime_stage_base_image = "debian:buster-slim" %}
|
||||||
{% set package_arch_name = "" %}
|
{% set package_arch_name = "" %}
|
||||||
{% elif "aarch64" in target_file %}
|
{% elif "arm64v8" in target_file %}
|
||||||
{% set runtime_stage_base_image = "balenalib/aarch64-debian:buster" %}
|
{% set runtime_stage_base_image = "balenalib/aarch64-debian:buster" %}
|
||||||
{% set package_arch_name = "arm64" %}
|
{% set package_arch_name = "arm64" %}
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
{% set runtime_stage_base_image = "balenalib/rpi-debian:buster" %}
|
{% set runtime_stage_base_image = "balenalib/rpi-debian:buster" %}
|
||||||
{% set package_arch_name = "armel" %}
|
{% set package_arch_name = "armel" %}
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
{% set runtime_stage_base_image = "balenalib/armv7hf-debian:buster" %}
|
{% set runtime_stage_base_image = "balenalib/armv7hf-debian:buster" %}
|
||||||
{% set package_arch_name = "armhf" %}
|
{% set package_arch_name = "armhf" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -73,7 +73,7 @@ RUN rustup set profile minimal
|
||||||
ENV USER "root"
|
ENV USER "root"
|
||||||
ENV RUSTFLAGS='-C link-arg=-s'
|
ENV RUSTFLAGS='-C link-arg=-s'
|
||||||
|
|
||||||
{% elif "aarch64" in target_file or "armv" in target_file %}
|
{% elif "arm32" in target_file or "arm64" in target_file %}
|
||||||
# Install required build libs for {{ package_arch_name }} architecture.
|
# Install required build libs for {{ package_arch_name }} architecture.
|
||||||
RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \
|
RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \
|
||||||
/etc/apt/sources.list.d/deb-src.list \
|
/etc/apt/sources.list.d/deb-src.list \
|
||||||
|
@ -85,7 +85,7 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \
|
||||||
libc6-dev{{ package_arch_prefix }}
|
libc6-dev{{ package_arch_prefix }}
|
||||||
|
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{% if "aarch64" in target_file %}
|
{% if "arm64v8" in target_file %}
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y \
|
&& apt-get install -y \
|
||||||
--no-install-recommends \
|
--no-install-recommends \
|
||||||
|
@ -97,7 +97,7 @@ RUN apt-get update \
|
||||||
ENV CARGO_HOME "/root/.cargo"
|
ENV CARGO_HOME "/root/.cargo"
|
||||||
ENV USER "root"
|
ENV USER "root"
|
||||||
|
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y \
|
&& apt-get install -y \
|
||||||
--no-install-recommends \
|
--no-install-recommends \
|
||||||
|
@ -109,7 +109,7 @@ RUN apt-get update \
|
||||||
ENV CARGO_HOME "/root/.cargo"
|
ENV CARGO_HOME "/root/.cargo"
|
||||||
ENV USER "root"
|
ENV USER "root"
|
||||||
|
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y \
|
&& apt-get install -y \
|
||||||
--no-install-recommends \
|
--no-install-recommends \
|
||||||
|
@ -150,17 +150,17 @@ COPY ./Cargo.* ./
|
||||||
COPY ./rust-toolchain ./rust-toolchain
|
COPY ./rust-toolchain ./rust-toolchain
|
||||||
COPY ./build.rs ./build.rs
|
COPY ./build.rs ./build.rs
|
||||||
|
|
||||||
{% if "aarch64" in target_file %}
|
{% if "arm64v8" in target_file %}
|
||||||
ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc"
|
ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc"
|
||||||
ENV CROSS_COMPILE="1"
|
ENV CROSS_COMPILE="1"
|
||||||
ENV OPENSSL_INCLUDE_DIR="/usr/include/aarch64-linux-gnu"
|
ENV OPENSSL_INCLUDE_DIR="/usr/include/aarch64-linux-gnu"
|
||||||
ENV OPENSSL_LIB_DIR="/usr/lib/aarch64-linux-gnu"
|
ENV OPENSSL_LIB_DIR="/usr/lib/aarch64-linux-gnu"
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc"
|
ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc"
|
||||||
ENV CROSS_COMPILE="1"
|
ENV CROSS_COMPILE="1"
|
||||||
ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabi"
|
ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabi"
|
||||||
ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabi"
|
ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabi"
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc"
|
ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc"
|
||||||
ENV CROSS_COMPILE="1"
|
ENV CROSS_COMPILE="1"
|
||||||
ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf"
|
ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf"
|
||||||
|
@ -170,13 +170,13 @@ ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf"
|
||||||
{% if "alpine" in target_file %}
|
{% if "alpine" in target_file %}
|
||||||
RUN rustup target add x86_64-unknown-linux-musl
|
RUN rustup target add x86_64-unknown-linux-musl
|
||||||
|
|
||||||
{% elif "aarch64" in target_file %}
|
{% elif "arm64v8" in target_file %}
|
||||||
RUN rustup target add aarch64-unknown-linux-gnu
|
RUN rustup target add aarch64-unknown-linux-gnu
|
||||||
|
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
RUN rustup target add arm-unknown-linux-gnueabi
|
RUN rustup target add arm-unknown-linux-gnueabi
|
||||||
|
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||||
{% endif %}
|
{% endif %}
|
||||||
# Builds your dependencies and removes the
|
# Builds your dependencies and removes the
|
||||||
|
@ -196,11 +196,11 @@ RUN touch src/main.rs
|
||||||
# your actual source files being built
|
# your actual source files being built
|
||||||
{% if "amd64" in target_file %}
|
{% if "amd64" in target_file %}
|
||||||
RUN cargo build --features ${DB} --release
|
RUN cargo build --features ${DB} --release
|
||||||
{% elif "aarch64" in target_file %}
|
{% elif "arm64v8" in target_file %}
|
||||||
RUN cargo build --features ${DB} --release --target=aarch64-unknown-linux-gnu
|
RUN cargo build --features ${DB} --release --target=aarch64-unknown-linux-gnu
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
RUN cargo build --features ${DB} --release --target=arm-unknown-linux-gnueabi
|
RUN cargo build --features ${DB} --release --target=arm-unknown-linux-gnueabi
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
RUN cargo build --features ${DB} --release --target=armv7-unknown-linux-gnueabihf
|
RUN cargo build --features ${DB} --release --target=armv7-unknown-linux-gnueabihf
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -265,11 +265,11 @@ COPY Rocket.toml .
|
||||||
COPY --from=vault /web-vault ./web-vault
|
COPY --from=vault /web-vault ./web-vault
|
||||||
{% if "alpine" in target_file %}
|
{% if "alpine" in target_file %}
|
||||||
COPY --from=build /app/target/x86_64-unknown-linux-musl/release/bitwarden_rs .
|
COPY --from=build /app/target/x86_64-unknown-linux-musl/release/bitwarden_rs .
|
||||||
{% elif "aarch64" in target_file %}
|
{% elif "arm64v8" in target_file %}
|
||||||
COPY --from=build /app/target/aarch64-unknown-linux-gnu/release/bitwarden_rs .
|
COPY --from=build /app/target/aarch64-unknown-linux-gnu/release/bitwarden_rs .
|
||||||
{% elif "armv6" in target_file %}
|
{% elif "arm32v6" in target_file %}
|
||||||
COPY --from=build /app/target/arm-unknown-linux-gnueabi/release/bitwarden_rs .
|
COPY --from=build /app/target/arm-unknown-linux-gnueabi/release/bitwarden_rs .
|
||||||
{% elif "armv7" in target_file %}
|
{% elif "arm32v7" in target_file %}
|
||||||
COPY --from=build /app/target/armv7-unknown-linux-gnueabihf/release/bitwarden_rs .
|
COPY --from=build /app/target/armv7-unknown-linux-gnueabihf/release/bitwarden_rs .
|
||||||
{% else %}
|
{% else %}
|
||||||
COPY --from=build app/target/release/bitwarden_rs .
|
COPY --from=build app/target/release/bitwarden_rs .
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
The arch-specific directory names follow the arch identifiers used by the Docker official images:
|
||||||
|
|
||||||
|
https://github.com/docker-library/official-images/blob/master/README.md#architectures-other-than-amd64
|
|
@ -0,0 +1,19 @@
|
||||||
|
The hooks in this directory are used to create multi-arch images using Docker Hub automated builds.
|
||||||
|
|
||||||
|
Docker Hub hooks provide these predefined [environment variables](https://docs.docker.com/docker-hub/builds/advanced/#environment-variables-for-building-and-testing):
|
||||||
|
|
||||||
|
* `SOURCE_BRANCH`: the name of the branch or the tag that is currently being tested.
|
||||||
|
* `SOURCE_COMMIT`: the SHA1 hash of the commit being tested.
|
||||||
|
* `COMMIT_MSG`: the message from the commit being tested and built.
|
||||||
|
* `DOCKER_REPO`: the name of the Docker repository being built.
|
||||||
|
* `DOCKERFILE_PATH`: the dockerfile currently being built.
|
||||||
|
* `DOCKER_TAG`: the Docker repository tag being built.
|
||||||
|
* `IMAGE_NAME`: the name and tag of the Docker repository being built. (This variable is a combination of `DOCKER_REPO:DOCKER_TAG`.)
|
||||||
|
|
||||||
|
The current multi-arch image build relies on the original bitwarden_rs Dockerfiles, which use cross-compilation for architectures other than `amd64`, and don't yet support all arch/database/OS combinations. However, cross-compilation is much faster than QEMU-based builds (e.g., using `docker buildx`). This situation may need to be revisited at some point.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
* https://docs.docker.com/docker-hub/builds/advanced/
|
||||||
|
* https://docs.docker.com/engine/reference/commandline/manifest/
|
||||||
|
* https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/
|
|
@ -0,0 +1,30 @@
|
||||||
|
# The default Debian-based SQLite images support these arches.
|
||||||
|
#
|
||||||
|
# Other images (Alpine-based, or with other database backends) currently
|
||||||
|
# support only a subset of these.
|
||||||
|
arches=(
|
||||||
|
amd64
|
||||||
|
arm32v6
|
||||||
|
arm32v7
|
||||||
|
arm64v8
|
||||||
|
)
|
||||||
|
|
||||||
|
case "${DOCKER_REPO}" in
|
||||||
|
*-mysql)
|
||||||
|
db=mysql
|
||||||
|
arches=(amd64)
|
||||||
|
;;
|
||||||
|
*-postgresql)
|
||||||
|
db=postgresql
|
||||||
|
arches=(amd64)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
db=sqlite
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "${DOCKER_TAG}" == *alpine ]]; then
|
||||||
|
# The Alpine build currently only works for amd64.
|
||||||
|
os_suffix=.alpine
|
||||||
|
arches=(amd64)
|
||||||
|
fi
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo ">>> Building images..."
|
||||||
|
|
||||||
|
source ./hooks/arches.sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
for arch in "${arches[@]}"; do
|
||||||
|
docker build \
|
||||||
|
-t "${DOCKER_REPO}:${DOCKER_TAG}-${arch}" \
|
||||||
|
-f docker/${arch}/${db}/Dockerfile${os_suffix} \
|
||||||
|
.
|
||||||
|
done
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo ">>> Pushing images..."
|
||||||
|
|
||||||
|
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
|
||||||
|
declare -A annotations=(
|
||||||
|
[amd64]="--os linux --arch amd64"
|
||||||
|
[arm32v6]="--os linux --arch arm --variant v6"
|
||||||
|
[arm32v7]="--os linux --arch arm --variant v7"
|
||||||
|
[arm64v8]="--os linux --arch arm64 --variant v8"
|
||||||
|
)
|
||||||
|
|
||||||
|
source ./hooks/arches.sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
declare -A images
|
||||||
|
for arch in ${arches[@]}; do
|
||||||
|
images[$arch]="${DOCKER_REPO}:${DOCKER_TAG}-${arch}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Push the images that were just built; manifest list creation fails if the
|
||||||
|
# images (manifests) referenced don't already exist in the Docker registry.
|
||||||
|
for image in "${images[@]}"; do
|
||||||
|
docker push "${image}"
|
||||||
|
done
|
||||||
|
|
||||||
|
manifest_lists=("${DOCKER_REPO}:${DOCKER_TAG}")
|
||||||
|
|
||||||
|
# If the Docker tag starts with a version number, assume the latest release is
|
||||||
|
# being pushed. Add an extra manifest (`latest-release` or `alpine-release`,
|
||||||
|
# as appropriate) to make it easier to track the latest release.
|
||||||
|
if [[ "${DOCKER_TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
||||||
|
if [[ "${DOCKER_TAG}" == *alpine ]]; then
|
||||||
|
manifest_lists+=(${DOCKER_REPO}:alpine-release)
|
||||||
|
else
|
||||||
|
manifest_lists+=(${DOCKER_REPO}:latest-release)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
for manifest_list in "${manifest_lists[@]}"; do
|
||||||
|
# Create the (multi-arch) manifest list of arch-specific images.
|
||||||
|
docker manifest create ${manifest_list} ${images[@]}
|
||||||
|
|
||||||
|
# Make sure each image manifest is annotated with the correct arch info.
|
||||||
|
# Docker does not auto-detect the arch of each cross-compiled image, so
|
||||||
|
# everything would appear as `linux/amd64` otherwise.
|
||||||
|
for arch in "${arches[@]}"; do
|
||||||
|
docker manifest annotate ${annotations[$arch]} ${manifest_list} ${images[$arch]}
|
||||||
|
done
|
||||||
|
|
||||||
|
# Push the manifest list.
|
||||||
|
docker manifest push --purge ${manifest_list}
|
||||||
|
done
|
Loading…
Reference in New Issue