Repository navigation
fix(containers): production frontend image, non-root, no dev-mode masking - #10
Merged
Merged
Conversation
…king
First time the container path could be exercised (docker now installed) — it was
badly broken.
- frontend/Dockerfile ran 'npm run dev': a hot-reloading DEVELOPMENT server shipped
as the production artifact, in an image that ran as root. Replaced with a
three-stage Next.js standalone build (deps -> builder -> runner) that runs as the
unprivileged 'node' user (trivy DS-0002 HIGH cleared).
- docker-compose.yml masked the image three ways: 'command: [npm run dev]' overrode
the image CMD, './frontend:/app' hid the built app, and an anonymous
'/app/node_modules' volume shadowed the installed modules. In practice the
frontend container crash-looped with 'sh: next: not found'. All three removed;
the backend had the same './backend:/app' masking.
- backend/Dockerfile: dropped apt entirely. Installing libssl-dev failed outright
('libssl3t64 u2' pinned by the index vs u3 offered). No compiler is needed — every
dependency ships a manylinux wheel. Now python:3.12-slim matching the repo target,
plus the missing HEALTHCHECK (DS-0026) that uses the bundled interpreter.
- Added .dockerignore to both contexts: without them the 539MB node_modules, the
.git dir and any local .env would be copied into the image.
- compose ports bound to 127.0.0.1 instead of 0.0.0.0.
- Removed the 'nethermind' username/naming from the built images in favour of netcore.
Verified with real containers:
- docker compose up -d -> backend healthy and frontend healthy within 10s
- curl 127.0.0.1:8000/health 200; curl 127.0.0.1:3000/ 200
- docker exec nethermind-backend id -> uid=1000(netcore)
- docker exec nethermind-frontend id -> uid=1000(node)
- trivy config on both Dockerfiles -> 0 findings (was 1 HIGH + 2 LOW)
- pytest 11 passed; gitleaks clean; compose down -v afterwards, 0 containers left
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Docker is now installed on the build host, so the container path could finally be exercised. It was badly broken — and had never worked.
Fixes
1. The "production" frontend image ran
npm run dev— a hot-reloading development server shipped as the production artifact, from an image running as root (trivy DS-0002, HIGH).Replaced with a three-stage Next.js standalone build (
deps → builder → runner) running as the unprivilegednodeuser.2.
docker-compose.ymlmasked the image three separate ways — this is why the stack never worked:command: ["npm", "run", "dev"]overrode the image's CMD./frontend:/appbind-mount hid the built application/app/node_modulesvolume shadowed the installed modulesResult: the container crash-looped with
sh: next: not found. All three removed. The backend had the same./backend:/appmasking.3.
backend/Dockerfilecould not build at all. Installinglibssl-devfailed outright — the index pinslibssl3t64 3.5.7-1~deb13u2whileu3is what gets offered.aptis now gone entirely: no compiler is needed, since every dependency inrequirements.txtships a manylinux wheel. Base bumped topython:3.12-slimto match the repo's declared target, and the missingHEALTHCHECKadded (DS-0026), using the bundled interpreter so nocurlis required.4. No
.dockerignorein either context — the 539 MBnode_modules, the.gitdirectory and any local.envwould have been copied into the images. Both added.5. Compose ports bound to
127.0.0.1instead of0.0.0.0.Verification (real containers, real commands)
docker compose up -dcurl 127.0.0.1:8000/healthcurl 127.0.0.1:3000/docker exec nethermind-backend iddocker exec nethermind-frontend idtrivy configboth Dockerfilespytest tests/ -qgitleakscompose down -vBefore this branch: frontend
unhealthy/restartingwith exit 127, and the backend image would not build.Publishing mode is
draft— review only, nothing released.