diff --git a/Dockerfile b/Dockerfile index d959a03292..fff191cc58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,21 @@ -FROM golang:1.26-bookworm AS build-env +# +# Stage 1: build the web bundle with pnpm. +# +# Uses the official pnpm image. Node is auto-downloaded by pnpm using the +# `devEngines.runtime` field in package.json (onFail: "download"). +# +FROM ghcr.io/pnpm/pnpm:11 AS web-build -WORKDIR /usr/src/social-app +WORKDIR /app ENV DEBIAN_FRONTEND=noninteractive # -# Node +# pnpm config # -ENV NODE_VERSION=24.15.0 -ENV NVM_DIR=/usr/share/nvm - -# -# Go -# -ENV GODEBUG="netdns=go" -ENV GOOS="linux" -ENV GOARCH="amd64" -ENV CGO_ENABLED=1 -ENV GOEXPERIMENT="loopvar" +ENV CI=1 +# use the pnpm version specified in package.json +ENV pnpm_config_pm_on_fail=download # The latest git hash of the preview branch on render.com # https://render.com/docs/docker-secrets#environment-variables-in-docker-builds @@ -42,41 +40,48 @@ ENV SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN:-unknown} ARG EXPO_PUBLIC_SENTRY_DSN ENV EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN -# -# Copy everything into the container -# COPY . . -# -# Generate the JavaScript webpack. -# -RUN mkdir --parents $NVM_DIR && \ - wget \ - --output-document=/tmp/nvm-install.sh \ - https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh && \ - bash /tmp/nvm-install.sh - -RUN \. "$NVM_DIR/nvm.sh" && \ - nvm install $NODE_VERSION && \ - nvm use $NODE_VERSION && \ - echo "Using bundle identifier: $EXPO_PUBLIC_BUNDLE_IDENTIFIER" && \ +RUN echo "Using bundle identifier: $EXPO_PUBLIC_BUNDLE_IDENTIFIER" && \ echo "EXPO_PUBLIC_ENV=$EXPO_PUBLIC_ENV" >> .env && \ echo "EXPO_PUBLIC_RELEASE_VERSION=$EXPO_PUBLIC_RELEASE_VERSION" >> .env && \ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER" >> .env && \ echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \ - echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env && \ - npm install --global pnpm@11.1.1 && \ - pnpm install --frozen-lockfile && \ - pnpm intl:build 2>&1 | tee i18n.log && \ - if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi && \ - SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER pnpm build-web + echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env + +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile + +RUN pnpm intl:build 2>&1 | tee i18n.log && \ + if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi + +RUN SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN \ + SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION \ + SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER \ + pnpm build-web + +# +# Stage 2: build the bskyweb Go binary, embedding the assets from stage 1. +# +# post-web-build.js (run by `pnpm build-web`) writes the bundled JS/CSS/media +# into bskyweb/static/* and regenerates bskyweb/templates/scripts.html, so +# copying the bskyweb/ tree from stage 1 is enough for go:embed to find +# everything. +# +FROM golang:1.26-bookworm AS go-build + +WORKDIR /usr/src/social-app + +ENV GODEBUG="netdns=go" +ENV GOOS="linux" +ENV GOARCH="amd64" +ENV CGO_ENABLED=1 +ENV GOEXPERIMENT="loopvar" + +COPY --from=web-build /app/bskyweb ./bskyweb # DEBUG -RUN find ./bskyweb/static && find ./web-build/static +RUN find ./bskyweb/static -# -# Generate the bskyweb Go binary. -# RUN cd bskyweb/ && \ go mod download && \ go mod verify @@ -89,6 +94,9 @@ RUN cd bskyweb/ && \ -o /bskyweb \ ./cmd/bskyweb +# +# Stage 3: runtime image. +# FROM debian:bookworm-slim ENV GODEBUG=netdns=go @@ -102,7 +110,7 @@ RUN apt-get update && apt-get install --yes \ ENTRYPOINT ["dumb-init", "--"] WORKDIR /bskyweb -COPY --from=build-env /bskyweb /usr/bin/bskyweb +COPY --from=go-build /bskyweb /usr/bin/bskyweb CMD ["/usr/bin/bskyweb"]