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: use production level docker settings #26

Merged
merged 18 commits into from
Oct 24, 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
17 changes: 17 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,20 @@ build
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# other dotfiles
.git
.gitignore
.dockerignore
.github
.tool-versions
.envrc

# playwright stuff
e2e-tests
playwright.config.ts
playwright-report
screenshots

# Other misc files that don't make sense in the docker container
README.md
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npm run test:e2e
run: npm run test:http-e2e
- uses: actions/upload-artifact@v3
if: always()
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,4 @@ build
/playwright-report/
/playwright/.cache/
screenshots
.envrc
34 changes: 30 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
FROM node:20-slim
FROM node:20-slim as builder

Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if alpine images are going to be even smaller.

Copy link
Member Author

Choose a reason for hiding this comment

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

probably

RUN apt-get update
RUN apt-get install -y build-essential cmake git libssl-dev
RUN apt-get install -y build-essential cmake git libssl-dev tini

WORKDIR /app

COPY . .
COPY package*.json ./

RUN npm ci --quiet

COPY . .

RUN npm run build

RUN npm prune --omit=dev

FROM node:20-slim as app
ENV NODE_ENV production
WORKDIR /app
# built src without dev dependencies
COPY --from=builder /app ./
# tini is used to handle signals properly, see https://github.com/krallin/tini#using-tini
Copy link
Collaborator

Choose a reason for hiding this comment

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

a further opportunity for improvement will be removing node_modules as it has devDependencies here, reinstalling with NODE_ENV=production (already set) would only install dependencies

Further reduction in image size.

Copy link
Member Author

Choose a reason for hiding this comment

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

node_modules should be removed above in the npm prune --omit=dev line

SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
COPY --from=builder /usr/bin/tini /usr/bin/tini

# copy shared libraries (without having artifacts from apt-get install that is needed to build our application)
COPY --from=builder /usr/lib/**/libcrypto* /usr/lib/
COPY --from=builder /usr/lib/**/libssl* /usr/lib/

Comment on lines +27 to +28
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've been burned in the past while handling shared libs. Can we not:

flowchart
    A[node:20-slim] -->|Install LibSSL| B(Base Image)
    B --> C[Builder Image]
    C --> |Build Assets| D(Built Image)
    B --> E[App Image]
    D --> |Copy Built Assets| E
    E --> F(Publish)
Loading

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 can re-install libssl and it would re-use the cached image, but that was more troublesome due to some additional things being installed by other apt-get installed packges: build-essential cmake git libssl-dev and I didn't want to reinstall all of them.

HEALTHCHECK --interval=12s --timeout=12s --start-period=10s CMD npm run healthcheck

CMD [ "npm", "start" ]
# Use tini to handle signals properly, see https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals
ENTRYPOINT ["/usr/bin/tini", "-p", "SIGKILL", "--"]

CMD [ "node", "dist/src/index.js" ]

# for best practices, see:
# * https://snyk.io/blog/10-best-practices-to-containerize-nodejs-web-applications-with-docker/
# * https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md
# * https://nodejs.org/en/docs/guides/nodejs-docker-webapp
50 changes: 49 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ $ docker build . --tag helia --platform linux/arm64
### Running

```sh
$ docker run -it -p 8080:8080 -e DEBUG="helia-server" helia
$ docker run -it -p 8080:8080 -e DEBUG="helia-http-gateway" helia
```

## Supported Environment Variables
Expand All @@ -38,6 +38,54 @@ $ docker run -it -p 8080:8080 -e DEBUG="helia-server" helia
| `DEBUG` | Debug level | `''`|
| `PORT` | Port to listen on | `8080` |
| `HOST` | Host to listen on | `0.0.0.0` |
| `USE_BITSWAP` | Use bitswap to fetch content from IPFS | `true` |
| `USE_TRUSTLESS_GATEWAYS` | Whether to fetch content from trustless-gateways or not | `true` |
| `TRUSTLESS_GATEWAYS` | Comma separated list of trusted gateways to fetch content from | [Defined in Helia](https://github.com/ipfs/helia/blob/main/packages/helia/src/block-brokers/trustless-gateway/index.ts) |
| `USE_LIBP2P` | Whether to use libp2p networking | `true` |

<!--
TODO: currently broken when used in docker, but they work when running locally (you can cache datastore and blockstore locally to speed things up if you want)
| `FILE_DATASTORE_PATH` | Path to use with a datastore-level passed to Helia as the datastore | `null`; memory datastore is used by default. |
| `FILE_BLOCKSTORE_PATH` | Path to use with a blockstore-level passed to Helia as the blockstore | `null`; memory blockstore is used by default. |
-->

See the source of truth for all `process.env.<name>` environment variables at [src/constants.ts](src/constants.ts).

### Running with custom configurations

Note that any of the following calls to docker can be replaced with something like `MY_ENV_VAR="MY_VALUE" npm run start`

#### Disable libp2p
```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_LIBP2P="false" helia
```

#### Disable bitswap
```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_BITSWAP="false" helia
```

#### Disable trustless gateways
```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e USE_TRUSTLESS_GATEWAYS="false" helia
```

#### Customize trustless gateways
```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e TRUSTLESS_GATEWAYS="https://ipfs.io,https://dweb.link" helia
```

<!--
#### With file datastore and blockstore

**NOTE:** Not currently supported due to docker volume? issues.

```sh
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" helia
# and if you want to re-use a volume from your host:
$ docker run -it -p $PORT:8080 -e DEBUG="helia-http-gateway*" -e FILE_DATASTORE_PATH="./datastore" -e FILE_BLOCKSTORE_PATH="./blockstore" -v ./datastore:/datastore -v ./blockstore:/blockstore helia
```
-->

## E2E Testing

Expand Down
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
version: "3.8"

services:
server:
helia-http-gateway:
build: .
restart: always
ports:
- "8080:8080"
- "${PORT:-8080}:8080"
environment:
- DEBUG="helia-server*"
- DEBUG="${DEBUG:-helia-http-gateway*}"
Loading
Loading