diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c5fa336 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,69 @@ +ARG RUST_VERSION=1.94.1 +ARG APP_NAME=mnemosyne + +################################################################################ +# Create a stage for building the application. + +FROM rust:${RUST_VERSION}-alpine AS build +ARG APP_NAME +WORKDIR /app +ENV IN_DOCKER=true + +# Install host build dependencies. +RUN apk add --no-cache clang lld musl-dev git + +# Build the application. +# Leverage a cache mount to /usr/local/cargo/registry/ +# for downloaded dependencies, a cache mount to /usr/local/cargo/git/db +# for git repository dependencies, and a cache mount to /app/target/ for +# compiled dependencies which will speed up subsequent builds. +# Leverage a bind mount to the src directory to avoid having to copy the +# source code into the container. Once built, copy the executable to an +# output directory before the cache mounted /app/target is unmounted. +RUN --mount=type=bind,source=src,target=src \ + --mount=type=bind,source=web,target=web \ + --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ + --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ + --mount=type=cache,target=/app/target/ \ + --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/usr/local/cargo/registry/ \ + cargo build --locked --release && \ + cp ./target/release/$APP_NAME /bin/server + +################################################################################ +# Create a new stage for running the application that contains the minimal +# runtime dependencies for the application. This often uses a different base +# image from the build stage where the necessary files are copied from the build +# stage. +# +# The example below uses the alpine image as the foundation for running the app. +# By specifying the "3.18" tag, it will use version 3.18 of alpine. If +# reproducibility is important, consider using a digest +# (e.g., alpine@sha256:664888ac9cfd28068e062c991ebcff4b4c7307dc8dd4df9e728bedde5c449d91). +FROM alpine:3.23.3 AS final + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/go/dockerfile-user-best-practices/ +ARG UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + appuser + +RUN mkdir -p /app && chown appuser:appuser /app +USER appuser +WORKDIR /app +ENV IN_DOCKER=true + +# Copy the executable from the "build" stage. +COPY --from=build /bin/server /app/server + +# Expose the port that the application listens on. +EXPOSE 39321 + +# What the container should run when it is started. +CMD ["/app/server"]