-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathDockerfile
More file actions
296 lines (268 loc) · 11.2 KB
/
Dockerfile
File metadata and controls
296 lines (268 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# syntax=docker/dockerfile:1
ARG NODE_VERSION=22
ARG BUILDPLATFORM
# Shared deps (alpine) for website/docs/webapp builds
FROM node:${NODE_VERSION}-alpine AS deps-alpine
WORKDIR /repo
RUN apk add --no-cache libc6-compat
ENV REDISMS_DISABLE_POSTINSTALL=1
ENV YARN_CACHE_FOLDER=/tmp/.yarn-cache
COPY package.json yarn.lock ./
RUN mkdir -p apps/ui apps/server apps/cli apps/website apps/docs packages/agents packages/cli-common packages/protocol packages/release-runtime packages/audio-stream-native packages/sherpa-native
COPY apps/ui/package.json apps/ui/
COPY apps/server/package.json apps/server/
COPY apps/cli/package.json apps/cli/
COPY apps/website/package.json apps/website/
COPY apps/docs/package.json apps/docs/
COPY packages/agents/package.json packages/agents/
COPY packages/cli-common/package.json packages/cli-common/
COPY packages/protocol/package.json packages/protocol/
COPY packages/release-runtime/package.json packages/release-runtime/
COPY packages/audio-stream-native/package.json packages/audio-stream-native/
COPY packages/sherpa-native/package.json packages/sherpa-native/
COPY docker/scripts/yarn-install-with-retry.sh /usr/local/bin/yarn-install-with-retry
RUN chmod +x /usr/local/bin/yarn-install-with-retry
RUN --mount=type=cache,target=/tmp/.yarn-cache,sharing=locked \
yarn config set registry https://registry.npmjs.org/ \
&& yarn-install-with-retry --frozen-lockfile --ignore-engines --network-timeout 600000 --prefer-offline --non-interactive
# Shared deps (alpine) for web UI export embeds.
# We build the web export on the BUILDPLATFORM because the output is architecture-agnostic, and
# running Node/Yarn under QEMU for linux/arm64 has proven unstable (SIGILL).
FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-alpine AS deps-alpine-build
WORKDIR /repo
RUN apk add --no-cache libc6-compat
ENV REDISMS_DISABLE_POSTINSTALL=1
ENV YARN_CACHE_FOLDER=/tmp/.yarn-cache
COPY package.json yarn.lock ./
RUN mkdir -p apps/ui apps/server apps/cli apps/website apps/docs packages/agents packages/cli-common packages/protocol packages/release-runtime packages/audio-stream-native packages/sherpa-native
COPY apps/ui/package.json apps/ui/
COPY apps/server/package.json apps/server/
COPY apps/cli/package.json apps/cli/
COPY apps/website/package.json apps/website/
COPY apps/docs/package.json apps/docs/
COPY packages/agents/package.json packages/agents/
COPY packages/cli-common/package.json packages/cli-common/
COPY packages/protocol/package.json packages/protocol/
COPY packages/release-runtime/package.json packages/release-runtime/
COPY packages/audio-stream-native/package.json packages/audio-stream-native/
COPY packages/sherpa-native/package.json packages/sherpa-native/
COPY docker/scripts/yarn-install-with-retry.sh /usr/local/bin/yarn-install-with-retry
RUN chmod +x /usr/local/bin/yarn-install-with-retry
RUN --mount=type=cache,target=/tmp/.yarn-cache,sharing=locked \
yarn config set registry https://registry.npmjs.org/ \
&& yarn-install-with-retry --frozen-lockfile --ignore-engines --network-timeout 600000 --prefer-offline --non-interactive
# Shared deps (debian) for server builds (needs toolchain for native deps)
FROM node:${NODE_VERSION} AS deps-debian
RUN apt-get update && apt-get install -y python3 ffmpeg make g++ build-essential && rm -rf /var/lib/apt/lists/*
WORKDIR /repo
ENV REDISMS_DISABLE_POSTINSTALL=1
ENV YARN_CACHE_FOLDER=/tmp/.yarn-cache
COPY package.json yarn.lock ./
RUN mkdir -p apps/ui apps/server apps/cli apps/website apps/docs packages/agents packages/cli-common packages/protocol packages/release-runtime packages/audio-stream-native packages/sherpa-native
COPY apps/ui/package.json apps/ui/
COPY apps/server/package.json apps/server/
COPY apps/cli/package.json apps/cli/
COPY apps/website/package.json apps/website/
COPY apps/docs/package.json apps/docs/
COPY packages/agents/package.json packages/agents/
COPY packages/cli-common/package.json packages/cli-common/
COPY packages/protocol/package.json packages/protocol/
COPY packages/release-runtime/package.json packages/release-runtime/
COPY packages/audio-stream-native/package.json packages/audio-stream-native/
COPY packages/sherpa-native/package.json packages/sherpa-native/
COPY docker/scripts/yarn-install-with-retry.sh /usr/local/bin/yarn-install-with-retry
RUN chmod +x /usr/local/bin/yarn-install-with-retry
RUN --mount=type=cache,target=/tmp/.yarn-cache,sharing=locked \
yarn config set registry https://registry.npmjs.org/ \
&& yarn-install-with-retry --frozen-lockfile --ignore-engines --network-timeout 600000 --prefer-offline --non-interactive
#
# Targets
#
# Website (Vite static)
FROM deps-alpine AS website-builder
ARG WEBSITE_VARIANT=prerelease
COPY apps/website ./apps/website
RUN test -f "apps/website/index.${WEBSITE_VARIANT}.html" && cp "apps/website/index.${WEBSITE_VARIANT}.html" "apps/website/index.html"
RUN yarn workspace @happier-dev/website build
FROM nginxinc/nginx-unprivileged:alpine AS website
USER root
RUN apk add --no-cache curl
COPY --from=website-builder /repo/apps/website/dist /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
RUN echo 'server { \
listen 8080; \
server_name _; \
root /usr/share/nginx/html; \
\
location = /health { \
return 200 "ok\n"; \
} \
\
location /assets/ { \
try_files $uri =404; \
} \
\
location /.well-known/ { \
try_files $uri =404; \
} \
\
location / { \
try_files $uri $uri/ /index.html; \
} \
}' > /etc/nginx/conf.d/default.conf
USER 101
EXPOSE 8080
# Webapp (Expo export static)
FROM deps-alpine-build AS webapp-builder
ARG HAPPIER_EMBEDDED_POLICY_ENV=preview
ARG POSTHOG_API_KEY=""
ARG POSTHOG_HOST=""
ARG SENTRY_DSN=""
ARG SENTRY_RELEASE=""
ARG SENTRY_AUTH_TOKEN=""
ARG SENTRY_URL=""
ARG REVENUE_CAT_STRIPE=""
ENV NODE_ENV=production
ENV APP_ENV=production
ENV EXPO_PUBLIC_POSTHOG_KEY=$POSTHOG_API_KEY
ENV EXPO_PUBLIC_POSTHOG_HOST=$POSTHOG_HOST
ENV EXPO_PUBLIC_SENTRY_DSN=$SENTRY_DSN
ENV EXPO_PUBLIC_SENTRY_RELEASE=$SENTRY_RELEASE
ENV EXPO_PUBLIC_REVENUE_CAT_STRIPE=$REVENUE_CAT_STRIPE
ENV HAPPIER_EMBEDDED_POLICY_ENV=$HAPPIER_EMBEDDED_POLICY_ENV
COPY .github/feature-policy ./.github/feature-policy
COPY apps/ui ./apps/ui
COPY packages/agents ./packages/agents
COPY packages/protocol ./packages/protocol
RUN yarn workspace @happier-dev/protocol postinstall:real && yarn workspace @happier-dev/agents postinstall:real
RUN yarn workspace @happier-dev/app postinstall:real
RUN rm -rf apps/ui/dist
RUN yarn workspace @happier-dev/app expo export --platform web --output-dir dist
RUN if [ -n "$SENTRY_AUTH_TOKEN" ]; then cd apps/ui && SENTRY_AUTH_TOKEN="$SENTRY_AUTH_TOKEN" SENTRY_URL="$SENTRY_URL" SENTRY_RELEASE="$SENTRY_RELEASE" npx --yes sentry-expo-upload-sourcemaps dist; else echo "[docker] SENTRY_AUTH_TOKEN not set; skipping Sentry source maps upload"; fi
FROM nginxinc/nginx-unprivileged:alpine AS webapp
USER root
RUN apk add --no-cache curl
COPY --from=webapp-builder /repo/apps/ui/dist /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
RUN echo 'server { \
listen 8080; \
\
location = /health { \
return 200 "ok\n"; \
} \
\
location /_expo/ { \
root /usr/share/nginx/html; \
add_header Cache-Control "public, max-age=31536000, immutable"; \
try_files $uri =404; \
} \
\
location /assets/ { \
root /usr/share/nginx/html; \
add_header Cache-Control "public, max-age=31536000, immutable"; \
try_files $uri =404; \
} \
\
location /.well-known/ { \
root /usr/share/nginx/html; \
try_files $uri =404; \
} \
\
location / { \
root /usr/share/nginx/html; \
index index.html index.htm; \
add_header Cache-Control "no-store"; \
try_files $uri $uri.html $uri/index.html $uri/index.htm $uri/ /index.html /index.htm =404; \
} \
\
error_page 500 502 503 504 /50x.html; \
location = /50x.html { \
root /usr/share/nginx/html; \
try_files $uri @redirect_to_index; \
internal; \
} \
\
error_page 404 = @handle_404; \
\
location @handle_404 { \
root /usr/share/nginx/html; \
try_files /404.html @redirect_to_index; \
internal; \
} \
\
location @redirect_to_index { \
return 302 /; \
} \
}' > /etc/nginx/conf.d/default.conf
USER 101
EXPOSE 8080
# Docs (Next.js)
FROM deps-alpine AS docs-builder
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
COPY apps/docs ./apps/docs
RUN yarn workspace docs postinstall:real && yarn workspace docs build
FROM node:${NODE_VERSION}-alpine AS docs
WORKDIR /repo
RUN apk add --no-cache libc6-compat curl
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
COPY --from=docs-builder /repo/node_modules /repo/node_modules
COPY --from=docs-builder /repo/apps/docs /repo/apps/docs
EXPOSE 3000
CMD ["yarn", "--cwd", "apps/docs", "start"]
# Server
FROM deps-debian AS server-builder
ARG HAPPIER_EMBEDDED_POLICY_ENV=preview
ARG HAPPIER_BUILD_DB_PROVIDERS=""
ENV HAPPIER_BUILD_DB_PROVIDERS=$HAPPIER_BUILD_DB_PROVIDERS
ENV HAPPIER_EMBEDDED_POLICY_ENV=$HAPPIER_EMBEDDED_POLICY_ENV
COPY .github/feature-policy ./.github/feature-policy
COPY apps/server ./apps/server
COPY packages/agents ./packages/agents
COPY packages/protocol ./packages/protocol
RUN yarn workspace @happier-dev/protocol postinstall:real && yarn workspace @happier-dev/agents postinstall:real
RUN yarn workspace @happier-dev/server postinstall:real
RUN yarn workspace @happier-dev/server build
FROM node:${NODE_VERSION} AS server
WORKDIR /repo
RUN apt-get update && apt-get install -y python3 ffmpeg curl && rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
ENV PORT=3005
ENV RUN_MIGRATIONS=1
COPY --from=server-builder --chown=node:node /repo/node_modules /repo/node_modules
COPY --from=server-builder --chown=node:node /repo/packages/agents /repo/packages/agents
COPY --from=server-builder --chown=node:node /repo/packages/protocol /repo/packages/protocol
COPY --from=server-builder --chown=node:node /repo/apps/server /repo/apps/server
COPY --from=server-builder /repo/apps/server/scripts/run-server.sh /usr/local/bin/run-server
RUN chmod +x /usr/local/bin/run-server
RUN mkdir -p /data && chown -R node:node /data
USER node
EXPOSE 3005
CMD ["run-server"]
# Convenience: worker image variant (same bits, different defaults)
FROM server AS server-worker
ENV SERVER_ROLE=worker
# Relay server (self-host default: light + sqlite)
FROM server AS relay-server
# Embed the web UI bundle so self-hosted deployments can serve UI from the server.
# Disable at runtime by clearing HAPPIER_SERVER_UI_DIR (e.g. `-e HAPPIER_SERVER_UI_DIR=`).
COPY --from=webapp-builder --chown=node:node /repo/apps/ui/dist /repo/apps/ui/dist
ARG SENTRY_RELEASE=""
ENV SENTRY_RELEASE=$SENTRY_RELEASE
ARG SENTRY_SERVER_CENTRAL_DSN=""
ENV HAPPIER_SENTRY_CENTRAL_DSN=$SENTRY_SERVER_CENTRAL_DSN
ENV HAPPIER_SENTRY_USE_CENTRAL_DSN=1
ENV HAPPIER_SERVER_FLAVOR=light
ENV HAPPY_SERVER_FLAVOR=light
ENV HAPPIER_DB_PROVIDER=sqlite
ENV HAPPY_DB_PROVIDER=sqlite
ENV HAPPIER_SERVER_LIGHT_DATA_DIR=/data
ENV HAPPY_SERVER_LIGHT_DATA_DIR=/data
ENV HAPPIER_SERVER_UI_DIR=/repo/apps/ui/dist
ENV HAPPIER_SERVER_UI_PREFIX=/
ENV HAPPIER_SERVER_UI_REQUIRED=1
VOLUME ["/data"]
# Default target when building without --target
FROM server AS default