diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 386986f..fe32a3a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,9 +20,11 @@ variables: rules: - if: '$CI_COMMIT_BRANCH == "master"' - if: '$CI_COMMIT_BRANCH == "next"' + # TODO: Remove this after debugging + - if: '$CI_COMMIT_BRANCH == "multiarch-docker-support"' - if: '$CI_COMMIT_TAG' interruptible: true - image: "rust:latest" + image: "rust:1.56.0" tags: ["docker"] cache: paths: @@ -30,16 +32,16 @@ variables: - target/ key: "build_cache-$TARGET-release" variables: - CARGO_PROFILE_RELEASE_LTO=true - CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 + CARGO_PROFILE_RELEASE_LTO: "off" # TODO: change to true again + CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "256" # TODO: Change to 1 again + RUSTUP_HOME: "/root/.rustup" before_script: + - echo $USER + - export PATH="root/.cargo/bin:$PATH" - 'echo "Building for target $TARGET"' - 'mkdir -p cargohome && CARGOHOME="cargohome"' - "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging - - 'apt-get update -yqq' - - 'echo "Installing packages: $NEEDED_PACKAGES"' - - "apt-get install -yqq --no-install-recommends $NEEDED_PACKAGES" - - "rustup target add $TARGET" + - 'time rustup target add "$TARGET"' script: - time cargo build --target $TARGET --release - 'mv "target/$TARGET/release/conduit" "conduit-$TARGET"' @@ -57,52 +59,64 @@ build:release:cargo:x86_64-unknown-linux-gnu: - "conduit-x86_64-unknown-linux-gnu" expose_as: "Conduit for x86_64-unknown-linux-gnu" +build:release:cargo:x86_64-unknown-linux-musl: + image: registry.gitlab.fachschaften.org/jfowl/cargo-cross-for-ci/cargo-cross-builder:rust1.56.0-x86_64-unknown-linux-musl + extends: .build-cargo-shared-settings + variables: + TARGET: "x86_64-unknown-linux-musl" + artifacts: + name: "conduit-x86_64-unknown-linux-musl" + paths: + - "conduit-x86_64-unknown-linux-musl" + expose_as: "Conduit for x86_64-unknown-linux-musl" + + build:release:cargo:armv7-unknown-linux-gnueabihf: extends: .build-cargo-shared-settings + image: + name: registry.gitlab.fachschaften.org/jfowl/cargo-cross-for-ci/cargo-cross-builder:rust1.56.0-armv7-unknown-linux-gnueabihf variables: TARGET: "armv7-unknown-linux-gnueabihf" - NEEDED_PACKAGES: "build-essential gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross" - CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc - CC_armv7_unknown_linux_gnueabihf: arm-linux-gnueabihf-gcc - CXX_armv7_unknown_linux_gnueabihf: arm-linux-gnueabihf-g++ artifacts: name: "conduit-armv7-unknown-linux-gnueabihf" paths: - "conduit-armv7-unknown-linux-gnueabihf" expose_as: "Conduit for armv7-unknown-linux-gnueabihf" +build:release:cargo:armv7-unknown-linux-musleabihf: + extends: .build-cargo-shared-settings + image: + name: registry.gitlab.fachschaften.org/jfowl/cargo-cross-for-ci/cargo-cross-builder:rust1.56.0-armv7-unknown-linux-musleabihf + variables: + TARGET: "armv7-unknown-linux-musleabihf" + artifacts: + name: "conduit-armv7-unknown-linux-musleabihf" + paths: + - "conduit-armv7-unknown-linux-musleabihf" + expose_as: "Conduit for armv7-unknown-linux-musleabihf" + + build:release:cargo:aarch64-unknown-linux-gnu: + image: registry.gitlab.fachschaften.org/jfowl/cargo-cross-for-ci/cargo-cross-builder:rust1.56.0-aarch64-unknown-linux-gnu extends: .build-cargo-shared-settings variables: TARGET: "aarch64-unknown-linux-gnu" - NEEDED_PACKAGES: "build-essential gcc-10-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross" - CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc - CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc - CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++ - TARGET_CC: "/usr/bin/aarch64-linux-gnu-gcc-10" - TARGET_AR: "/usr/bin/aarch64-linux-gnu-gcc-ar-10" artifacts: name: "conduit-aarch64-unknown-linux-gnu" paths: - "conduit-aarch64-unknown-linux-gnu" expose_as: "Conduit for aarch64-unknown-linux-gnu" -build:release:cargo:x86_64-unknown-linux-musl: +build:release:cargo:aarch64-unknown-linux-musl: + image: registry.gitlab.fachschaften.org/jfowl/cargo-cross-for-ci/cargo-cross-builder:rust1.56.0-aarch64-unknown-linux-musl extends: .build-cargo-shared-settings - image: "rust:alpine" variables: - TARGET: "x86_64-unknown-linux-musl" - before_script: - - 'echo "Building for target $TARGET"' - - 'mkdir -p cargohome && CARGOHOME="cargohome"' - - "cat /etc/*-release && rustc --version && cargo --version" # Print version info for debugging - - "rustup target add $TARGET" - - "apk add libc-dev" + TARGET: "aarch64-unknown-linux-musl" artifacts: - name: "conduit-x86_64-unknown-linux-musl" + name: "conduit-aarch64-unknown-linux-musl" paths: - - "conduit-x86_64-unknown-linux-musl" - expose_as: "Conduit for x86_64-unknown-linux-musl" + - "conduit-aarch64-unknown-linux-musl" + expose_as: "Conduit for aarch64-unknown-linux-musl" @@ -213,7 +227,6 @@ build:cargo-deb:x86_64-unknown-linux-gnu: - "mkdir -p /kaniko/.docker" - 'echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"},\"$DOCKER_HUB\":{\"username\":\"$DOCKER_HUB_USER\",\"password\":\"$DOCKER_HUB_PASSWORD\"}}}" > /kaniko/.docker/config.json' - build:docker:next: extends: .docker-shared-settings needs: @@ -280,6 +293,40 @@ build:docker:tags: - if: '$CI_COMMIT_TAG' +build:docker:new-way-of-building: + stage: "build docker image" + image: jdrouet/docker-with-buildx:stable + tags: ["docker"] + services: + - docker:dind + needs: + - "build:release:cargo:x86_64-unknown-linux-musl" + rules: + - if: '$CI_COMMIT_BRANCH == "master"' + - if: '$CI_COMMIT_BRANCH == "next"' + # TODO: Remove this after debugging + - if: '$CI_COMMIT_BRANCH == "multiarch-docker-support"' + variables: + DOCKER_HOST: tcp://docker:2375/ + DOCKER_TLS_CERTDIR: "" + DOCKER_DRIVER: overlay2 + # PLATFORMS: "linux/arm/v7,linux/arm64/v8,linux/amd64" + PLATFORMS: "linux/amd64" + IMAGE_TAG: "$CI_REGISTRY_IMAGE/debug-conduit:multiarch-test-dont-use-yet" + DOCKER_FILE: "docker/ci-binaries-packaging.Dockerfile" + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + # Prepare buildx to build multiarch stuff: + - docker context create 'ci-context' + - docker buildx create --name 'multiarch-builder' --use 'ci-context' + # Copy binaries to their docker arch path + - mkdir -p linux/ && mv ./conduit-x86_64-unknown-linux-musl linux/amd64 + # Actually build multiarch image: + - docker buildx build --push --platform $PLATFORMS --tag $IMAGE_TAG --file $DOCKER_FILE . + + + # --------------------------------------------------------------------- # # Run tests # diff --git a/Dockerfile b/Dockerfile index f4b176f..56a8059 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,97 +1,52 @@ -# Using multistage build: -# https://docs.docker.com/develop/develop-images/multistage-build/ -# https://whitfin.io/speeding-up-rust-docker-builds/ - - -########################## BUILD IMAGE ########################## -# Alpine build image to build Conduit's statically compiled binary -FROM alpine:3.14 as builder - -# Install packages needed for building all crates -RUN apk add --no-cache \ - cargo \ - openssl-dev - -# Specifies if the local project is build or if Conduit gets build -# from the official git repository. Defaults to the git repo. -ARG LOCAL=false -# Specifies which revision/commit is build. Defaults to HEAD -ARG GIT_REF=origin/master - -# Copy project files from current folder -COPY . . -# Build it from the copied local files or from the official git repository -RUN if [[ $LOCAL == "true" ]]; then \ - mv ./docker/healthcheck.sh . ; \ - echo "Building from local source..." ; \ - cargo install --path . ; \ - else \ - echo "Building revision '${GIT_REF}' from online source..." ; \ - cargo install --git "https://gitlab.com/famedly/conduit.git" --rev ${GIT_REF} ; \ - echo "Loadings healthcheck script from online source..." ; \ - wget "https://gitlab.com/famedly/conduit/-/raw/${GIT_REF#origin/}/docker/healthcheck.sh" ; \ - fi - -########################## RUNTIME IMAGE ########################## -# Create new stage with a minimal image for the actual -# runtime image/container +# syntax=docker/dockerfile:1 +FROM rust:1.53-alpine as builder +WORKDIR /usr/src/conduit + +# == Build dependencies without our own code separately for caching == +# +# Need a fake main.rs since Cargo refuses to build anything otherwise. +# +# See https://github.com/rust-lang/cargo/issues/2644 for a Cargo feature +# request that would allow just dependencies to be compiled, presumably +# regardless of whether source files are available. +RUN mkdir src && echo 'fn main() {}' > src/main.rs +COPY Cargo.toml Cargo.lock ./ +RUN cargo build +# TODO: RUN cargo build --release + +# == Actual build == +RUN rm -r src +COPY src src +# main.rs has to have its timestamp updated for this to work correctly since +# otherwise the build with the fake main.rs from above is newer than the +# source files (COPY preserves timestamps). +RUN touch src/main.rs + +RUN cargo install --path . +# TODO: RUN cargo install --release --path . + + +# This build stage is going to be run later FROM alpine:3.14 -ARG CREATED -ARG VERSION -ARG GIT_REF=origin/master - -ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml" - -# Labels according to https://github.com/opencontainers/image-spec/blob/master/annotations.md -# including a custom label specifying the build command -LABEL org.opencontainers.image.created=${CREATED} \ - org.opencontainers.image.authors="Conduit Contributors" \ - org.opencontainers.image.title="Conduit" \ - org.opencontainers.image.version=${VERSION} \ - org.opencontainers.image.vendor="Conduit Contributors" \ - org.opencontainers.image.description="A Matrix homeserver written in Rust" \ - org.opencontainers.image.url="https://conduit.rs/" \ - org.opencontainers.image.revision=${GIT_REF} \ - org.opencontainers.image.source="https://gitlab.com/famedly/conduit.git" \ - org.opencontainers.image.licenses="Apache-2.0" \ - org.opencontainers.image.documentation="" \ - org.opencontainers.image.ref.name="" \ - org.label-schema.docker.build="docker build . -t matrixconduit/matrix-conduit:latest --build-arg CREATED=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg VERSION=$(grep -m1 -o '[0-9].[0-9].[0-9]' Cargo.toml)" \ - maintainer="Weasy666" - -# Standard port on which Conduit launches. You still need to map the port when using the docker command or docker-compose. -EXPOSE 6167 - -# Copy config files from context and the binary from -# the "builder" stage to the current stage into folder -# /srv/conduit and create data folder for database -RUN mkdir -p /srv/conduit/.local/share/conduit -COPY --from=builder /root/.cargo/bin/conduit /srv/conduit/ -COPY --from=builder ./healthcheck.sh /srv/conduit/ - -# Add www-data user and group with UID 82, as used by alpine -# https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install -RUN set -x ; \ - addgroup -Sg 82 www-data 2>/dev/null ; \ - adduser -S -D -H -h /srv/conduit -G www-data -g www-data www-data 2>/dev/null ; \ - addgroup www-data www-data 2>/dev/null && exit 0 ; exit 1 - -# Change ownership of Conduit files to www-data user and group -RUN chown -cR www-data:www-data /srv/conduit - # Install packages needed to run Conduit RUN apk add --no-cache \ ca-certificates \ curl \ libgcc -# Test if Conduit is still alive, uses the same endpoint as Element -HEALTHCHECK --start-period=5s --interval=60s CMD ./healthcheck.sh +# Prepare path for database and media files +RUN mkdir -p /srv/conduit/.local/share/conduit + +# TODO: Change ? or maybe leave it like that +RUN mkdir -p /srv/conduit/.local/share/conduit +COPY --from=builder /usr/local/cargo/bin/conduit /srv/conduit/ + +# TODO: Check if we don't want to just use ENVs for running condit in docker +ENV CONDUIT_CONFIG="/srv/conduit/conduit.toml" + +# TODO: not needed, but documents it? +EXPOSE 6167 -# Set user to www-data -USER www-data -# Set container home directory WORKDIR /srv/conduit -# Run Conduit -ENTRYPOINT [ "/srv/conduit/conduit" ] +ENTRYPOINT [ "/srv/conduit/conduit" ] \ No newline at end of file diff --git a/docker/ci-binaries-packaging.Dockerfile b/docker/ci-binaries-packaging.Dockerfile index fb67439..f1bbdfa 100644 --- a/docker/ci-binaries-packaging.Dockerfile +++ b/docker/ci-binaries-packaging.Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 # --------------------------------------------------------------------------------------------------------- # This Dockerfile is intended to be built as part of Conduit's CI pipeline. # It does not build Conduit in Docker, but just copies the matching build artifact from the build job. @@ -33,7 +34,7 @@ LABEL org.opencontainers.image.created=${CREATED} \ org.opencontainers.image.revision=${GIT_REF} \ org.opencontainers.image.source="https://gitlab.com/famedly/conduit.git" \ org.opencontainers.image.licenses="Apache-2.0" \ - org.opencontainers.image.documentation="" \ + org.opencontainers.image.documentation="https://gitlab.com/famedly/conduit" \ org.opencontainers.image.ref.name="" # Standard port on which Conduit launches. You still need to map the port when using the docker command or docker-compose. @@ -42,9 +43,16 @@ EXPOSE 6167 # create data folder for database RUN mkdir -p /srv/conduit/.local/share/conduit -# Copy the Conduit binary into the image at the latest possible moment to maximise caching: -COPY ./conduit-x86_64-unknown-linux-musl /srv/conduit/conduit +# Test if Conduit is still alive, uses the same endpoint as Element COPY ./docker/healthcheck.sh /srv/conduit/ +HEALTHCHECK --start-period=5s --interval=60s CMD ./healthcheck.sh + +# Copy the Conduit binary into the image at the latest possible moment to maximise caching: + +# depending on the target platform (e.g. "linux/arm/v7", "linux/arm64/v8", or "linux/amd64") +# copy the matching binary into this docker image +ARG TARGETPLATFORM +COPY ./$TARGETPLATFORM /srv/conduit/conduit # Add www-data user and group with UID 82, as used by alpine # https://git.alpinelinux.org/aports/tree/main/nginx/nginx.pre-install @@ -57,10 +65,6 @@ RUN set -x ; \ RUN chown -cR www-data:www-data /srv/conduit RUN chmod +x /srv/conduit/healthcheck.sh - -# Test if Conduit is still alive, uses the same endpoint as Element -HEALTHCHECK --start-period=5s --interval=60s CMD ./healthcheck.sh - # Set user to www-data USER www-data # Set container home directory