73 lines
2.6 KiB
Docker
73 lines
2.6 KiB
Docker
# Frontend: built first, it is the part that changes most often
|
|
FROM node:22-slim AS frontend
|
|
WORKDIR /build
|
|
|
|
# Dependencies in their own layer, so a source-only change does not reinstall them
|
|
COPY frontend/package.json frontend/package-lock.json ./
|
|
RUN npm ci
|
|
|
|
COPY frontend/ ./
|
|
# The checks run here rather than in a separate CI job: the build then fails on
|
|
# the runner for the same reason it would fail locally, and there is only one
|
|
# environment to keep working.
|
|
RUN npx eslint . --max-warnings=0
|
|
RUN npm run build # type-check + vite build
|
|
|
|
|
|
# Backend: compiled against the sqlx offline data, so no database is needed here
|
|
FROM rust:1.97-slim AS backend
|
|
WORKDIR /build
|
|
|
|
ENV SQLX_OFFLINE=true
|
|
# Traceability: `build.rs` falls back on this when there is no git repository
|
|
ARG GIT_HASH=unknown
|
|
ENV GIT_HASH=${GIT_HASH}
|
|
|
|
# Warm the dependency layer with a dummy main, so editing src/ does not rebuild
|
|
# every crate we depend on
|
|
COPY Cargo.toml Cargo.lock build.rs ./
|
|
RUN mkdir src && echo 'fn main() {}' > src/main.rs \
|
|
&& cargo build --release \
|
|
&& rm -rf src
|
|
|
|
COPY .sqlx/ .sqlx/
|
|
COPY src/ src/
|
|
# cargo skips a rebuild when only mtime changed: force it for our own crate
|
|
RUN touch src/main.rs \
|
|
&& cargo build --release --locked \
|
|
&& cargo test --release --locked
|
|
|
|
|
|
# Runtime
|
|
FROM debian:trixie-slim
|
|
LABEL org.opencontainers.image.title="vm-selector"
|
|
|
|
# virsh is how the app talks to libvirt. openssh-client is only needed if you
|
|
# point vm.uri at a qemu+ssh:// uri instead of the mounted socket; curl serves
|
|
# the healthcheck.
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends libvirt-clients openssh-client curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# The migrations travel with the image, so the stack needs nothing from the
|
|
# repository: the `migrate` service runs this same image with another entrypoint.
|
|
COPY --from=ghcr.io/amacneil/dbmate:2 /usr/local/bin/dbmate /usr/local/bin/dbmate
|
|
COPY db/migrations/ /app/db/migrations/
|
|
|
|
# Unprivileged, but it must land in the host's libvirt group to reach the
|
|
# socket: `group_add` in the compose file does that at run time.
|
|
RUN useradd --system --create-home --uid 10001 app
|
|
|
|
WORKDIR /app
|
|
COPY --from=backend /build/target/release/app-template /usr/local/bin/vm-selector
|
|
COPY --from=frontend /build/dist/ /app/frontend/
|
|
COPY docker/config.yml /etc/app-template/config.yml
|
|
|
|
USER app
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD curl -fsS http://localhost:3000/api/version || exit 1
|
|
|
|
# No shell: signals reach the binary directly, so the graceful shutdown works
|
|
ENTRYPOINT ["/usr/local/bin/vm-selector"]
|