From ca0fd7a31b724d06ba4eca203bfeda9e38c5e767 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Mon, 13 Sep 2021 12:00:52 +0200 Subject: [PATCH] Optimize release workflow. - Split Debian and Alpine into different build matrix This starts building both Debian and Alpine based images at the same time - Make use of Docker BuildKit, which improves speed also. - Use BuildKit caching for Rust Cargo across docker images. This prevents downloading the same crates multiple times. - Use Github Actions Services to start a docker registry, starting it via the build script sometimes caused issues. - Updated the Build workflow to use Ubuntu 20.04 which is more close to the Bullseye Debian release regarding package versions. --- .github/workflows/build.yml | 45 ++----- .github/workflows/hadolint.yml | 2 +- .github/workflows/release.yml | 28 +++-- docker/Dockerfile.j2 | 109 ++++++++++------- docker/Makefile | 6 + docker/amd64/Dockerfile | 26 ++-- docker/amd64/Dockerfile.alpine | 16 ++- docker/amd64/Dockerfile.buildx | 126 +++++++++++++++++++ docker/amd64/Dockerfile.buildx.alpine | 118 ++++++++++++++++++ docker/arm64/Dockerfile | 75 +++++++----- docker/arm64/Dockerfile.buildx | 169 ++++++++++++++++++++++++++ docker/armv6/Dockerfile | 75 +++++++----- docker/armv6/Dockerfile.buildx | 169 ++++++++++++++++++++++++++ docker/armv7/Dockerfile | 75 +++++++----- docker/armv7/Dockerfile.alpine | 16 ++- docker/armv7/Dockerfile.buildx | 169 ++++++++++++++++++++++++++ docker/armv7/Dockerfile.buildx.alpine | 125 +++++++++++++++++++ hooks/build | 7 +- hooks/push | 7 +- 19 files changed, 1170 insertions(+), 193 deletions(-) create mode 100644 docker/amd64/Dockerfile.buildx create mode 100644 docker/amd64/Dockerfile.buildx.alpine create mode 100644 docker/arm64/Dockerfile.buildx create mode 100644 docker/armv6/Dockerfile.buildx create mode 100644 docker/armv7/Dockerfile.buildx create mode 100644 docker/armv7/Dockerfile.buildx.alpine diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0f80b950..f92e6e54 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,30 +31,22 @@ jobs: matrix: channel: - nightly - # - stable target-triple: - x86_64-unknown-linux-gnu - # - x86_64-unknown-linux-musl include: - target-triple: x86_64-unknown-linux-gnu host-triple: x86_64-unknown-linux-gnu features: [sqlite,mysql,postgresql] # Remember to update the `cargo test` to match the amount of features channel: nightly - os: ubuntu-18.04 + os: ubuntu-20.04 ext: "" - # - target-triple: x86_64-unknown-linux-gnu - # host-triple: x86_64-unknown-linux-gnu - # features: "sqlite,mysql,postgresql" - # channel: stable - # os: ubuntu-18.04 - # ext: "" name: Building ${{ matrix.channel }}-${{ matrix.target-triple }} runs-on: ${{ matrix.os }} steps: # Checkout the repo - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 # End Checkout the repo @@ -73,13 +65,13 @@ jobs: # Enable Rust Caching - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@842ef286fff290e445b90b4002cc9807c3669641 # v1.3.0 # End Enable Rust Caching # Uses the rust-toolchain file to determine version - name: 'Install ${{ matrix.channel }}-${{ matrix.host-triple }} for target: ${{ matrix.target-triple }}' - uses: actions-rs/toolchain@v1 + uses: actions-rs/toolchain@b2417cde72dcf67f306c0ae8e0828a81bf0b189f # v1.0.6 with: profile: minimal target: ${{ matrix.target-triple }} @@ -90,28 +82,28 @@ jobs: # Run cargo tests (In release mode to speed up future builds) # First test all features together, afterwards test them separately. - name: "`cargo test --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: test args: --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }} # Test single features # 0: sqlite - name: "`cargo test --release --features ${{ matrix.features[0] }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: test args: --release --features ${{ matrix.features[0] }} --target ${{ matrix.target-triple }} if: ${{ matrix.features[0] != '' }} # 1: mysql - name: "`cargo test --release --features ${{ matrix.features[1] }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: test args: --release --features ${{ matrix.features[1] }} --target ${{ matrix.target-triple }} if: ${{ matrix.features[1] != '' }} # 2: postgresql - name: "`cargo test --release --features ${{ matrix.features[2] }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: test args: --release --features ${{ matrix.features[2] }} --target ${{ matrix.target-triple }} @@ -121,7 +113,7 @@ jobs: # Run cargo clippy, and fail on warnings (In release mode to speed up future builds) - name: "`cargo clippy --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: clippy args: --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }} -- -D warnings @@ -130,7 +122,7 @@ jobs: # Run cargo fmt - name: '`cargo fmt`' - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: fmt args: --all -- --check @@ -139,7 +131,7 @@ jobs: # Build the binary - name: "`cargo build --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }}`" - uses: actions-rs/cargo@v1 + uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b # v1.0.1 with: command: build args: --release --features ${{ join(matrix.features, ',') }} --target ${{ matrix.target-triple }} @@ -148,21 +140,8 @@ jobs: # Upload artifact to Github Actions - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@27121b0bdffd731efa15d66772be8dc71245d074 # v2.2.4 with: name: vaultwarden-${{ matrix.target-triple }}${{ matrix.ext }} path: target/${{ matrix.target-triple }}/release/vaultwarden${{ matrix.ext }} # End Upload artifact to Github Actions - - - ## This is not used at the moment - ## We could start using this when we can build static binaries - # Upload to github actions release - # - name: Release - # uses: Shopify/upload-to-release@1 - # if: startsWith(github.ref, 'refs/tags/') - # with: - # name: vaultwarden-${{ matrix.target-triple }}${{ matrix.ext }} - # path: target/${{ matrix.target-triple }}/release/vaultwarden${{ matrix.ext }} - # repo-token: ${{ secrets.GITHUB_TOKEN }} - # End Upload to github actions release diff --git a/.github/workflows/hadolint.yml b/.github/workflows/hadolint.yml index 3a766c89..375e437a 100644 --- a/.github/workflows/hadolint.yml +++ b/.github/workflows/hadolint.yml @@ -16,7 +16,7 @@ jobs: steps: # Checkout the repo - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 # End Checkout the repo diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e8b9607..4b425c01 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Skip Duplicates Actions id: skip_check - uses: fkirc/skip-duplicate-actions@master + uses: fkirc/skip-duplicate-actions@f75dd6564bb646f95277dc8c3b80612e46a4a1ea # v3.4.1 with: cancel_others: 'true' # Only run this when not creating a tag @@ -40,23 +40,33 @@ jobs: docker-build: runs-on: ubuntu-latest needs: skip_check - if: ${{ needs.skip_check.outputs.should_skip != 'true' }} + # Start a local docker registry to be used to generate multi-arch images. + services: + registry: + image: registry:2 + ports: + - 5000:5000 env: - # DOCKER_BUILDKIT: 1 # Disabled for now, but we should look at this because it will speedup building! + DOCKER_BUILDKIT: 1 # Disabled for now, but we should look at this because it will speedup building! # DOCKER_REPO/secrets.DOCKERHUB_REPO needs to be 'index.docker.io//' DOCKER_REPO: ${{ secrets.DOCKERHUB_REPO }} SOURCE_COMMIT: ${{ github.sha }} SOURCE_REPOSITORY_URL: "https://github.com/${{ github.repository }}" + if: ${{ needs.skip_check.outputs.should_skip != 'true' && github.repository == 'dani-garcia/vaultwarden' }} + strategy: + matrix: + base_image: ["debian","alpine"] + steps: # Checkout the repo - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 with: fetch-depth: 0 # Login to Docker Hub - name: Login to Docker Hub - uses: docker/login-action@v1 + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 # v1.10.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -79,16 +89,18 @@ jobs: - name: Build Debian based images shell: bash env: - DOCKER_TAG: ${{steps.vars.outputs.DOCKER_TAG}} + DOCKER_TAG: "${{steps.vars.outputs.DOCKER_TAG}}" run: | ./hooks/build + if: ${{ matrix.base_image == 'debian' }} - name: Push Debian based images shell: bash env: - DOCKER_TAG: ${{steps.vars.outputs.DOCKER_TAG}} + DOCKER_TAG: "${{steps.vars.outputs.DOCKER_TAG}}" run: | ./hooks/push + if: ${{ matrix.base_image == 'debian' }} - name: Build Alpine based images shell: bash @@ -96,6 +108,7 @@ jobs: DOCKER_TAG: "${{steps.vars.outputs.DOCKER_TAG}}-alpine" run: | ./hooks/build + if: ${{ matrix.base_image == 'alpine' }} - name: Push Alpine based images shell: bash @@ -103,3 +116,4 @@ jobs: DOCKER_TAG: "${{steps.vars.outputs.DOCKER_TAG}}-alpine" run: | ./hooks/push + if: ${{ matrix.base_image == 'alpine' }} diff --git a/docker/Dockerfile.j2 b/docker/Dockerfile.j2 index 1fc83996..2a849a5b 100644 --- a/docker/Dockerfile.j2 +++ b/docker/Dockerfile.j2 @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -40,6 +42,11 @@ {% else %} {% set package_arch_target_param = "" %} {% endif %} +{% if "buildx" in target_file %} +{% set mount_rust_cache = "--mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry " %} +{% else %} +{% set mount_rust_cache = "" %} +{% endif %} # Using multistage build: # https://docs.docker.com/develop/develop-images/multistage-build/ # https://whitfin.io/speeding-up-rust-docker-builds/ @@ -86,22 +93,39 @@ ARG DB=sqlite,mysql,postgresql {% endif %} # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal +{# {% if "alpine" not in target_file and "buildx" in target_file %} +# Debian based Buildx builds can use some special apt caching to speedup building. +# By default Debian based images have some rules to keep docker builds clean, we need to remove this. +# See: https://hub.docker.com/r/docker/dockerfile +RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache +{% endif %} #} + +# Create CARGO_HOME folder and don't download rust docs +RUN {{ mount_rust_cache -}} mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal {% if "alpine" in target_file %} -ENV USER "root" ENV RUSTFLAGS='-C link-arg=-s' {% if "armv7" in target_file %} ENV CFLAGS_armv7_unknown_linux_musleabihf="-mfpu=vfpv3-d16" {% endif %} {% elif "arm" in target_file %} +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the {{ package_arch_prefix }} version. +# What we can do is a force install, because nothing important is overlapping each other. +# # Install required build libs for {{ package_arch_name }} architecture. # To compile both mysql and postgresql we need some extra packages for both host arch and target arch -RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ - /etc/apt/sources.list.d/deb-src.list \ +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ && dpkg --add-architecture {{ package_arch_name }} \ && apt-get update \ && apt-get install -y \ @@ -110,24 +134,43 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ libc6-dev{{ package_arch_prefix }} \ libpq5{{ package_arch_prefix }} \ libpq-dev \ + libmariadb3:amd64 \ libmariadb-dev{{ package_arch_prefix }} \ libmariadb-dev-compat{{ package_arch_prefix }} \ gcc-{{ package_cross_compiler }} \ - && mkdir -p ~/.cargo \ - && echo '[target.{{ package_arch_target }}]' >> ~/.cargo/config \ - && echo 'linker = "{{ package_cross_compiler }}-gcc"' >> ~/.cargo/config \ - && echo 'rustflags = ["-L/usr/lib/{{ package_cross_compiler }}"]' >> ~/.cargo/config + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5{{ package_arch_prefix }} package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/{{ package_cross_compiler }}/libpq.so.5 /usr/lib/{{ package_cross_compiler }}/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.{{ package_arch_target }}]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "{{ package_cross_compiler }}-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/{{ package_cross_compiler }}"]' >> "${CARGO_HOME}/config" -ENV CARGO_HOME "/root/.cargo" -ENV USER "root" -{% endif -%} +# Set arm specific environment values +ENV CC_{{ package_arch_target | replace("-", "_") }}="/usr/bin/{{ package_cross_compiler }}-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/{{ package_cross_compiler }}" +ENV OPENSSL_LIB_DIR="/usr/lib/{{ package_cross_compiler }}" -{% if "amd64" in target_file and "alpine" not in target_file %} +{% elif "amd64" in target_file %} # Install DB packages -RUN apt-get update && apt-get install -y \ - --no-install-recommends \ - libmariadb-dev{{ package_arch_prefix }} \ - libpq-dev{{ package_arch_prefix }} \ +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libmariadb-dev{{ package_arch_prefix }} \ + libpq-dev{{ package_arch_prefix }} \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* {% endif %} @@ -140,37 +183,14 @@ COPY ./Cargo.* ./ COPY ./rust-toolchain ./rust-toolchain COPY ./build.rs ./build.rs -{% if "alpine" not in target_file %} -{% if "arm" in target_file %} -# NOTE: This should be the last apt-get/dpkg for this stage, since after this it will fail because of broken dependencies. -# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. -# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) -# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the {{ package_arch_prefix }} version. -# What we can do is a force install, because nothing important is overlapping each other. -RUN apt-get install -y --no-install-recommends libmariadb3:amd64 \ - && apt-get download libmariadb-dev-compat:amd64 \ - && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ - && rm -rvf ./libmariadb-dev-compat*.deb \ - # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. - # The libpq5{{ package_arch_prefix }} package seems to not provide a symlink to libpq.so.5 with the name libpq.so. - # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. - # Without this specific file the ld command will fail and compilation fails with it. - && ln -sfnr /usr/lib/{{ package_cross_compiler }}/libpq.so.5 /usr/lib/{{ package_cross_compiler }}/libpq.so - -ENV CC_{{ package_arch_target | replace("-", "_") }}="/usr/bin/{{ package_cross_compiler }}-gcc" -ENV CROSS_COMPILE="1" -ENV OPENSSL_INCLUDE_DIR="/usr/include/{{ package_cross_compiler }}" -ENV OPENSSL_LIB_DIR="/usr/lib/{{ package_cross_compiler }}" -{% endif -%} -{% endif %} {% if package_arch_target is defined %} -RUN rustup target add {{ package_arch_target }} +RUN {{ mount_rust_cache -}} rustup target add {{ package_arch_target }} {% endif %} # Builds your dependencies and removes the # dummy project, except the target folder # This folder contains the compiled dependencies -RUN cargo build --features ${DB} --release{{ package_arch_target_param }} \ +RUN {{ mount_rust_cache -}} cargo build --features ${DB} --release{{ package_arch_target_param }} \ && find . -not -path "./target*" -delete # Copies the complete project @@ -182,7 +202,7 @@ RUN touch src/main.rs # Builds again, this time it'll just be # your actual source files being built -RUN cargo build --features ${DB} --release{{ package_arch_target_param }} +RUN {{ mount_rust_cache -}} cargo build --features ${DB} --release{{ package_arch_target_param }} {% if "alpine" in target_file %} {% if "armv7" in target_file %} # hadolint ignore=DL3059 @@ -231,6 +251,7 @@ RUN mkdir /data \ dumb-init \ libmariadb-dev-compat \ libpq5 \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* {% endif %} diff --git a/docker/Makefile b/docker/Makefile index 86b3b64c..8c939cba 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -7,3 +7,9 @@ all: $(OBJECTS) %/Dockerfile.alpine: Dockerfile.j2 render_template ./render_template "$<" "{\"target_file\":\"$@\"}" > "$@" + +%/Dockerfile.buildx: Dockerfile.j2 render_template + ./render_template "$<" "{\"target_file\":\"$@\"}" > "$@" + +%/Dockerfile.buildx.alpine: Dockerfile.j2 render_template + ./render_template "$<" "{\"target_file\":\"$@\"}" > "$@" diff --git a/docker/amd64/Dockerfile b/docker/amd64/Dockerfile index 8f448ccc..6769ef4f 100644 --- a/docker/amd64/Dockerfile +++ b/docker/amd64/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -31,16 +33,25 @@ FROM rust:1.54-bullseye as build ARG DB=sqlite,mysql,postgresql # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal + +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal # Install DB packages -RUN apt-get update && apt-get install -y \ - --no-install-recommends \ - libmariadb-dev \ - libpq-dev \ +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libmariadb-dev \ + libpq-dev \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* # Creates a dummy project used to grab dependencies @@ -90,6 +101,7 @@ RUN mkdir /data \ dumb-init \ libmariadb-dev-compat \ libpq5 \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* diff --git a/docker/amd64/Dockerfile.alpine b/docker/amd64/Dockerfile.alpine index 64963b99..9ac4dc38 100644 --- a/docker/amd64/Dockerfile.alpine +++ b/docker/amd64/Dockerfile.alpine @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -31,12 +33,18 @@ FROM clux/muslrust:nightly-2021-08-22 as build ARG DB=sqlite,postgresql # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal -ENV USER "root" +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + ENV RUSTFLAGS='-C link-arg=-s' # Creates a dummy project used to grab dependencies diff --git a/docker/amd64/Dockerfile.buildx b/docker/amd64/Dockerfile.buildx new file mode 100644 index 00000000..a4aa826a --- /dev/null +++ b/docker/amd64/Dockerfile.buildx @@ -0,0 +1,126 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM rust:1.54-bullseye as build + +# Debian-based builds support multidb +ARG DB=sqlite,mysql,postgresql + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# Install DB packages +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libmariadb-dev \ + libpq-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM debian:bullseye-slim + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 + + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apt-get update && apt-get install -y \ + --no-install-recommends \ + openssl \ + ca-certificates \ + curl \ + dumb-init \ + libmariadb-dev-compat \ + libpq5 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/docker/amd64/Dockerfile.buildx.alpine b/docker/amd64/Dockerfile.buildx.alpine new file mode 100644 index 00000000..ca666c1a --- /dev/null +++ b/docker/amd64/Dockerfile.buildx.alpine @@ -0,0 +1,118 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM clux/muslrust:nightly-2021-08-22 as build + +# Alpine-based AMD64 (musl) does not support mysql/mariadb during compile time. +ARG DB=sqlite,postgresql + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +ENV RUSTFLAGS='-C link-arg=-s' + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry rustup target add x86_64-unknown-linux-musl + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=x86_64-unknown-linux-musl \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=x86_64-unknown-linux-musl + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM alpine:3.14 + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 +ENV SSL_CERT_DIR=/etc/ssl/certs + + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apk add --no-cache \ + openssl \ + tzdata \ + curl \ + dumb-init \ + postgresql-libs \ + ca-certificates + + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/x86_64-unknown-linux-musl/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/docker/arm64/Dockerfile b/docker/arm64/Dockerfile index ddda4f98..3e019ba6 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -31,15 +33,27 @@ FROM rust:1.54-bullseye as build ARG DB=sqlite,mysql,postgresql # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :arm64 version. +# What we can do is a force install, because nothing important is overlapping each other. +# # Install required build libs for arm64 architecture. # To compile both mysql and postgresql we need some extra packages for both host arch and target arch -RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ - /etc/apt/sources.list.d/deb-src.list \ +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ && dpkg --add-architecture arm64 \ && apt-get update \ && apt-get install -y \ @@ -48,16 +62,35 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ libc6-dev:arm64 \ libpq5:arm64 \ libpq-dev \ + libmariadb3:amd64 \ libmariadb-dev:arm64 \ libmariadb-dev-compat:arm64 \ gcc-aarch64-linux-gnu \ - && mkdir -p ~/.cargo \ - && echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config \ - && echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config \ - && echo 'rustflags = ["-L/usr/lib/aarch64-linux-gnu"]' >> ~/.cargo/config + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:arm64 package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/aarch64-linux-gnu/libpq.so.5 /usr/lib/aarch64-linux-gnu/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.aarch64-unknown-linux-gnu]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "aarch64-linux-gnu-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/aarch64-linux-gnu"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/aarch64-linux-gnu" +ENV OPENSSL_LIB_DIR="/usr/lib/aarch64-linux-gnu" -ENV CARGO_HOME "/root/.cargo" -ENV USER "root" # Creates a dummy project used to grab dependencies RUN USER=root cargo new --bin /app @@ -68,25 +101,6 @@ COPY ./Cargo.* ./ COPY ./rust-toolchain ./rust-toolchain COPY ./build.rs ./build.rs -# NOTE: This should be the last apt-get/dpkg for this stage, since after this it will fail because of broken dependencies. -# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. -# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) -# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :arm64 version. -# What we can do is a force install, because nothing important is overlapping each other. -RUN apt-get install -y --no-install-recommends libmariadb3:amd64 \ - && apt-get download libmariadb-dev-compat:amd64 \ - && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ - && rm -rvf ./libmariadb-dev-compat*.deb \ - # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. - # The libpq5:arm64 package seems to not provide a symlink to libpq.so.5 with the name libpq.so. - # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. - # Without this specific file the ld command will fail and compilation fails with it. - && ln -sfnr /usr/lib/aarch64-linux-gnu/libpq.so.5 /usr/lib/aarch64-linux-gnu/libpq.so - -ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc" -ENV CROSS_COMPILE="1" -ENV OPENSSL_INCLUDE_DIR="/usr/include/aarch64-linux-gnu" -ENV OPENSSL_LIB_DIR="/usr/lib/aarch64-linux-gnu" RUN rustup target add aarch64-unknown-linux-gnu # Builds your dependencies and removes the @@ -128,6 +142,7 @@ RUN mkdir /data \ dumb-init \ libmariadb-dev-compat \ libpq5 \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* # hadolint ignore=DL3059 diff --git a/docker/arm64/Dockerfile.buildx b/docker/arm64/Dockerfile.buildx new file mode 100644 index 00000000..afbdd46d --- /dev/null +++ b/docker/arm64/Dockerfile.buildx @@ -0,0 +1,169 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM rust:1.54-bullseye as build + +# Debian-based builds support multidb +ARG DB=sqlite,mysql,postgresql + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :arm64 version. +# What we can do is a force install, because nothing important is overlapping each other. +# +# Install required build libs for arm64 architecture. +# To compile both mysql and postgresql we need some extra packages for both host arch and target arch +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ + && dpkg --add-architecture arm64 \ + && apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libssl-dev:arm64 \ + libc6-dev:arm64 \ + libpq5:arm64 \ + libpq-dev \ + libmariadb3:amd64 \ + libmariadb-dev:arm64 \ + libmariadb-dev-compat:arm64 \ + gcc-aarch64-linux-gnu \ + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:arm64 package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/aarch64-linux-gnu/libpq.so.5 /usr/lib/aarch64-linux-gnu/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.aarch64-unknown-linux-gnu]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "aarch64-linux-gnu-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/aarch64-linux-gnu"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/aarch64-linux-gnu" +ENV OPENSSL_LIB_DIR="/usr/lib/aarch64-linux-gnu" + + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry rustup target add aarch64-unknown-linux-gnu + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=aarch64-unknown-linux-gnu \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=aarch64-unknown-linux-gnu + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM balenalib/aarch64-debian:bullseye + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 + +# hadolint ignore=DL3059 +RUN [ "cross-build-start" ] + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apt-get update && apt-get install -y \ + --no-install-recommends \ + openssl \ + ca-certificates \ + curl \ + dumb-init \ + libmariadb-dev-compat \ + libpq5 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# hadolint ignore=DL3059 +RUN [ "cross-build-end" ] + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/aarch64-unknown-linux-gnu/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/docker/armv6/Dockerfile b/docker/armv6/Dockerfile index 1935517f..a5d1693b 100644 --- a/docker/armv6/Dockerfile +++ b/docker/armv6/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -31,15 +33,27 @@ FROM rust:1.54-bullseye as build ARG DB=sqlite,mysql,postgresql # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armel version. +# What we can do is a force install, because nothing important is overlapping each other. +# # Install required build libs for armel architecture. # To compile both mysql and postgresql we need some extra packages for both host arch and target arch -RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ - /etc/apt/sources.list.d/deb-src.list \ +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ && dpkg --add-architecture armel \ && apt-get update \ && apt-get install -y \ @@ -48,16 +62,35 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ libc6-dev:armel \ libpq5:armel \ libpq-dev \ + libmariadb3:amd64 \ libmariadb-dev:armel \ libmariadb-dev-compat:armel \ gcc-arm-linux-gnueabi \ - && mkdir -p ~/.cargo \ - && echo '[target.arm-unknown-linux-gnueabi]' >> ~/.cargo/config \ - && echo 'linker = "arm-linux-gnueabi-gcc"' >> ~/.cargo/config \ - && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabi"]' >> ~/.cargo/config + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:armel package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/arm-linux-gnueabi/libpq.so.5 /usr/lib/arm-linux-gnueabi/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.arm-unknown-linux-gnueabi]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "arm-linux-gnueabi-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabi"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabi" +ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabi" -ENV CARGO_HOME "/root/.cargo" -ENV USER "root" # Creates a dummy project used to grab dependencies RUN USER=root cargo new --bin /app @@ -68,25 +101,6 @@ COPY ./Cargo.* ./ COPY ./rust-toolchain ./rust-toolchain COPY ./build.rs ./build.rs -# NOTE: This should be the last apt-get/dpkg for this stage, since after this it will fail because of broken dependencies. -# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. -# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) -# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armel version. -# What we can do is a force install, because nothing important is overlapping each other. -RUN apt-get install -y --no-install-recommends libmariadb3:amd64 \ - && apt-get download libmariadb-dev-compat:amd64 \ - && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ - && rm -rvf ./libmariadb-dev-compat*.deb \ - # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. - # The libpq5:armel package seems to not provide a symlink to libpq.so.5 with the name libpq.so. - # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. - # Without this specific file the ld command will fail and compilation fails with it. - && ln -sfnr /usr/lib/arm-linux-gnueabi/libpq.so.5 /usr/lib/arm-linux-gnueabi/libpq.so - -ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc" -ENV CROSS_COMPILE="1" -ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabi" -ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabi" RUN rustup target add arm-unknown-linux-gnueabi # Builds your dependencies and removes the @@ -128,6 +142,7 @@ RUN mkdir /data \ dumb-init \ libmariadb-dev-compat \ libpq5 \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* # hadolint ignore=DL3059 diff --git a/docker/armv6/Dockerfile.buildx b/docker/armv6/Dockerfile.buildx new file mode 100644 index 00000000..5d7dc057 --- /dev/null +++ b/docker/armv6/Dockerfile.buildx @@ -0,0 +1,169 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM rust:1.54-bullseye as build + +# Debian-based builds support multidb +ARG DB=sqlite,mysql,postgresql + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armel version. +# What we can do is a force install, because nothing important is overlapping each other. +# +# Install required build libs for armel architecture. +# To compile both mysql and postgresql we need some extra packages for both host arch and target arch +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ + && dpkg --add-architecture armel \ + && apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libssl-dev:armel \ + libc6-dev:armel \ + libpq5:armel \ + libpq-dev \ + libmariadb3:amd64 \ + libmariadb-dev:armel \ + libmariadb-dev-compat:armel \ + gcc-arm-linux-gnueabi \ + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:armel package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/arm-linux-gnueabi/libpq.so.5 /usr/lib/arm-linux-gnueabi/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.arm-unknown-linux-gnueabi]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "arm-linux-gnueabi-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabi"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_arm_unknown_linux_gnueabi="/usr/bin/arm-linux-gnueabi-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabi" +ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabi" + + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry rustup target add arm-unknown-linux-gnueabi + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=arm-unknown-linux-gnueabi \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=arm-unknown-linux-gnueabi + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM balenalib/rpi-debian:bullseye + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 + +# hadolint ignore=DL3059 +RUN [ "cross-build-start" ] + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apt-get update && apt-get install -y \ + --no-install-recommends \ + openssl \ + ca-certificates \ + curl \ + dumb-init \ + libmariadb-dev-compat \ + libpq5 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# hadolint ignore=DL3059 +RUN [ "cross-build-end" ] + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/arm-unknown-linux-gnueabi/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/docker/armv7/Dockerfile b/docker/armv7/Dockerfile index 9172b90e..9a168f65 100644 --- a/docker/armv7/Dockerfile +++ b/docker/armv7/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -31,15 +33,27 @@ FROM rust:1.54-bullseye as build ARG DB=sqlite,mysql,postgresql # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armhf version. +# What we can do is a force install, because nothing important is overlapping each other. +# # Install required build libs for armhf architecture. # To compile both mysql and postgresql we need some extra packages for both host arch and target arch -RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ - /etc/apt/sources.list.d/deb-src.list \ +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ && dpkg --add-architecture armhf \ && apt-get update \ && apt-get install -y \ @@ -48,16 +62,35 @@ RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > \ libc6-dev:armhf \ libpq5:armhf \ libpq-dev \ + libmariadb3:amd64 \ libmariadb-dev:armhf \ libmariadb-dev-compat:armhf \ gcc-arm-linux-gnueabihf \ - && mkdir -p ~/.cargo \ - && echo '[target.armv7-unknown-linux-gnueabihf]' >> ~/.cargo/config \ - && echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config \ - && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabihf"]' >> ~/.cargo/config + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:armhf package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/arm-linux-gnueabihf/libpq.so.5 /usr/lib/arm-linux-gnueabihf/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.armv7-unknown-linux-gnueabihf]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "arm-linux-gnueabihf-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabihf"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf" +ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf" -ENV CARGO_HOME "/root/.cargo" -ENV USER "root" # Creates a dummy project used to grab dependencies RUN USER=root cargo new --bin /app @@ -68,25 +101,6 @@ COPY ./Cargo.* ./ COPY ./rust-toolchain ./rust-toolchain COPY ./build.rs ./build.rs -# NOTE: This should be the last apt-get/dpkg for this stage, since after this it will fail because of broken dependencies. -# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. -# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) -# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armhf version. -# What we can do is a force install, because nothing important is overlapping each other. -RUN apt-get install -y --no-install-recommends libmariadb3:amd64 \ - && apt-get download libmariadb-dev-compat:amd64 \ - && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ - && rm -rvf ./libmariadb-dev-compat*.deb \ - # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. - # The libpq5:armhf package seems to not provide a symlink to libpq.so.5 with the name libpq.so. - # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. - # Without this specific file the ld command will fail and compilation fails with it. - && ln -sfnr /usr/lib/arm-linux-gnueabihf/libpq.so.5 /usr/lib/arm-linux-gnueabihf/libpq.so - -ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc" -ENV CROSS_COMPILE="1" -ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf" -ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf" RUN rustup target add armv7-unknown-linux-gnueabihf # Builds your dependencies and removes the @@ -128,6 +142,7 @@ RUN mkdir /data \ dumb-init \ libmariadb-dev-compat \ libpq5 \ + && apt-get clean \ && rm -rf /var/lib/apt/lists/* # hadolint ignore=DL3059 diff --git a/docker/armv7/Dockerfile.alpine b/docker/armv7/Dockerfile.alpine index a6ca1582..f78168cf 100644 --- a/docker/armv7/Dockerfile.alpine +++ b/docker/armv7/Dockerfile.alpine @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + # This file was generated using a Jinja2 template. # Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. @@ -32,12 +34,18 @@ FROM messense/rust-musl-cross:armv7-musleabihf as build ARG DB=sqlite,vendored_openssl # Build time options to avoid dpkg warnings and help with reproducible builds. -ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" -# Don't download rust docs -RUN rustup set profile minimal -ENV USER "root" +# Create CARGO_HOME folder and don't download rust docs +RUN mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + ENV RUSTFLAGS='-C link-arg=-s' ENV CFLAGS_armv7_unknown_linux_musleabihf="-mfpu=vfpv3-d16" diff --git a/docker/armv7/Dockerfile.buildx b/docker/armv7/Dockerfile.buildx new file mode 100644 index 00000000..938abd58 --- /dev/null +++ b/docker/armv7/Dockerfile.buildx @@ -0,0 +1,169 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM rust:1.54-bullseye as build + +# Debian-based builds support multidb +ARG DB=sqlite,mysql,postgresql + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +# NOTE: Any apt-get/dpkg after this stage will fail because of broken dependencies. +# For Diesel-RS migrations_macros to compile with MySQL/MariaDB we need to do some magic. +# We at least need libmariadb3:amd64 installed for the x86_64 version of libmariadb.so (client) +# We also need the libmariadb-dev-compat:amd64 but it can not be installed together with the :armhf version. +# What we can do is a force install, because nothing important is overlapping each other. +# +# Install required build libs for armhf architecture. +# To compile both mysql and postgresql we need some extra packages for both host arch and target arch +RUN sed 's/^deb/deb-src/' /etc/apt/sources.list > /etc/apt/sources.list.d/deb-src.list \ + && dpkg --add-architecture armhf \ + && apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libssl-dev:armhf \ + libc6-dev:armhf \ + libpq5:armhf \ + libpq-dev \ + libmariadb3:amd64 \ + libmariadb-dev:armhf \ + libmariadb-dev-compat:armhf \ + gcc-arm-linux-gnueabihf \ + # + # Manual install libmariadb-dev-compat:amd64 ( After this broken dependencies will break apt ) + && apt-get download libmariadb-dev-compat:amd64 \ + && dpkg --force-all -i ./libmariadb-dev-compat*.deb \ + && rm -rvf ./libmariadb-dev-compat*.deb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + # + # For Diesel-RS migrations_macros to compile with PostgreSQL we need to do some magic. + # The libpq5:armhf package seems to not provide a symlink to libpq.so.5 with the name libpq.so. + # This is only provided by the libpq-dev package which can't be installed for both arch at the same time. + # Without this specific file the ld command will fail and compilation fails with it. + && ln -sfnr /usr/lib/arm-linux-gnueabihf/libpq.so.5 /usr/lib/arm-linux-gnueabihf/libpq.so \ + # + # Make sure cargo has the right target config + && echo '[target.armv7-unknown-linux-gnueabihf]' >> "${CARGO_HOME}/config" \ + && echo 'linker = "arm-linux-gnueabihf-gcc"' >> "${CARGO_HOME}/config" \ + && echo 'rustflags = ["-L/usr/lib/arm-linux-gnueabihf"]' >> "${CARGO_HOME}/config" + +# Set arm specific environment values +ENV CC_armv7_unknown_linux_gnueabihf="/usr/bin/arm-linux-gnueabihf-gcc" +ENV CROSS_COMPILE="1" +ENV OPENSSL_INCLUDE_DIR="/usr/include/arm-linux-gnueabihf" +ENV OPENSSL_LIB_DIR="/usr/lib/arm-linux-gnueabihf" + + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry rustup target add armv7-unknown-linux-gnueabihf + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=armv7-unknown-linux-gnueabihf \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=armv7-unknown-linux-gnueabihf + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM balenalib/armv7hf-debian:bullseye + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 + +# hadolint ignore=DL3059 +RUN [ "cross-build-start" ] + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apt-get update && apt-get install -y \ + --no-install-recommends \ + openssl \ + ca-certificates \ + curl \ + dumb-init \ + libmariadb-dev-compat \ + libpq5 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# hadolint ignore=DL3059 +RUN [ "cross-build-end" ] + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/armv7-unknown-linux-gnueabihf/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/docker/armv7/Dockerfile.buildx.alpine b/docker/armv7/Dockerfile.buildx.alpine new file mode 100644 index 00000000..8b72d1d3 --- /dev/null +++ b/docker/armv7/Dockerfile.buildx.alpine @@ -0,0 +1,125 @@ +# syntax=docker/dockerfile:1 + +# This file was generated using a Jinja2 template. +# Please make your changes in `Dockerfile.j2` and then `make` the individual Dockerfiles. + +# Using multistage build: +# https://docs.docker.com/develop/develop-images/multistage-build/ +# https://whitfin.io/speeding-up-rust-docker-builds/ +####################### VAULT BUILD IMAGE ####################### +# The web-vault digest specifies a particular web-vault build on Docker Hub. +# Using the digest instead of the tag name provides better security, +# as the digest of an image is immutable, whereas a tag name can later +# be changed to point to a malicious image. +# +# To verify the current digest for a given tag name: +# - From https://hub.docker.com/r/vaultwarden/web-vault/tags, +# click the tag name to view the digest of the image it currently points to. +# - From the command line: +# $ docker pull vaultwarden/web-vault:v2.21.1 +# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1 +# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5] +# +# - Conversely, to get the tag name from the digest: +# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 +# [vaultwarden/web-vault:v2.21.1] +# +FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault + +########################## BUILD IMAGE ########################## +FROM messense/rust-musl-cross:armv7-musleabihf as build + +# Alpine-based ARM (musl) only supports sqlite during compile time. +# We now also need to add vendored_openssl, because the current base image we use to build has OpenSSL removed. +ARG DB=sqlite,vendored_openssl + +# Build time options to avoid dpkg warnings and help with reproducible builds. +ENV DEBIAN_FRONTEND=noninteractive \ + LANG=C.UTF-8 \ + TZ=UTC \ + TERM=xterm-256color \ + CARGO_HOME="/root/.cargo" \ + USER="root" + + +# Create CARGO_HOME folder and don't download rust docs +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry mkdir -pv "${CARGO_HOME}" \ + && rustup set profile minimal + +ENV RUSTFLAGS='-C link-arg=-s' +ENV CFLAGS_armv7_unknown_linux_musleabihf="-mfpu=vfpv3-d16" + +# Creates a dummy project used to grab dependencies +RUN USER=root cargo new --bin /app +WORKDIR /app + +# Copies over *only* your manifests and build files +COPY ./Cargo.* ./ +COPY ./rust-toolchain ./rust-toolchain +COPY ./build.rs ./build.rs + +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry rustup target add armv7-unknown-linux-musleabihf + +# Builds your dependencies and removes the +# dummy project, except the target folder +# This folder contains the compiled dependencies +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=armv7-unknown-linux-musleabihf \ + && find . -not -path "./target*" -delete + +# Copies the complete project +# To avoid copying unneeded files, use .dockerignore +COPY . . + +# Make sure that we actually build the project +RUN touch src/main.rs + +# Builds again, this time it'll just be +# your actual source files being built +RUN --mount=type=cache,target=/root/.cargo/git --mount=type=cache,target=/root/.cargo/registry cargo build --features ${DB} --release --target=armv7-unknown-linux-musleabihf +# hadolint ignore=DL3059 +RUN musl-strip target/armv7-unknown-linux-musleabihf/release/vaultwarden + +######################## RUNTIME IMAGE ######################## +# Create a new stage with a minimal image +# because we already have a binary built +FROM balenalib/armv7hf-alpine:3.14 + +ENV ROCKET_ENV "staging" +ENV ROCKET_PORT=80 +ENV ROCKET_WORKERS=10 +ENV SSL_CERT_DIR=/etc/ssl/certs + +# hadolint ignore=DL3059 +RUN [ "cross-build-start" ] + +# Create data folder and Install needed libraries +RUN mkdir /data \ + && apk add --no-cache \ + openssl \ + tzdata \ + curl \ + dumb-init \ + ca-certificates + +# hadolint ignore=DL3059 +RUN [ "cross-build-end" ] + +VOLUME /data +EXPOSE 80 +EXPOSE 3012 + +# Copies the files from the context (Rocket.toml file and web-vault) +# and the binary from the "build" stage to the current stage +WORKDIR / +COPY Rocket.toml . +COPY --from=vault /web-vault ./web-vault +COPY --from=build /app/target/armv7-unknown-linux-musleabihf/release/vaultwarden . + +COPY docker/healthcheck.sh /healthcheck.sh +COPY docker/start.sh /start.sh + +HEALTHCHECK --interval=60s --timeout=10s CMD ["/healthcheck.sh"] + +# Configures the startup! +ENTRYPOINT ["/usr/bin/dumb-init", "--"] +CMD ["/start.sh"] diff --git a/hooks/build b/hooks/build index f18c58bf..96f04d15 100755 --- a/hooks/build +++ b/hooks/build @@ -34,12 +34,17 @@ for label in "${LABELS[@]}"; do LABEL_ARGS+=(--label "${label}") done +# Check if DOCKER_BUILDKIT is set, if so, use the Dockerfile.buildx as template +if [[ -n "${DOCKER_BUILDKIT}" ]]; then + buildx_suffix=.buildx +fi + set -ex for arch in "${arches[@]}"; do docker build \ "${LABEL_ARGS[@]}" \ -t "${DOCKER_REPO}:${DOCKER_TAG}-${arch}" \ - -f docker/${arch}/Dockerfile${distro_suffix} \ + -f docker/${arch}/Dockerfile${buildx_suffix}${distro_suffix} \ . done diff --git a/hooks/push b/hooks/push index 4c690eb0..de8d24e8 100755 --- a/hooks/push +++ b/hooks/push @@ -10,7 +10,7 @@ join() { local IFS="$1"; shift; echo "$*"; } set -ex -echo ">>> Starting local Docker registry..." +echo ">>> Starting local Docker registry when needed..." # Docker Buildx's `docker-container` driver is needed for multi-platform # builds, but it can't access existing images on the Docker host (like the @@ -28,7 +28,10 @@ echo ">>> Starting local Docker registry..." # First check if there already is a registry container running, else skip it. # This will only happen either locally or running it via Github Actions # -docker start registry > /dev/null 2>&1 || docker run -d --name registry --network host registry:2 # defaults to port 5000 +if ! timeout 5 bash -c 'cat < /dev/null > /dev/tcp/localhost/5000'; then + # defaults to port 5000 + docker run -d --name registry --network host registry:2 +fi # Docker Hub sets a `DOCKER_REPO` env var with the format `index.docker.io/user/repo`. # Strip the registry portion to construct a local repo path for use in `Dockerfile.buildx`.