-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDockerfile
360 lines (303 loc) · 26.7 KB
/
Dockerfile
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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# This is a mutli-stage Docker build.
# Stage 0 (named `manifests`) collects the dependency manifest files
# Stage 1 (named `monorepo`) builds the monorepo
# Stage 2 (named: 'frontend') builds the frontend for deployment
# Stage 3 (named: 'backend') builds the backend for deployment
# Stage 4 (named: 'e2e') builds playwright and metamask for e2e testing
# Multistage builds allow our final deployments to be small and to maximize
# cache hits. In future we will further optimize by using remote nx cache
# to share cache hits between builds.
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ░█████╗░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ██╔══██╗
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ██║░░██║
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ██║░░██║
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ╚█████╔╝
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░╚════╝░
# ███╗░░░███╗░█████╗░███╗░░██╗██╗███████╗███████╗░██████╗████████╗░██████╗
# ████╗░████║██╔══██╗████╗░██║██║██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝
# ██╔████╔██║███████║██╔██╗██║██║█████╗░░█████╗░░╚█████╗░░░░██║░░░╚█████╗░
# ██║╚██╔╝██║██╔══██║██║╚████║██║██╔══╝░░██╔══╝░░░╚═══██╗░░░██║░░░░╚═══██╗
# ██║░╚═╝░██║██║░░██║██║░╚███║██║██║░░░░░███████╗██████╔╝░░░██║░░░██████╔╝
# ╚═╝░░░░░╚═╝╚═╝░░╚═╝╚═╝░░╚══╝╚═╝╚═╝░░░░░╚══════╝╚═════╝░░░░╚═╝░░░╚═════╝░
# Stage 0 (named `manifests`) collects
# dependency manifest files (`package.json` and `yarn.lock`) which are then
# used by stage 1 to install these dependencies
# development. The only reason we need a separate stage just for collecting the
# dependency manifests is that Docker's `COPY` command still does not allow
# copying based on a glob pattern (see this GitHub issue for more details
# https://github.com/moby/moby/issues/15858). Being able to copy only manifests
# into stage 1 (the `COPY --from=manifests` statement) is important to maximize
# Docker build cache hit rate. `alpine` is chosen as the base image for the
# first stage because it's the smallest image that have access to the `cp
# --parents -t` command (by installing the `coreutils` package).
FROM alpine:3.16 as manifests
RUN apk add coreutils
WORKDIR /tmp
COPY tsconfig.json .gitmodules pnpm-workspace.yaml pnpm-lock.yaml .nvmrc package.json ./src/
COPY packages src/packages/
COPY apps src/apps/
RUN mkdir manifests && \
cd src && \
# copy package.json recursively
find . -name 'package.json' | xargs cp --parents -t ../manifests/ && \
# pnpm-lock
cp pnpm-lock.yaml ../manifests/ && \
# pnpm-workspace
cp pnpm-workspace.yaml ../manifests/ && \
# .nvmrc
cp .nvmrc ../manifests/ && \
# .gitmodules
cp .gitmodules ../manifests/ && \
# tsconfig
cp tsconfig.json ../manifests/
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ░░███╗░░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ░████║░░
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ██╔██║░░
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ╚═╝██║░░
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ███████╗
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ╚══════╝
# ███╗░░░███╗░█████╗░███╗░░██╗░█████╗░██████╗░███████╗██████╗░░█████╗░
# ████╗░████║██╔══██╗████╗░██║██╔══██╗██╔══██╗██╔════╝██╔══██╗██╔══██╗
# ██╔████╔██║██║░░██║██╔██╗██║██║░░██║██████╔╝█████╗░░██████╔╝██║░░██║
# ██║╚██╔╝██║██║░░██║██║╚████║██║░░██║██╔══██╗██╔══╝░░██╔═══╝░██║░░██║
# ██║░╚═╝░██║╚█████╔╝██║░╚███║╚█████╔╝██║░░██║███████╗██║░░░░░╚█████╔╝
# ╚═╝░░░░░╚═╝░╚════╝░╚═╝░░╚══╝░╚════╝░╚═╝░░╚═╝╚══════╝╚═╝░░░░░░╚════╝░
# stage 1 (named 'monorepo') installs all dependencies
# and builds all packages in the monorepo
# This stage is expensive and it's final image is very large
# for that reason we do not deploy anything from this stage
# but it is capable of running anything in the monorepo nonetheless
# including the integration tests, unit tests, lint, any application
# and dev servers, etc. You can even develop completely in this image!
# We start with playwright image purely for convenience. This image
# has all the dependencies we need to build the monorepo and run the
# integration tests. We would ideally use a smaller image such as
# node-alpine with the exact same node version as our nvmrc file
# this node version doesn't exctly match our nvmrce file and we should
# fix that. I tried to install with nvm but it was a pain and I gave up
# for now
FROM node:18.12.1-bullseye as monorepo
ENV PATH "$PATH:/root/.foundry/bin"
ENV NX_DAEMON=false
# Add the Foundry CLI to the PATH and do a quick test to make sure it's installed to path
RUN curl -L https://foundry.paradigm.xyz | bash && \
foundryup && \
forge --version && \
anvil --version && \
cast --version && \
npm i [email protected] --global
WORKDIR /monorepo
# Copy manifest files into the image in
# preparation for `yarn install`.
COPY --from=manifests --chown=node:node /tmp/manifests ./
# install all dependencies
RUN pnpm i --frozen-lockfile
# set NODE_ENV after installing so dev deps get installed
ENV NODE_ENV=production
# copy rest of repo and buildd
COPY . .
# remove rust which is built in it's own seperate step for now
# later we want to add rust to this image
RUN rm -rf apps/forgecli
# build all apps and packages
RUN pnpm build && rm -rf node_modules/.cache
CMD ["pnpm", "nx", "run-many", "--targets=test,lint,typecheck", "--all", "--parallel"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ██████╗░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ╚════██╗
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ░░███╔═╝
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ██╔══╝░░
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ███████╗
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ╚══════╝
# ██╗░░░██╗██╗████████╗███████╗ ░█████╗░██████╗░██████╗░
# ██║░░░██║██║╚══██╔══╝██╔════╝ ██╔══██╗██╔══██╗██╔══██╗
# ╚██╗░██╔╝██║░░░██║░░░█████╗░░ ███████║██████╔╝██████╔╝
# ░╚████╔╝░██║░░░██║░░░██╔══╝░░ ██╔══██║██╔═══╝░██╔═══╝░
# ░░╚██╔╝░░██║░░░██║░░░███████╗ ██║░░██║██║░░░░░██║░░░░░
# ░░░╚═╝░░░╚═╝░░░╚═╝░░░╚══════╝ ╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░
# @gateway/frontend
# Stage 2 (named frontend) is the stage that prepares the frontend for
# production. It uses the nginx image to serve the frontend.
# The nginx image is configured to serve the frontend from the
# /usr/share/nginx/html directory. The frontend is copied from the
# build directory of the frontend stage.
# The build for the frontend is a simple vite bundle. Vite will bundle
# everything including javascript, images, sass, node_modules and more into
# a single directory. This directory is then served by nginx.
# The nginx configuration is copied from the ops/nginx.conf file.
# The nginx image exposes port 80.
# The nginx image is started with the command "nginx -g daemon off;".
# This command starts nginx in the foreground.
# The nginx image is based on the alpine image.
# The alpine image is a lightweight image that is optimized for size.
# The alpine image is based on the musl libc library.
# we don't use alpine for most of our images because it's very difficult to
# get the right dependencies installed for the various packages we use.
# it only supports very specific node.js versions (well) for the most part
# and it's even more difficult to get playwright or puppeteer to work on it.
FROM nginx:stable-alpine as ts-sol-playground-runner
COPY --from=monorepo /monorepo/apps/ts-sol-playground/dist /usr/share/nginx/html
COPY apps/ts-sol-playground/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ██████╗░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ╚════██╗
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ░█████╔╝
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ░╚═══██╗
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ██████╔╝
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ╚═════╝░
# ██████╗░██╗░░░░░░█████╗░░██████╗░
# ██╔══██╗██║░░░░░██╔══██╗██╔════╝░
# ██████╦╝██║░░░░░██║░░██║██║░░██╗░
# ██╔══██╗██║░░░░░██║░░██║██║░░╚██╗
# ██████╦╝███████╗╚█████╔╝╚██████╔╝
# ╚═════╝░╚══════╝░╚════╝░░╚═════╝░
FROM nginx:stable-alpine as blog-runner
COPY --from=monorepo /monorepo/apps/blog/dist /usr/share/nginx/html
COPY apps/blog/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ░░██╗██╗
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ░██╔╝██║
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ██╔╝░██║
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ███████║
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ╚════██║
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░░░░░╚═╝
# ███╗░░██╗███████╗██╗░░██╗████████╗ ░█████╗░██████╗░██████╗░
# ████╗░██║██╔════╝╚██╗██╔╝╚══██╔══╝ ██╔══██╗██╔══██╗██╔══██╗
# ██╔██╗██║█████╗░░░╚███╔╝░░░░██║░░░ ███████║██████╔╝██████╔╝
# ██║╚████║██╔══╝░░░██╔██╗░░░░██║░░░ ██╔══██║██╔═══╝░██╔═══╝░
# ██║░╚███║███████╗██╔╝╚██╗░░░██║░░░ ██║░░██║██║░░░░░██║░░░░░
# ╚═╝░░╚══╝╚══════╝╚═╝░░╚═╝░░░╚═╝░░░ ╚═╝░░╚═╝╚═╝░░░░░╚═╝░░░░░
# FROM gcr.io/distroless/nodejs18 AS next-app-runner
# WORKDIR /app
# ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
# RUN addgroup --system --gid 1001 nodejs
# RUN adduser --system --uid 1001 nextjs
# COPY --from=monorepo /monorepo/apps/next-app/public ./public
# COPY --from=monorepo --chown=nextjs:nodejs /monorepo/apps/next-app/.next/standalone ./
# COPY --from=monorepo --chown=nextjs:nodejs /monorepo/apps/next-app/.next/static ./.next/static
# USER nextjs
# EXPOSE 3000
# ENV PORT 3000
# CMD ["node", "server.js"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ███████╗
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ██╔════╝
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ██████╗░
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ╚════██╗
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ██████╔╝
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ╚═════╝░
# ██████╗░░█████╗░░█████╗░██╗░░██╗███████╗███╗░░██╗██████╗░
# ██╔══██╗██╔══██╗██╔══██╗██║░██╔╝██╔════╝████╗░██║██╔══██╗
# ██████╦╝███████║██║░░╚═╝█████═╝░█████╗░░██╔██╗██║██║░░██║
# ██╔══██╗██╔══██║██║░░██╗██╔═██╗░██╔══╝░░██║╚████║██║░░██║
# ██████╦╝██║░░██║╚█████╔╝██║░╚██╗███████╗██║░╚███║██████╔╝
# ╚═════╝░╚═╝░░╚═╝░╚════╝░╚═╝░░╚═╝╚══════╝╚═╝░░╚══╝╚═════╝░
# @gateway/backend
# Stage 3 (named backend) is the stage that prepares the backend for
# production. It uses the node-bullseye-slim image that maches our
# nvmrc version of node.js. This is the smallest image we could find
# that was reasonably easy to get the dependencies installed for
# puppeteer to be able to open chrome correctly. To make the image
# it's smallest we bundle the backend with tsup (an esbuild based library)
# that bundles the backend into a single file. However, there are some
# dependencies that are not bundled into the single file. These are
# installed with npm. This image is unnecessarily large because of the
# image generator. Ideally, the image generator would be a separate
# service that is called from the backend. This would allow us to
# the much smaller node-alpine 16.17.1 image to run the server.
FROM gcr.io/distroless/nodejs18 as example-server-runner
ENV NODE_ENV=production
WORKDIR /monorepo
COPY --from=monorepo /monorepo/apps/example-server/dist/run.js ./apps/example-server/dist/run.js
EXPOSE $EXAMPLE_SERVER_PORT
CMD ["apps/example-server/dist/run.js"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ░█████╗░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ██╔═══╝░
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ██████╗░
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ██╔══██╗
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ╚█████╔╝
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░╚════╝░
# ███████╗░█████╗░██████╗░░██████╗░███████╗ ░█████╗░██╗░░░░░██╗
# ██╔════╝██╔══██╗██╔══██╗██╔════╝░██╔════╝ ██╔══██╗██║░░░░░██║
# █████╗░░██║░░██║██████╔╝██║░░██╗░█████╗░░ ██║░░╚═╝██║░░░░░██║
# ██╔══╝░░██║░░██║██╔══██╗██║░░╚██╗██╔══╝░░ ██║░░██╗██║░░░░░██║
# ██║░░░░░╚█████╔╝██║░░██║╚██████╔╝███████╗ ╚█████╔╝███████╗██║
# ╚═╝░░░░░░╚════╝░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░╚════╝░╚══════╝╚═╝
FROM rust:1.24.0 as forgecli
WORKDIR /monorepo
COPY Cargo.lock Cargo.toml rust-toolchain.toml rustfmt.toml apps/forgecli ./
RUN cargo install && cargo build
CMD ["cargo", "run", "--package", "forgecli"]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ███████╗
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ╚════██║
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ░░░░██╔╝
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ░░░██╔╝░
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ░░██╔╝░░
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░░╚═╝░░░
# ░█████╗░░█████╗░███╗░░██╗████████╗██████╗░░█████╗░░█████╗░████████╗░██████╗
# ██╔══██╗██╔══██╗████╗░██║╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
# ██║░░╚═╝██║░░██║██╔██╗██║░░░██║░░░██████╔╝███████║██║░░╚═╝░░░██║░░░╚█████╗░
# ██║░░██╗██║░░██║██║╚████║░░░██║░░░██╔══██╗██╔══██║██║░░██╗░░░██║░░░░╚═══██╗
# ╚█████╔╝╚█████╔╝██║░╚███║░░░██║░░░██║░░██║██║░░██║╚█████╔╝░░░██║░░░██████╔╝
# ░╚════╝░░╚════╝░╚═╝░░╚══╝░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝░╚════╝░░░░╚═╝░░░╚═════╝░
# Use the latest foundry image
# TODO pin this to a specific version
FROM ghcr.io/foundry-rs/foundry as contracts-deployer
WORKDIR /monorepo
COPY . .
# install without using git
RUN forge install && \
forge build && \
forge test && \
rm -rf cache
ENTRYPOINT ["forge", "script", "packages/contracts/script/Deploy.s.sol:Deploy"]
CMD [ "--rpc-url", "http://anvil:8545" ]
# ░██████╗████████╗░█████╗░░██████╗░███████╗ ░█████╗░
# ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██╔════╝ ██╔══██╗
# ╚█████╗░░░░██║░░░███████║██║░░██╗░█████╗░░ ╚█████╔╝
# ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██╔══╝░░ ██╔══██╗
# ██████╔╝░░░██║░░░██║░░██║╚██████╔╝███████╗ ╚█████╔╝
# ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚══════╝ ░╚════╝░
# ███████╗██████╗░███████╗
# ██╔════╝╚════██╗██╔════╝
# █████╗░░░░███╔═╝█████╗░░
# ██╔══╝░░██╔══╝░░██╔══╝░░
# ███████╗███████╗███████╗
# ╚══════╝╚══════╝╚══════╝
# Stage 4 (named e2e) is the stage that prepares playwright for
# running the e2e tests. It's a separate stage because playwright
# and docker don't play nice together. To make sure we don't have
# issues maintaining it we always run the app in a seperate
# image from the playwright tests. We keep the playwright
# image only for playwright and use the official microsoft
# playwright image as a base. This makes it unlikely we will
# have issues and an easy upgrade path into the future.
# As a result these e2e tests run if the app is running seperately
# outside of this container.
# We use the builds form previous stage but otherwise
# mostly build this image from scratch to make sure no node module
# installations on different images are incompatible with each other.
# WARNING - the node version here is a different 16.x version than the
# nvmrc version. This is unlikely to cause issues
FROM mcr.microsoft.com/playwright:v1.29.0-focal as e2e
ENV NX_DAEMON=false
ENV PATH "$PATH:/root/.foundry/bin"
RUN apt-get update && apt-get install -y \
make \
g++ --no-install-recommends && curl \
# Add the Foundry CLI to the PATH and do a quick test to make sure it's installed to path
curl -L https://foundry.paradigm.xyz | bash && \
foundryup && forge --version && anvil --version && cast --version && \
# Install pnpm to install node modules
npm i [email protected] --global
WORKDIR /monorepo
# Copy manifest files into the image in
# preparation for `yarn install`.
COPY pnpm-workspace.yaml pnpm-lock.yaml .nvmrc package.json ./
COPY ./apps/e2e ./apps/e2e/
# ignore scripts dealing with presinstall and postinstall
RUN pnpm i --frozen-lockfile --ignore-scripts
ENV NODE_ENV=production
# TODO actually run the e2e tests