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.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..ea63e1e 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -1,8 +1,10 @@ +# 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 +COPY --chown=builder:builder ./Rocket.toml /app/Rocket.toml ENTRYPOINT ["/entrypoint.sh"] CMD ["run", "--bin", "server"] diff --git a/docker/Dockerfile.rel b/docker/Dockerfile.rel index e293ccc..2d3672c 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 @@ -5,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 \ @@ -29,4 +50,4 @@ HEALTHCHECK \ --retries=3 \ CMD curl -q localhost:8000 -CMD ["/usr/local/bin/server"] +CMD ["/app/bin/server"] diff --git a/fejctl b/fejctl index ee4cf8e..879419e 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,8 @@ 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' \ "$image:dev" "$@" } @@ -109,6 +117,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/'`