# Production image for dchain-node. # # Differs from the repo-root Dockerfile in two ways: # 1. No testdata / contract WASMs baked in — a fresh node uses the native # username_registry (shipped in-binary) and starts with an empty keys # directory; identities and optional WASM contracts come in via # mounted volumes or docker-compose bind mounts. # 2. Builds only `node` and `client` — no wallet/peerid helpers that # aren't needed in production. # # The resulting image is ~20 MB vs ~60 MB for the dev one, and has no # pre-installed keys that an attacker could exploit to impersonate a # testnet validator. # ---- build stage ---- FROM golang:1.24-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . # Build-time version metadata. All four args are injected via -ldflags -X # into go-blockchain/node/version so `node --version` and # /api/well-known-version report the real commit, not the "dev" default. # Callers pass these with `docker build --build-arg VERSION_TAG=... …`; # the deploy/single/update.sh script derives them from git automatically. ARG VERSION_TAG=dev ARG VERSION_COMMIT=none ARG VERSION_DATE=unknown ARG VERSION_DIRTY=false RUN LDFLAGS="-s -w \ -X go-blockchain/node/version.Tag=${VERSION_TAG} \ -X go-blockchain/node/version.Commit=${VERSION_COMMIT} \ -X go-blockchain/node/version.Date=${VERSION_DATE} \ -X go-blockchain/node/version.Dirty=${VERSION_DIRTY}" && \ CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="$LDFLAGS" -o /bin/node ./cmd/node && \ CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="$LDFLAGS" -o /bin/client ./cmd/client # ---- runtime stage ---- FROM alpine:3.19 RUN apk add --no-cache ca-certificates tzdata # Run as unprivileged user by default. Operators can override with --user root # if they need to bind privileged ports (shouldn't be necessary behind Caddy). RUN addgroup -S dchain && adduser -S -G dchain dchain COPY --from=builder /bin/node /usr/local/bin/node COPY --from=builder /bin/client /usr/local/bin/client USER dchain # Default data location; override in compose with a named volume. VOLUME /data # libp2p P2P port + HTTP (serves /api/*, /metrics, /api/ws). EXPOSE 4001/tcp EXPOSE 8080/tcp ENTRYPOINT ["/usr/local/bin/node"]