hardened bluesky app fork with microcosm
1#
2# Stage 1: build the web bundle with pnpm.
3#
4# Uses the official pnpm image. Node is auto-downloaded by pnpm using the
5# `devEngines.runtime` field in package.json (onFail: "download").
6#
7FROM ghcr.io/pnpm/pnpm:11 AS web-build
8
9WORKDIR /app
10
11ENV DEBIAN_FRONTEND=noninteractive
12
13#
14# pnpm config
15#
16ENV CI=1
17# use the pnpm version specified in package.json
18ENV pnpm_config_pm_on_fail=download
19
20# The latest git hash of the preview branch on render.com
21# https://render.com/docs/docker-secrets#environment-variables-in-docker-builds
22ARG RENDER_GIT_COMMIT
23
24#
25# Expo
26#
27ARG EXPO_PUBLIC_ENV
28ENV EXPO_PUBLIC_ENV=${EXPO_PUBLIC_ENV:-development}
29ARG EXPO_PUBLIC_RELEASE_VERSION
30ENV EXPO_PUBLIC_RELEASE_VERSION=$EXPO_PUBLIC_RELEASE_VERSION
31ARG EXPO_PUBLIC_BUNDLE_IDENTIFIER
32# If not set by GitHub workflows, we're probably in Render
33ENV EXPO_PUBLIC_BUNDLE_IDENTIFIER=${EXPO_PUBLIC_BUNDLE_IDENTIFIER:-$RENDER_GIT_COMMIT}
34
35#
36# Sentry
37#
38ARG SENTRY_AUTH_TOKEN
39ENV SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN:-unknown}
40ARG EXPO_PUBLIC_SENTRY_DSN
41ENV EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN
42
43COPY . .
44
45RUN echo "Using bundle identifier: $EXPO_PUBLIC_BUNDLE_IDENTIFIER" && \
46 echo "EXPO_PUBLIC_ENV=$EXPO_PUBLIC_ENV" >> .env && \
47 echo "EXPO_PUBLIC_RELEASE_VERSION=$EXPO_PUBLIC_RELEASE_VERSION" >> .env && \
48 echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER" >> .env && \
49 echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \
50 echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env
51
52RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
53
54RUN pnpm intl:build 2>&1 | tee i18n.log && \
55 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
56
57RUN SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN \
58 SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION \
59 SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER \
60 pnpm build-web
61
62#
63# Stage 2: build the bskyweb Go binary, embedding the assets from stage 1.
64#
65# post-web-build.js (run by `pnpm build-web`) writes the bundled JS/CSS/media
66# into bskyweb/static/* and regenerates bskyweb/templates/scripts.html, so
67# copying the bskyweb/ tree from stage 1 is enough for go:embed to find
68# everything.
69#
70FROM golang:1.26-bookworm AS go-build
71
72WORKDIR /usr/src/social-app
73
74ENV GODEBUG="netdns=go"
75ENV GOOS="linux"
76ENV GOARCH="amd64"
77ENV CGO_ENABLED=1
78ENV GOEXPERIMENT="loopvar"
79
80COPY --from=web-build /app/bskyweb ./bskyweb
81
82# DEBUG
83RUN find ./bskyweb/static
84
85RUN cd bskyweb/ && \
86 go mod download && \
87 go mod verify
88
89RUN cd bskyweb/ && \
90 go build \
91 -v \
92 -trimpath \
93 -tags timetzdata \
94 -o /bskyweb \
95 ./cmd/bskyweb
96
97#
98# Stage 3: runtime image.
99#
100FROM debian:bookworm-slim
101
102ENV GODEBUG=netdns=go
103ENV TZ=Etc/UTC
104ENV DEBIAN_FRONTEND=noninteractive
105
106RUN apt-get update && apt-get install --yes \
107 dumb-init \
108 ca-certificates
109
110ENTRYPOINT ["dumb-init", "--"]
111
112WORKDIR /bskyweb
113COPY --from=go-build /bskyweb /usr/bin/bskyweb
114
115CMD ["/usr/bin/bskyweb"]
116
117LABEL org.opencontainers.image.source=https://github.com/bluesky-social/social-app
118LABEL org.opencontainers.image.description="bsky.app Web App"
119LABEL org.opencontainers.image.licenses=MIT
120
121# NOOP