Skip to content

Commit fa51e82

Browse files
committed
chore: cleanup Dockerfile
1 parent 029b3bd commit fa51e82

File tree

1 file changed

+78
-26
lines changed

1 file changed

+78
-26
lines changed

Dockerfile

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,104 @@
1-
FROM node:18 AS node
1+
# syntax=docker/dockerfile:1
2+
############################################################
3+
# 1) Base Node environment
4+
############################################################
5+
FROM node:18 AS node-base
26

7+
# Create non-root workspace owned by uid/gid 1000 (keeps permissions consistent across stages)
38
RUN mkdir /app && chown 1000:1000 /app
49
USER 1000
510
WORKDIR /app
611

7-
FROM node AS build-cli
12+
############################################################
13+
# 2) Dependency layer (Yarn cache prefetch)
14+
############################################################
15+
FROM node-base AS deps
816
ARG TARGETARCH
917

10-
COPY .yarnrc.yml yarn.lock ./
11-
COPY --chown=1000:1000 .yarn .yarn
18+
# Copy only Yarn config + lockfile up front to maximize layer caching
19+
COPY --link --chown=1000:1000 .yarnrc.yml yarn.lock ./
20+
COPY --link --chown=1000:1000 .yarn .yarn
21+
22+
# Pre-fetch Yarn cache without installing (fast, deterministic, cacheable)
23+
# NOTE: BuildKit cache mount keeps the artifact cache across builds.
1224
RUN yarn fetch
1325

14-
RUN NODE_ARCH=$(if [ "$TARGETARCH" = "amd64" ]; then echo "x64"; elif [ "$TARGETARCH" = "arm" ]; then echo "armv7"; else echo "$TARGETARCH"; fi) && \
15-
echo $NODE_ARCH>.nodearch
26+
# Normalize Docker's TARGETARCH into Node's arch names and persist for later stages
27+
# amd64 -> x64, arm -> armv7, otherwise pass through (arm64, etc.)
28+
RUN bash -lc 'case "$TARGETARCH" in \
29+
amd64) echo x64 ;; \
30+
arm) echo armv7 ;; \
31+
*) echo "$TARGETARCH" ;; \
32+
esac > .nodearch'
33+
34+
############################################################
35+
# 3) CLI build (bundle with ncc, pack with vercel/pkg)
36+
############################################################
37+
FROM deps AS build-cli
1638

17-
# prefetch node, see https://github.com/vercel/pkg/issues/292#issuecomment-401353635
39+
# Prefetch the Node runtime that "pkg" will embed so the next step is faster and stable
40+
# (See: https://github.com/vercel/pkg/issues/292#issuecomment-401353635)
1841
RUN touch noop.js && \
19-
yarn pkg -t node18-linuxstatic-$(cat .nodearch) noop.js --out=noop && rm -rf noop && \
20-
rm noop.js
42+
yarn pkg -t node18-linuxstatic-$(cat .nodearch) noop.js --out=noop && \
43+
rm -rf noop noop.js
2144

22-
COPY package.json index.js ./
23-
COPY src src
24-
RUN yarn build:ncc
25-
RUN yarn pkg -t node18-linuxstatic-$(cat .nodearch) -o ./dist-bin/dockerfile-x --compress=GZip ./dist/index.js
45+
# Copy the minimum project sources necessary for building the CLI
46+
COPY --link --chown=1000:1000 src ./src
47+
COPY --link --chown=1000:1000 index.js package.json ./
2648

49+
# Build the CLI (ncc) and then produce a single-file static binary via pkg
50+
RUN yarn build:ncc && \
51+
yarn pkg -t node18-linuxstatic-$(cat .nodearch) \
52+
-o ./dist-bin/dockerfile-x --compress=GZip ./dist/index.js
53+
54+
############################################################
55+
# 4) CA certificates for final scratch
56+
############################################################
2757
FROM alpine:3 AS certs
28-
RUN apk --update add ca-certificates
58+
RUN apk --no-cache add ca-certificates
2959

60+
############################################################
61+
# 5) Build Go frontend (static binary)
62+
############################################################
3063
FROM golang:1.25 AS build-frontend
3164
ARG TARGETARCH
3265
WORKDIR /app
33-
COPY vendor vendor
34-
COPY go.mod go.sum ./
35-
COPY pkg pkg
36-
COPY main.go ./
37-
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build -mod vendor -ldflags '-w -extldflags "-static"' -o dist-bin/dockerfile-x-frontend .
3866

67+
# Copy modules first for better caching, then the sources
68+
COPY --link go.mod go.sum ./
69+
COPY --link vendor ./vendor
70+
COPY --link pkg ./pkg
71+
COPY --link main.go ./
72+
73+
# Produce a fully-static Linux binary (no CGO, strip symbols)
74+
# GOARCH is derived from Docker's --platform
75+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH \
76+
go build -mod=vendor -trimpath -buildvcs=false \
77+
-ldflags='-s -w -extldflags "-static"' \
78+
-o dist-bin/dockerfile-x-frontend .
79+
80+
############################################################
81+
# 6) Minimal final image
82+
############################################################
3983
FROM scratch
4084

41-
# see https://github.com/moby/buildkit/blob/master/frontend/dockerfile/cmd/dockerfile-frontend/Dockerfile
85+
# BuildKit frontend capabilities (mirrors upstream Dockerfile frontend)
86+
# Ref: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/cmd/dockerfile-frontend/Dockerfile
4287
LABEL moby.buildkit.frontend.network.none="true"
4388
LABEL moby.buildkit.frontend.caps="moby.buildkit.frontend.inputs,moby.buildkit.frontend.subrequests,moby.buildkit.frontend.contexts"
4489

45-
ENTRYPOINT [ "/dockerfile-x-frontend" ]
46-
ENV PATH=/
47-
ENV DOCKERFILEX_TMPDIR=/workspace
90+
# Keep PATH minimal; put binaries at root so ENTRYPOINT can reference them directly
91+
ENV PATH=/ \
92+
DOCKERFILEX_TMPDIR=/workspace
93+
94+
# Run as non-root and default to a writeable working directory
4895
USER 1000
4996
WORKDIR /workspace
50-
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
51-
COPY --from=build-frontend /app/dist-bin/ /
52-
COPY --from=build-cli /app/dist-bin/ /
97+
98+
# Copy only the necessary runtime artifacts
99+
COPY --link --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
100+
COPY --link --from=build-frontend /app/dist-bin/ /
101+
COPY --link --from=build-cli /app/dist-bin/ /
102+
103+
# The Go frontend is the entrypoint; the CLI binary is also available in PATH
104+
ENTRYPOINT ["/dockerfile-x-frontend"]

0 commit comments

Comments
 (0)