Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: docker monorepo build #1219

Merged
merged 18 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/funny-paws-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/services": patch
---

The build phase of services now works on machines with older protobuf compilers
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
node_modules
holic marked this conversation as resolved.
Show resolved Hide resolved
**/node_modules
.gitignore
*.md
dist
**/dist
**/out/
**/cache/
**/bindings/
**/artifacts/
**/abi/
**/broadcast/
**/deploys/
40 changes: 40 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
FROM docker.io/library/debian:bullseye-slim as base
Copy link
Contributor

@roninjin10 roninjin10 Aug 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Could use the official nodejs bulssey-slim image with the exact version of node specified in engines Easier to deal with node versioning and deletes some of the apt-gets

ENV SHELL /bin/bash

WORKDIR /opt
RUN apt-get -y update --fix-missing && \
apt-get -y upgrade && \
apt-get install -y --no-install-recommends \
libssl-dev make cmake graphviz \
git pkg-config curl time rhash ca-certificates jq \
python3 python3-pip lsof ruby ruby-bundler git-restore-mtime xz-utils zstd unzip gnupg protobuf-compiler \
wget net-tools iptables iproute2 iputils-ping ed zlib1g-dev wabt && \
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
apt-get install -y nodejs

# foundry
RUN curl -L https://foundry.paradigm.xyz/ | bash && \
${HOME}/.foundry/bin/foundryup \
&& forge --version \
&& cast --version \
&& anvil --version \
&& chisel --version
# go
RUN wget https://dl.google.com/go/go1.20.4.linux-amd64.tar.gz && \
# -C to move to given directory
tar -C /usr/local/ -xzf go1.20.4.linux-amd64.tar.gz
# pnpm
RUN npm install pnpm --global && pnpm --version

FROM base AS builder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: not a big deal but unnecessary to start a new image here

COPY . /app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be needlessly slow with bad caching. Everytime any file changes you will need to rebuild node modules.

What you should do is instead COPY pnpm-lock.yaml and then run pnpm fetch. This installs node modules with only the pnpm lockfile so if that didn't change it gets cached.

See pnpm fetch documentation about docker for more info https://pnpm.io/cli/fetch

WORKDIR /app

ENV PATH="${PATH}:/usr/local/go/bin"
ENV PATH="${PATH}:/root/.foundry/bin"
Comment on lines +33 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see adding foundry to path here

RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use pnpm fetch followed by pnpm install --offline see comment above

RUN pnpm run -r build

FROM builder AS store-indexer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice good use of multistage build

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually looking at this now you could likely Copy in just the buld artifacts and then run pnpm i --production to not install dev deps and have a smaller image. This is a nit though if the image is not too large don't need to optimize now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to make it super tiny you would use a smaller image than bullseye slim. You don't need very much to run just a node process usually requires more extra tooling to build an app than to run an app.

As an example I build with bullseye-slim. but then run the application with the much tinier gcr.io/distroless/nodejs18 as example-server-runner image here https://github.com/roninjin10/stax/blob/main/Dockerfile#L242

I use distroless specifically because it's debian based

WORKDIR /app/packages/store-indexer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this dockerfile is specific to store-indexer, should we put this in packages/store-indexer/bin? or does that make the rest of the infra complicated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are having one top level docker file that builds the entire monorepo, then takes specific artifacts and put them in different images. This dockerfile actually describes two images right now: a global builder, and a specific store-indexer. Over time we will add more of them, one for each TS service that requires a Docker image.
having one per package is actually worse, given we would need to build the entire monorepo for each of them (instead of looping through all targets -- currently only store-indexer, and building + tagging them individually which will leverage the cache of the build stage).

EXPOSE 3001
15 changes: 10 additions & 5 deletions packages/services/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,32 @@ protoc-ts:
--plugin protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out ./protobuf/ts/ecs-stream \
--ts_proto_opt=env=browser,outputServices=nice-grpc,outputServices=generic-definitions,outputJsonMethods=false,useExactTypes=false,eslint_disable,esModuleInterop=true,importSuffix=.js \
--proto_path proto proto/ecs-stream.proto
--proto_path proto proto/ecs-stream.proto \
--experimental_allow_proto3_optional
protoc \
--plugin protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out ./protobuf/ts/ecs-snapshot \
--ts_proto_opt=env=browser,outputServices=nice-grpc,outputServices=generic-definitions,outputJsonMethods=false,useExactTypes=false,eslint_disable,esModuleInterop=true,importSuffix=.js \
--proto_path proto proto/ecs-snapshot.proto
--proto_path proto proto/ecs-snapshot.proto \
--experimental_allow_proto3_optional
protoc \
--plugin protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out ./protobuf/ts/ecs-relay \
--ts_proto_opt=env=browser,outputServices=nice-grpc,outputServices=generic-definitions,outputJsonMethods=false,useExactTypes=false,eslint_disable,esModuleInterop=true,importSuffix=.js \
--proto_path proto proto/ecs-relay.proto
--proto_path proto proto/ecs-relay.proto \
--experimental_allow_proto3_optional
protoc \
--plugin protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out ./protobuf/ts/faucet \
--ts_proto_opt=env=browser,outputServices=nice-grpc,outputServices=generic-definitions,outputJsonMethods=false,useExactTypes=false,eslint_disable,esModuleInterop=true,importSuffix=.js \
--proto_path proto proto/faucet.proto
--proto_path proto proto/faucet.proto \
--experimental_allow_proto3_optional
protoc \
--plugin protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto \
--ts_proto_out ./protobuf/ts/mode \
--ts_proto_opt=env=browser,outputServices=nice-grpc,outputServices=generic-definitions,outputJsonMethods=false,useExactTypes=false,eslint_disable,esModuleInterop=true,importSuffix=.js \
--proto_path proto proto/mode.proto
--proto_path proto proto/mode.proto \
--experimental_allow_proto3_optional
.PHONY: protoc-ts

protoc-clean:
Expand Down