# Multi-stage build of OtOpcUa.Host targeting linux-x64. Used by docker-dev/docker-compose.yml # to spin six host containers (central-1, central-2, site-a-1, site-a-2, site-b-1, site-b-2) from a single image — # Compose drives OTOPCUA_ROLES + Cluster:* env per container to differentiate them. # A separate `migrator` stage (below) applies EF migrations once on bring-up. # Build stage is PINNED to linux/amd64. Per-cluster mesh Phase 3 added an in-repo .proto compiled by # Grpc.Tools, whose bundled linux_arm64 `protoc` segfaults (exit 139) on Apple-Silicon Docker — so a # native-arm64 build stage cannot generate the gRPC stubs. `dotnet publish` here is framework-dependent # (portable IL + every RID's native assets), so the amd64-built output runs unchanged on the native # runtime image below; only this one-time build is emulated, runtime stays native/fast. FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0 AS build WORKDIR /src COPY . . RUN dotnet restore ZB.MOM.WW.OtOpcUa.slnx # Commit stamp (#893). .dockerignore keeps .git/ out of the build context, so SourceLink has no # repository to read and the informational version would be a bare "1.0.0". The compose `build.args` # (fed by docker-dev/compose.sh from the host's `git rev-parse HEAD`, plus "-dirty" for an uncommitted # tree) hand it to the SDK as SourceRevisionId, which yields "1.0.0+" in # AssemblyInformationalVersion (and so Telemetry's service.version). Left empty, the build still # succeeds as "1.0.0". Declared after restore so a new commit does not bust the restore layer. ARG SOURCE_REVISION= RUN dotnet publish src/Server/ZB.MOM.WW.OtOpcUa.Host/ZB.MOM.WW.OtOpcUa.Host.csproj \ -c Release -o /app --no-restore \ ${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}} FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime WORKDIR /app COPY --from=build /app ./ EXPOSE 9000 EXPOSE 4053 EXPOSE 4840 ENTRYPOINT ["dotnet", "OtOpcUa.Host.dll"] # ── Migrator (one-shot) ────────────────────────────────────────────────────── # Applies EF Core migrations to the ConfigDb so a fresh SQL volume gets the schema # with no operator step. docker-dev compose runs this once, before cluster-seed + # the host nodes (they depend on it via service_completed_successfully). The host # nodes deliberately do NOT auto-migrate (production owns schema changes), so this # rig-only stage carries that responsibility. The connection comes from the # OTOPCUA_CONFIG_CONNECTION env var read by DesignTimeDbContextFactory. FROM build AS migrator RUN dotnet tool install --global dotnet-ef --version 10.0.7 ENV PATH="${PATH}:/root/.dotnet/tools" WORKDIR /src ENTRYPOINT ["dotnet", "ef", "database", "update", \ "--project", "src/Core/ZB.MOM.WW.OtOpcUa.Configuration", \ "--startup-project", "src/Core/ZB.MOM.WW.OtOpcUa.Configuration"]