From fde8b93206b9d2470f2e5eed75b807ef9041f7a6 Mon Sep 17 00:00:00 2001 From: "soroush.asadi" Date: Thu, 4 Jun 2026 19:59:27 +0330 Subject: [PATCH] Fix Docker build/runtime: 0.0.0.0 bind, npm ci, HTTP-mirror fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issues found bringing the stack up locally and fixed: - Server was loopback-only inside the container (appsettings "Urls=localhost" wins over ASPNETCORE_URLS) → published port returned "empty reply". Force the bind with command-line args: ENTRYPOINT dotnet Hokm.Server.dll --urls 0.0.0.0:5005. - Web image: npm install crashed on alpine ("Exit handler never called"); root cause was UNABLE_TO_GET_ISSUER_CERT_LOCALLY — the Nexus mirror serves a partial chain that Node's CA bundle can't complete. Use npm ci + strict-ssl=false. - .NET restore hit the same partial chain (NU1301 PartialChain). Both registries are now build ARGs (NUGET_INDEX / NPM_REGISTRY) defaulting to the HTTPS mirror (CI runner trusts it); local .env overrides to the plain-HTTP Nexus (http://171.22.25.73:8081) which has no TLS. NuGet feed is generated inline with allowInsecureConnections so .NET 10 accepts the HTTP source. Verified on local Docker (Postgres-backed): db+server+web all healthy; API + web reachable from host on 1505/1500; auth → profile (1000 coins) → friend add/accept (bidirectional) → chat (unread) all 200; rows persisted in Postgres (Profiles=2, Friends=2, Messages=1). Co-Authored-By: Claude Opus 4.8 --- .gitea/workflows/ci-cd.yml | 2 +- Dockerfile | 12 ++++++++++-- docker-compose.yml | 5 +++++ server/Dockerfile | 26 ++++++++++++++++++++++---- server/nuget.docker.config | 15 --------------- 5 files changed, 38 insertions(+), 22 deletions(-) delete mode 100644 server/nuget.docker.config diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index be893d5..7c8b3db 100644 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -77,7 +77,7 @@ jobs: tar -xzf /tmp/repo.tar.gz --strip-components=1 - name: Install - run: npm install --legacy-peer-deps --ignore-scripts --registry https://mirror.soroushasadi.com/repository/npm-group/ + run: npm ci --legacy-peer-deps --registry https://mirror.soroushasadi.com/repository/npm-group/ - name: TypeScript check run: npx tsc --noEmit diff --git a/Dockerfile b/Dockerfile index f2db910..a4c51f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,19 @@ # Barg-e Vasat web (Next.js 16 static export → nginx) # The app is output:"export" (fully client-side), so we build the static `out/` # and serve it with nginx. NEXT_PUBLIC_* are baked at build time. +# npm ci (deterministic, installs the exact musl optional binaries from the +# lockfile) — `npm install` crashes here ("Exit handler never called") resolving +# Next SWC + Tailwind v4 native deps. FROM mirror.soroushasadi.com/node:20-alpine AS build WORKDIR /app COPY package*.json ./ -RUN npm install --legacy-peer-deps --ignore-scripts \ - --registry https://mirror.soroushasadi.com/repository/npm-group/ +# npm registry. Default = HTTPS Nexus (CI runner trusts the cert). Override with +# NPM_REGISTRY=http://:8081/repository/npm-group/ for hosts whose trust +# store lacks the mirror's intermediate (PartialChain) — e.g. local Docker Desktop. +# strict-ssl=false also tolerates the partial chain when HTTPS is used. +ARG NPM_REGISTRY=https://mirror.soroushasadi.com/repository/npm-group/ +RUN npm ci --legacy-peer-deps --strict-ssl=false --no-audit --no-fund \ + --registry "${NPM_REGISTRY}" COPY . . # Live mode + the API origin the BROWSER will use (host-mapped port / LAN IP). ARG NEXT_PUBLIC_USE_SERVER=1 diff --git a/docker-compose.yml b/docker-compose.yml index bf14e49..86cb224 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,9 @@ services: build: context: ./server dockerfile: Dockerfile + args: + # Default HTTPS; local .env overrides to the HTTP Nexus IP (PartialChain). + NUGET_INDEX: ${NUGET_INDEX:-https://mirror.soroushasadi.com/repository/nuget-group/index.json} image: hokm-server:latest container_name: hokm-server restart: unless-stopped @@ -67,6 +70,8 @@ services: # BROWSER uses to reach the API (host-mapped api port, or LAN IP). NEXT_PUBLIC_USE_SERVER: "1" NEXT_PUBLIC_SERVER_URL: ${NEXT_PUBLIC_SERVER_URL:-http://localhost:1505} + # Default HTTPS; local .env overrides to the HTTP Nexus IP (PartialChain). + NPM_REGISTRY: ${NPM_REGISTRY:-https://mirror.soroushasadi.com/repository/npm-group/} image: hokm-web:latest container_name: hokm-web restart: unless-stopped diff --git a/server/Dockerfile b/server/Dockerfile index 404e4c8..3b7fd26 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -2,7 +2,23 @@ # Build context = ./server (so Hokm.Engine + Hokm.Server are both in scope) FROM mirror.soroushasadi.com/dotnet/sdk:10.0 AS build WORKDIR /src -COPY nuget.docker.config /tmp/nuget.config +# NuGet feed. Default = HTTPS Nexus (CI runner trusts the cert). Override with +# NUGET_INDEX=http://:8081/repository/nuget-group/index.json for hosts +# whose trust store lacks the mirror's intermediate (PartialChain) — e.g. local +# Docker Desktop. allowInsecureConnections lets .NET 10 use the HTTP feed. +ARG NUGET_INDEX=https://mirror.soroushasadi.com/repository/nuget-group/index.json +RUN printf '%s\n' \ + '' \ + '' \ + ' ' \ + ' ' \ + " " \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + ' ' \ + '' > /tmp/nuget.config COPY Directory.Build.props ./ COPY src/ ./src/ RUN dotnet restore src/Hokm.Server/Hokm.Server.csproj --configfile /tmp/nuget.config @@ -13,9 +29,11 @@ WORKDIR /app # aspnet image ships no wget/curl — borrow busybox so the healthcheck has wget. COPY --from=mirror.soroushasadi.com/busybox:1.36 /bin/busybox /usr/bin/wget COPY --from=build /out ./ -# Bind all interfaces (appsettings binds localhost only, unreachable across the port map). -ENV ASPNETCORE_URLS=http://0.0.0.0:5005 +# Bind all interfaces. appsettings.json pins "Urls=http://localhost:5005" (dev), +# which wins over ASPNETCORE_URLS — so force 0.0.0.0 via command-line args, which +# have the highest config precedence. Otherwise the server is loopback-only inside +# the container and the published port returns "empty reply". EXPOSE 5005 HEALTHCHECK --interval=10s --timeout=5s --retries=12 --start-period=20s \ CMD wget -q -O- http://127.0.0.1:5005/ || exit 1 -ENTRYPOINT ["dotnet", "Hokm.Server.dll"] +ENTRYPOINT ["dotnet", "Hokm.Server.dll", "--urls", "http://0.0.0.0:5005"] diff --git a/server/nuget.docker.config b/server/nuget.docker.config deleted file mode 100644 index 23e5834..0000000 --- a/server/nuget.docker.config +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - -