From 0b2b986205dbf3c4e3aa84f80ae3db61b745b9fb Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 17 Apr 2021 13:46:38 +0200 Subject: [PATCH 1/3] [#31] Debug build is now rootless --- docker/Dockerfile.builder | 34 ++++++++++++++++++++++++++-------- docker/Dockerfile.dev | 3 ++- docker/Dockerfile.rel | 1 + fejctl | 29 ++++++++++++++++++++--------- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/docker/Dockerfile.builder b/docker/Dockerfile.builder index dc28716..4790f7c 100644 --- a/docker/Dockerfile.builder +++ b/docker/Dockerfile.builder @@ -1,17 +1,35 @@ +# vim: filetype=dockerfile # Our entire toolchain runs in alpine FROM alpine:latest AS builder -ENV PATH "$PATH:/root/.cargo/bin" +ENV PATH "$PATH:/app/.cargo/bin" # Needed for proper compiling of openssl-dev ENV RUSTFLAGS "-C target-feature=-crt-static" -WORKDIR /usr/src/app +# Add the build user +# Install dependencies +RUN addgroup -S builder && \ + adduser -S builder -G builder -h /app && \ + apk update && \ + apk add --no-cache \ + curl \ + gcc \ + libgcc \ + musl-dev \ + openssl-dev \ + postgresql-dev -# Install build dependencies, rustup & rust's nightly build & toolchain -RUN apk update && apk add --no-cache openssl-dev curl postgresql-dev libgcc musl-dev gcc && \ - { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; } && \ - rustup target add x86_64-unknown-linux-musl --toolchain nightly +# Switch to the non-root user +USER builder + +WORKDIR /app + +# Install rustup in the new user's home +# Create mountpoints for volumes with correct permissions +RUN { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly; } && \ + rustup target add x86_64-unknown-linux-musl --toolchain nightly && \ + mkdir -p .cargo/registry target # Copy source code over to builder -COPY Cargo.toml Cargo.lock ./ -COPY src/ ./src/ +COPY --chown=builder:builder Cargo.toml Cargo.lock ./ +COPY --chown=builder:builder src/ ./src/ diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index 7281bc3..28004ac 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,8 +1,9 @@ +# vim: filetype=dockerfile FROM chewingbever/fej-builder:latest ENV RUST_BACKTRACE 1 -COPY ./docker/entrypoint_dev.sh /entrypoint.sh +COPY --chown=builder:builder ./docker/entrypoint_dev.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] CMD ["run", "--bin", "server"] diff --git a/docker/Dockerfile.rel b/docker/Dockerfile.rel index e293ccc..0fa71ad 100644 --- a/docker/Dockerfile.rel +++ b/docker/Dockerfile.rel @@ -1,3 +1,4 @@ +# vim: filetype=dockerfile FROM chewingbever/fej-builder:latest AS builder # And then finally, build the project diff --git a/fejctl b/fejctl index ee4cf8e..688395c 100755 --- a/fejctl +++ b/fejctl @@ -9,18 +9,27 @@ function create_images() { # First, we build the builder DOCKER_BUILDKIT=1 docker build \ -f docker/Dockerfile.builder \ - -t "$image-builder:latest" . + -t "$image-builder:latest" . || { + >&2 echo "Failed to build builder."; + exit 1; + } if [[ "$1" = "rel" ]]; then DOCKER_BUILDKIT=1 docker build \ -t "$image:latest" \ - -f docker/Dockerfile.rel . + -f docker/Dockerfile.rel . || { + >&2 echo "Failed to build release image."; + exit 1; + } else # Then, we create the debug image DOCKER_BUILDKIT=1 docker build \ -t "$image:dev" \ - -f docker/Dockerfile.dev . + -f docker/Dockerfile.dev . || { + >&2 echo "Failed to build debug image."; + exit 1; + } fi } @@ -28,9 +37,9 @@ function create_images() { # # $@: the arguments to pass to the image (passed as arguments to cargo) function run_image() { - docker volume create fej_build-cache - docker volume create fej_registry-cache - docker volume create fej_db-data + docker volume create fej_build-cache > /dev/null + docker volume create fej_registry-cache > /dev/null + docker volume create fej_db-data > /dev/null # Run the database image docker run --rm \ @@ -54,9 +63,9 @@ function run_image() { --name fej \ --env-file .env.container \ --network fej \ - -v 'fej_build-cache:/usr/src/app/target' \ - -v 'fej_registry-cache:/root/.cargo/registry' \ - -v "$PWD/Rocket.toml:/usr/src/app/Rocket.toml:ro" \ + -v 'fej_build-cache:/app/target' \ + -v 'fej_registry-cache:/app/.cargo/registry' \ + -v "$PWD/Rocket.toml:/app/Rocket.toml:ro" \ "$image:dev" "$@" } @@ -109,6 +118,8 @@ function publish() { exit 2 fi + create_images rel + patch_version=`grep -Po '(?<=version = ").*(?=")' Cargo.toml | head -n1` major_version=`echo "$patch_version" | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1/'` minor_version=`echo "$patch_version" | sed -E 's/([0-9]+).([0-9]+).([0-9]+)/\1.\2/'` From adbe6d1fb7e566af58fb433039132ec723613b4b Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 17 Apr 2021 14:09:31 +0200 Subject: [PATCH 2/3] [#31] Release is now rootless (rip caching) --- .dockerignore | 3 +++ docker/Dockerfile.rel | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/.dockerignore b/.dockerignore index aa9bcf8..41f29f5 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,3 +9,6 @@ # Entrypoint for devop container !docker/entrypoint_dev.sh + +# Config file +!Rocket.toml diff --git a/docker/Dockerfile.rel b/docker/Dockerfile.rel index 0fa71ad..2d3672c 100644 --- a/docker/Dockerfile.rel +++ b/docker/Dockerfile.rel @@ -6,22 +6,42 @@ FROM chewingbever/fej-builder:latest AS builder # https://users.rust-lang.org/t/sigsegv-with-program-linked-against-openssl-in-an-alpine-container/52172 # TODO add what these flags do & why they work # NOTE: cargo install auto-appends bin to the path -RUN --mount=type=cache,target=/usr/src/app/target \ - --mount=type=cache,target=/root/.cargo/registry \ - cargo install \ - --path . \ - --root /usr/local \ - --target x86_64-unknown-linux-musl + +# RUN --mount=type=cache,mode=0777,target=/app/target \ +# --mount=type=cache,mode=0777,target=/app/.cargo/registry \ + +# Buildkit cache mounts really don't like it when you're not root, +# so I guess we're building release without a cache for now +RUN cargo install \ + --path . \ + --root /app/output \ + --target x86_64-unknown-linux-musl # Now, we create the actual image FROM alpine:latest # Install some dynamic libraries needed for everything to work -RUN apk update && apk add --no-cache openssl libgcc curl +# Create -non-root user +RUN apk update && \ + apk add --no-cache \ + curl \ + libgcc \ + libpq \ + openssl && \ + addgroup -S fej && \ + adduser -S fej -G fej -h /app + +# Switch to non-root user +USER fej:fej # Copy binary over to final image -COPY --from=builder /usr/local/bin/server /usr/local/bin/server +COPY --from=builder --chown=fej:fej /app/output/bin /app/bin + +# Embed config file inside container +# The workdir is changed so that the config file is read properly +WORKDIR /app +COPY --chown=fej:fej Rocket.toml /app/Rocket.toml HEALTHCHECK \ --interval=10s \ @@ -30,4 +50,4 @@ HEALTHCHECK \ --retries=3 \ CMD curl -q localhost:8000 -CMD ["/usr/local/bin/server"] +CMD ["/app/bin/server"] From 0bd09db295b96ec2dcec23fc92caf25353697f5a Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 17 Apr 2021 14:19:53 +0200 Subject: [PATCH 3/3] [#31] Config file is now copied into images --- docker/Dockerfile.dev | 1 + fejctl | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index 28004ac..ea63e1e 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -4,6 +4,7 @@ FROM chewingbever/fej-builder:latest ENV RUST_BACKTRACE 1 COPY --chown=builder:builder ./docker/entrypoint_dev.sh /entrypoint.sh +COPY --chown=builder:builder ./Rocket.toml /app/Rocket.toml ENTRYPOINT ["/entrypoint.sh"] CMD ["run", "--bin", "server"] diff --git a/fejctl b/fejctl index 688395c..879419e 100755 --- a/fejctl +++ b/fejctl @@ -65,7 +65,6 @@ function run_image() { --network fej \ -v 'fej_build-cache:/app/target' \ -v 'fej_registry-cache:/app/.cargo/registry' \ - -v "$PWD/Rocket.toml:/app/Rocket.toml:ro" \ "$image:dev" "$@" }