Files
OpenNest/OpenNest.Server/Dockerfile
T
ajandClaude Opus 5.5 54ad7ee84d feat(server): nest Auto Nest jobs on the server's worker
Large nests tie up the workstation that runs them. In Database mode, Auto Nest
can now queue the job on the nest server, where a worker container solves one
job at a time under its own CPU and memory limits. The job has no time limit,
so a throttled worker finds the same nest a fast one does, only later.

- Server: /api/nest-jobs queue (schema v15). The worker holds a job on a
  heartbeat lease. When the lease lapses, the job goes back to the queue,
  or fails after three attempts. Only one job runs at a time. Packages and
  results are opaque to the HTTP server, which stays off Engine and IO.
- Worker: OpenNest.Server.Worker in the same image (OPENNEST_ROLE=worker),
  reaching the server over HTTP only. It records each engine answer with
  RecordingNestingEngine and gives its job back on shutdown.
- Desktop: "Nest on the server" in the Auto Nest dialog, for built-in
  engines only. The client replays the recorded answers with
  RemoteNestSubmission, so validation, the review and Keep run locally
  against the client's own drawings, exactly as after a local run. A
  drawing edited after sending refuses the result. If the server cannot
  take the job, the user may nest locally instead.
- compose.server.yaml adds the throttled worker service. The Dockerfile,
  .dockerignore, CI paths and the deploy script now include the worker's
  projects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:18:09 -05:00

75 lines
3.5 KiB
Docker

# Build from the repository root: docker build -f OpenNest.Server/Dockerfile -t opennest-server .
# Release builds pass --build-arg VERSION=X.Y.Z and SOURCE_REVISION=<full commit SHA>;
# the defaults mark an unversioned development build. Base images may be pinned by digest.
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:8.0
ARG RUNTIME_IMAGE=mcr.microsoft.com/dotnet/aspnet:8.0
FROM ${SDK_IMAGE} AS build
WORKDIR /src
# The worker (OPENNEST_ROLE=worker) solves server nesting jobs, so it also needs the
# engine and the nest file format; the HTTP server references neither.
COPY OpenNest.Server/OpenNest.Server.csproj OpenNest.Server/
COPY OpenNest.Server.Worker/OpenNest.Server.Worker.csproj OpenNest.Server.Worker/
COPY OpenNest.Api/OpenNest.Api.csproj OpenNest.Api/
COPY OpenNest.Engine/OpenNest.Engine.csproj OpenNest.Engine/
COPY OpenNest.IO/OpenNest.IO.csproj OpenNest.IO/
COPY OpenNest.Data/OpenNest.Data.csproj OpenNest.Data/
COPY OpenNest.Core/OpenNest.Core.csproj OpenNest.Core/
RUN dotnet restore OpenNest.Server/OpenNest.Server.csproj \
&& dotnet restore OpenNest.Server.Worker/OpenNest.Server.Worker.csproj
COPY OpenNest.Server/ OpenNest.Server/
COPY OpenNest.Server.Worker/ OpenNest.Server.Worker/
COPY OpenNest.Api/ OpenNest.Api/
COPY OpenNest.Engine/ OpenNest.Engine/
COPY OpenNest.IO/ OpenNest.IO/
COPY OpenNest.Data/ OpenNest.Data/
COPY OpenNest.Core/ OpenNest.Core/
ARG VERSION=0.0.0-dev
ARG SOURCE_REVISION=unknown
RUN dotnet publish OpenNest.Server/OpenNest.Server.csproj -c Release -o /app --no-restore \
-p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION" \
&& dotnet publish OpenNest.Server.Worker/OpenNest.Server.Worker.csproj -c Release -o /app/worker --no-restore \
-p:Version="$VERSION" -p:SourceRevisionId="$SOURCE_REVISION"
FROM ${RUNTIME_IMAGE} AS runtime
# curl is installed only for the HEALTHCHECK below.
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Runtime files stay root-owned and read-only to the app user.
COPY --from=build /app .
COPY --chmod=0755 OpenNest.Server/entrypoint.sh OpenNest.Server/healthcheck.sh /app/
# SQLite database + .nest blobs live here; mount a volume at this path. The directory
# belongs to the base image's non-root app user (APP_UID 1654), so a fresh named volume
# inherits that ownership. Existing root-owned data needs a one-time scoped chown.
RUN mkdir -p /app/data && chown "$APP_UID:$APP_UID" /app/data && chmod 0750 /app/data
ENV OPENNEST_DB=/app/data/nests.db
# Listen on the explicit 8090 URL; clear the base image's 8080 port default.
ENV ASPNETCORE_URLS=http://+:8090
ENV ASPNETCORE_HTTP_PORTS=
EXPOSE 8090
USER $APP_UID
VOLUME /app/data
# The server answers /healthz; the worker touches its alive file every poll round and heartbeat.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --start-interval=2s --retries=3 \
CMD ["/app/healthcheck.sh"]
ARG VERSION=0.0.0-dev
ARG SOURCE_REVISION=unknown
ARG RUNTIME_IMAGE
LABEL org.opencontainers.image.title="OpenNest.Server" \
org.opencontainers.image.description="OpenNest nest-storage HTTP service (SQLite) and server nesting worker" \
org.opencontainers.image.source="https://github.com/ajisaacs/OpenNest" \
org.opencontainers.image.licenses="MIT" \
org.opencontainers.image.version="$VERSION" \
org.opencontainers.image.revision="$SOURCE_REVISION" \
org.opencontainers.image.base.name="$RUNTIME_IMAGE"
# OPENNEST_ROLE picks the process: server (default) or worker; see docs/server-nesting.md.
ENTRYPOINT ["/app/entrypoint.sh"]