Skip to content

Commit 27952d6

Browse files
authored
feat: improve dockerfile (#1295)
* feat: improve dockerfile - use smaller docker images for builder & runner - use node user instead of root to limit permissions - use dumb init for better process & signal handling - pin docker images to commit sha's * fix: copy all dir contents to runner * fix: create storage dirs manually * fix: check with root permissions * fix: update permissions for database dirs * fix: directory permissions for node user * fix: recursive chown for databases dir * fix: update get version method to work for node dist/index.js run * fix: change permissions for jobs dir so child containers can write * feat: make image smaller by removing unneeded stuff * docs: explain the assignment of node user to docker group * ci: add faster failure for test_integration & system to check error * Revert "ci: add faster failure for test_integration & system to check error" This reverts commit c7ceb5a. * docs: add comment for chmodSync fn
1 parent 70004bb commit 27952d6

7 files changed

Lines changed: 89 additions & 45 deletions

File tree

.dockerignore

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,17 @@ node_modules
22
/dist
33
logs
44
c2d_storage
5-
.env.local
6-
.env
5+
databases
6+
.env
7+
.env.*
8+
.git
9+
.github
10+
docs
11+
src/test
12+
*.md
13+
*.log
14+
.nyc_output
15+
coverage
16+
docker-compose.yml
17+
elasticsearch-compose.yml
18+
typesense-compose.yml

Dockerfile

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,56 @@
1-
FROM ubuntu:22.04 AS base
2-
RUN apt-get update && apt-get -y install bash curl git wget libatomic1 python3 build-essential
3-
COPY .nvmrc /usr/src/app/
4-
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
5-
ENV NVM_DIR=/usr/local/nvm
6-
RUN mkdir $NVM_DIR
7-
ENV NODE_VERSION=v22.15.0
8-
# Install nvm with node and npm
9-
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash \
10-
&& source $NVM_DIR/nvm.sh \
11-
&& nvm install $NODE_VERSION \
12-
&& nvm alias default $NODE_VERSION \
13-
&& nvm use default
14-
ENV NODE_PATH=$NVM_DIR/$NODE_VERSION/lib/node_modules
15-
ENV PATH=$NVM_DIR/versions/node/$NODE_VERSION/bin:$PATH
16-
ENV IPFS_GATEWAY='https://ipfs.io/'
17-
ENV ARWEAVE_GATEWAY='https://arweave.net/'
18-
19-
FROM base AS builder
20-
COPY package*.json /usr/src/app/
21-
COPY scripts/ /usr/src/app/scripts/
22-
WORKDIR /usr/src/app/
1+
FROM node:22.15.0-bookworm@sha256:a1f1274dadd49738bcd4cf552af43354bb781a7e9e3bc984cfeedc55aba2ddd8 AS builder
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
python3 \
4+
build-essential \
5+
libatomic1 \
6+
git \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
WORKDIR /usr/src/app
10+
COPY package*.json ./
11+
COPY scripts/ ./scripts/
2312
RUN npm ci
13+
COPY . .
14+
RUN npm run build && npm prune --omit=dev
15+
16+
17+
FROM node:22.15.0-bookworm-slim@sha256:557e52a0fcb928ee113df7e1fb5d4f60c1341dbda53f55e3d815ca10807efdce AS runner
18+
RUN apt-get update && apt-get install -y --no-install-recommends \
19+
dumb-init \
20+
gosu \
21+
libatomic1 \
22+
&& rm -rf /var/lib/apt/lists/*
23+
24+
ENV NODE_ENV=production \
25+
IPFS_GATEWAY='https://ipfs.io/' \
26+
ARWEAVE_GATEWAY='https://arweave.net/' \
27+
P2P_ipV4BindTcpPort=9000 \
28+
P2P_ipV4BindWsPort=9001 \
29+
P2P_ipV6BindTcpPort=9002 \
30+
P2P_ipV6BindWsPort=9003 \
31+
P2P_ipV4BindWssPort=9005 \
32+
HTTP_API_PORT=8000
33+
34+
EXPOSE 9000 9001 9002 9003 9005 8000
35+
36+
# GID of the docker group on the host. Needs to match so the node user can access
37+
# /var/run/docker.sock for compute jobs. Default is 999 (common on Debian/Ubuntu).
38+
# Override at build time if your host differs: docker build --build-arg DOCKER_GID=$(getent group docker | cut -d: -f3) .
39+
ARG DOCKER_GID=999
40+
RUN groupadd -g ${DOCKER_GID} docker && usermod -aG docker node
41+
42+
WORKDIR /usr/src/app
43+
44+
COPY --chown=node:node --from=builder /usr/src/app/dist ./dist
45+
COPY --chown=node:node --from=builder /usr/src/app/node_modules ./node_modules
46+
COPY --chown=node:node --from=builder /usr/src/app/schemas ./schemas
47+
COPY --chown=node:node --from=builder /usr/src/app/package.json ./
48+
COPY --chown=node:node --from=builder /usr/src/app/config.json ./
49+
50+
RUN mkdir -p databases c2d_storage logs
2451

52+
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
53+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
2554

26-
FROM base AS runner
27-
COPY . /usr/src/app
28-
WORKDIR /usr/src/app/
29-
COPY --from=builder /usr/src/app/node_modules/ /usr/src/app/node_modules/
30-
RUN npm run build
31-
ENV P2P_ipV4BindTcpPort=9000
32-
EXPOSE 9000
33-
ENV P2P_ipV4BindWsPort=9001
34-
EXPOSE 9001
35-
ENV P2P_ipV6BindTcpPort=9002
36-
EXPOSE 9002
37-
ENV P2P_ipV6BindWsPort=9003
38-
EXPOSE 9003
39-
ENV P2P_ipV4BindWssPort=9005
40-
EXPOSE 9005
41-
ENV HTTP_API_PORT=8000
42-
EXPOSE 8000
43-
ENV NODE_ENV='production'
44-
CMD ["npm","run","start"]
55+
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
56+
CMD ["node", "--max-old-space-size=28784", "--trace-warnings", "--experimental-specifier-resolution=node", "dist/index.js"]

docker-entrypoint.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Fix ownership of directories that may be mounted as volumes (owned by root).
5+
# Runs as root, then drops to 'node' user via gosu.
6+
chown -R node:node /usr/src/app/databases /usr/src/app/c2d_storage /usr/src/app/logs 2>/dev/null || true
7+
8+
exec gosu node dumb-init -- "$@"

src/components/Indexer/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { create256Hash } from '../../utils/crypt.js'
3838
import { getDatabase, isReachableConnection } from '../../utils/database.js'
3939
import { sleep } from '../../utils/util.js'
4040
import { isReindexingNeeded } from './version.js'
41+
import { getPackageVersion } from '../../utils/version.js'
4142
import { DB_EVENTS, ES_CONNECTION_EVENTS } from '../database/ElasticsearchConfigHelper.js'
4243

4344
/**
@@ -535,7 +536,7 @@ export class OceanIndexer {
535536
* Checks if reindexing is needed and triggers it for all chains
536537
*/
537538
public async checkAndTriggerReindexing(): Promise<void> {
538-
const currentVersion = process.env.npm_package_version
539+
const currentVersion = getPackageVersion()
539540
const dbActive = this.getDatabase()
540541
if (!dbActive || !(await isReachableConnection(dbActive.getConfig().url))) {
541542
INDEXER_LOGGER.error(`Giving up reindexing. DB is not online!`)

src/components/c2d/compute_engine_docker.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
createWriteStream,
3737
existsSync,
3838
mkdirSync,
39+
chmodSync,
3940
rmSync,
4041
writeFileSync,
4142
appendFileSync,
@@ -2932,6 +2933,8 @@ export class C2DEngineDocker extends C2DEngine {
29322933
if (!existsSync(dir)) {
29332934
mkdirSync(dir, { recursive: true })
29342935
}
2936+
// update directory permissions to allow read/write from job containers
2937+
chmodSync(dir, 0o777)
29352938
}
29362939
return true
29372940
} catch (e) {

src/components/core/utils/statusHandler.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { typesenseSchemas } from '../../database/TypesenseSchemas.js'
1414
import { SupportedNetwork } from '../../../@types/blockchain.js'
1515
import { getAdminAddresses } from '../../../utils/auth.js'
1616
import HumanHasher from 'humanhash'
17+
import { getPackageVersion } from '../../../utils/version.js'
1718

1819
function getSupportedStorageTypes(config: OceanNodeConfig): StorageTypes {
1920
return {
@@ -126,7 +127,7 @@ export async function status(
126127
publicKey: publicKeyHex,
127128
friendlyName: new HumanHasher().humanize(publicKeyHex),
128129
address: oceanNode.getKeyManager().getEthAddress(),
129-
version: process.env.npm_package_version,
130+
version: getPackageVersion(),
130131
http: config.hasHttp,
131132
p2p: config.hasP2P,
132133
provider: [],

src/utils/version.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { createRequire } from 'module'
2+
3+
const require = createRequire(import.meta.url)
4+
5+
export function getPackageVersion(): string {
6+
return process.env.npm_package_version ?? require('../../package.json').version
7+
}

0 commit comments

Comments
 (0)