Sfoglia il codice sorgente

chore(docker): fix & rewrite Node Dockerfiles

The new versions of these are designed to properly take advantage of pnpm and to
also minimize output size.

The builder image no longer is built on layers starting with just the
package.json files.  The reason for this is that with pnpm's content-addressed
store and the docker buildkit cache mounts, rebuilding the layers adds only
trivial overhead if dependencies haven't changed, and removing the Docker
layering to attempt to cache images with just node modules reduces complexity
significantly.

The runner image is now based on alpine and is drastically smaller.  We use
`pnpm export` (or, in the case of nextjs, we use standalone builds) to populate
the runner images with only the necessary packages and dependencies to further
reduce image sizes.
Connor Prussin 1 anno fa
parent
commit
29aa0b9c32

+ 2 - 1
.github/workflows/push-price-pusher-image.yml

@@ -39,7 +39,8 @@ jobs:
       - uses: aws-actions/amazon-ecr-login@v1
         id: ecr_login
       - run: |
-          DOCKER_BUILDKIT=1 docker build -t lerna -f Dockerfile.lerna .
+          DOCKER_BUILDKIT=1 docker build -t builder -f Dockerfile.builder .
+          DOCKER_BUILDKIT=1 docker build -t runner -f Dockerfile.runner .
           DOCKER_BUILDKIT=1 docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f apps/price_pusher/Dockerfile .
           docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
         env:

+ 3 - 2
.github/workflows/push-xc-admin-image.yml → .github/workflows/push-xc-admin-crank-executor-image.yml

@@ -29,8 +29,9 @@ jobs:
           password: ${{ secrets.GITHUB_TOKEN }}
       - name: Build docker image
         run: |
-          DOCKER_BUILDKIT=1 docker build -t lerna -f Dockerfile.lerna .
-          DOCKER_BUILDKIT=1 docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} -f governance/xc_admin/Dockerfile .
+          DOCKER_BUILDKIT=1 docker build -t builder -f Dockerfile.builder .
+          DOCKER_BUILDKIT=1 docker build -t runner -f Dockerfile.runner .
+          DOCKER_BUILDKIT=1 docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} -f governance/xc_admin/packages/crank_executor/Dockerfile .
       - name: Push docker image
         run: |
           docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}

+ 2 - 1
.github/workflows/push-xc-admin-frontend-image.yml

@@ -28,7 +28,8 @@ jobs:
           password: ${{ secrets.GITHUB_TOKEN }}
       - name: Build docker image
         run: |
-          DOCKER_BUILDKIT=1 docker build -t lerna -f Dockerfile.lerna .
+          DOCKER_BUILDKIT=1 docker build -t builder -f Dockerfile.builder .
+          DOCKER_BUILDKIT=1 docker build -t runner -f Dockerfile.runner .
           DOCKER_BUILDKIT=1 docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} \
             --build-arg NEXT_PUBLIC_RPC_POOL_TOKEN=${{ secrets.NEXT_PUBLIC_RPC_POOL_TOKEN }} \
             -f governance/xc_admin/packages/xc_admin_frontend/Dockerfile .

+ 7 - 0
Dockerfile.builder

@@ -0,0 +1,7 @@
+FROM node:18.20-slim@sha256:1da7652745e9ba5de396e436aa086588ea50d532540fa3147fbc1957c43a46ab as builder
+WORKDIR /usr/src/pyth
+ENV PNPM_HOME="/pnpm"
+ENV PATH="$PNPM_HOME:$PATH"
+RUN corepack enable
+COPY ./ .
+RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

+ 0 - 38
Dockerfile.lerna

@@ -1,38 +0,0 @@
-# The aim for the base image here is to only keep package*.json files while having the
-# same directory structure to be able to have lerna dependencies installed once and cached
-# as long as the package*.json files have not changed. In the future, we can further optimize
-# it by creating slim package files that only contain *dependencies and name keys.
-
-FROM node:18.13.0@sha256:d9061fd0205c20cd47f70bdc879a7a84fb472b822d3ad3158aeef40698d2ce36 as base
-
-WORKDIR /home/node
-COPY --chown=1000:1000 ./ ./
-
-# Remove files that are not json packages
-RUN find . -type f ! -name 'package*.json' -delete
-# Remove directories that are empty now
-RUN find . -type d -empty -delete
-
-COPY ./lerna.json ./
-COPY ./tsconfig.base.json ./
-
-FROM node:18.13.0@sha256:d9061fd0205c20cd47f70bdc879a7a84fb472b822d3ad3158aeef40698d2ce36 as lerna
-
-RUN apt-get update && apt-get install -y libusb-dev
-
-# 1000 is the uid and gid of the node user
-USER 1000
-RUN mkdir -p /home/node/.npm
-RUN mkdir -p /home/node/node_modules
-
-WORKDIR /home/node
-COPY --from=base --chown=1000:1000 /home/node ./
-
-RUN --mount=type=cache,uid=1000,gid=1000,id=lerna,target=/home/node/.npm \
-  --mount=type=cache,uid=1000,gid=1000,id=lerna,target=/home/node/node_modules \
-    pnpm i && cp -r node_modules node_modules_cache
-
-# Folders in the cache are not visible in the container that's why we copy
-# them and then move them back.
-
-RUN rm -rf node_modules && mv node_modules_cache node_modules

+ 5 - 0
Dockerfile.runner

@@ -0,0 +1,5 @@
+FROM node:18.20-alpine@sha256:6937be95129321422103452e2883021cc4a96b63c32d7947187fcb25df84fc3f as runner
+WORKDIR /srv
+ENV NODE_ENV production
+RUN addgroup --system --gid 1001 pyth && adduser --system --uid 1001 pyth -g pyth && chown pyth:pyth .
+USER pyth

+ 8 - 19
apps/price_pusher/Dockerfile

@@ -1,22 +1,11 @@
-# Defined in Dockerfile.lerna
-FROM lerna:latest
-
-USER root
-
-WORKDIR /home/node/
-USER 1000
-
-# local dependencies
-COPY --chown=1000:1000 target_chains/ethereum/sdk/solidity target_chains/ethereum/sdk/solidity
-COPY --chown=1000:1000 target_chains/sui/sdk/js target_chains/sui/sdk/js
-COPY --chown=1000:1000 price_service/client/js price_service/client/js
-COPY --chown=1000:1000 price_service/sdk/js price_service/sdk/js
-COPY --chown=1000:1000 target_chains/solana/sdk/js target_chains/solana/sdk/js
-
-COPY --chown=1000:1000 apps/price_pusher apps/price_pusher
-
+# Defined in Dockerfile.builder
+FROM builder AS price-pusher-builder
+RUN apt-get update && apt-get install -y git
 RUN pnpm exec lerna run build --scope="@pythnetwork/price-pusher" --include-dependencies
+RUN pnpm deploy --filter @pythnetwork/price-pusher --prod /srv/price-pusher
 
-WORKDIR /home/node/apps/price_pusher
 
-ENTRYPOINT [ "pnpm", "run", "start" ]
+# Defined in Dockerfile.runner
+FROM runner as price-pusher
+COPY --from=price-pusher-builder --chown=pyth:pyth /srv/price-pusher ./
+CMD [ "node", "lib/index.js" ]

+ 5 - 4
apps/price_pusher/docker-compose.beta.sample.yaml

@@ -1,9 +1,10 @@
 services:
   price-pusher:
-    # Use this to build the price pusher from source. A dependency of the pusher docker
-    # image is the pyth-crosschain monorepo lerna docker image. Build lerna image
-    # using the following command from the repo root:
-    # `docker buildx build -f Dockerfile.lerna -t lerna .`
+    # Use this to build the price pusher from source. The pusher docker image
+    # depends on the pyth-crosschain monorepo builder and runner docker
+    # images. Build the images using the following commands from the repo root:
+    # `docker buildx build -f Dockerfile.builder -t builder .`
+    # `docker buildx build -f Dockerfile.runner -t runner .`
     #
     # Please note that the docker build from source only works in x86_64 platforms
     # and doesn't work on arm platforms (like Apple M1/M2).

+ 5 - 4
apps/price_pusher/docker-compose.stable.sample.yaml

@@ -1,9 +1,10 @@
 services:
   price-pusher:
-    # Use this to build the price pusher from source. A dependency of the pusher docker
-    # image is the pyth-crosschain monorepo lerna docker image. Build lerna image
-    # using the following command from the repo root:
-    # `docker buildx build -f Dockerfile.lerna -t lerna .`
+    # Use this to build the price pusher from source. The pusher docker image
+    # depends on the pyth-crosschain monorepo builder and runner docker
+    # images. Build the images using the following commands from the repo root:
+    # `docker buildx build -f Dockerfile.builder -t builder .`
+    # `docker buildx build -f Dockerfile.runner -t runner .`
     #
     # Please note that the docker build from source only works in x86_64 platforms
     # and doesn't work on arm platforms (like Apple M1/M2).

+ 0 - 18
governance/xc_admin/Dockerfile

@@ -1,18 +0,0 @@
-# Defined in Dockerfile.lerna
-FROM lerna
-
-USER root
-
-WORKDIR /home/node/
-USER 1000
-
-COPY --chown=1000:1000 target_chains/solana/sdk/js target_chains/solana/sdk/js
-COPY --chown=1000:1000 governance/xc_admin governance/xc_admin
-COPY --chown=1000:1000 pythnet/message_buffer pythnet/message_buffer
-COPY --chown=1000:1000 price_service/sdk/js price_service/sdk/js
-
-RUN pnpm exec lerna run build --scope="{@pythnetwork/xc-admin-crank-executor,@pythnetwork/xc-admin-crank-pythnet-relayer,@pythnetwork/xc-admin-proposer-server}" --include-dependencies
-
-WORKDIR /home/node/governance/xc_admin
-
-CMD [ "node", "packages/crank_executor/lib/index.js" ]

+ 10 - 0
governance/xc_admin/packages/crank_executor/Dockerfile

@@ -0,0 +1,10 @@
+# Defined in Dockerfile.builder
+FROM builder AS xc-admin-crank-executor-builder
+RUN pnpm exec lerna run build --scope="@pythnetwork/xc-admin-crank-executor" --include-dependencies
+RUN pnpm deploy --filter @pythnetwork/xc-admin-crank-executor --prod /srv/xc-admin-crank-executor
+
+
+# Defined in Dockerfile.runner
+FROM runner as xc-admin-crank-executor
+COPY --from=xc-admin-crank-executor-builder --chown=pyth:pyth /srv/xc-admin-crank-executor ./
+CMD [ "node", "lib/index.js" ]

+ 0 - 1
governance/xc_admin/packages/xc_admin_frontend/.gitignore

@@ -33,7 +33,6 @@ yarn-error.log*
 
 # typescript
 *.tsbuildinfo
-next-env.d.ts
 
 
 # mappings

+ 13 - 21
governance/xc_admin/packages/xc_admin_frontend/Dockerfile

@@ -1,28 +1,20 @@
-# Defined in Dockerfile.lerna
-FROM lerna
-
-USER root
-
-WORKDIR /home/node/
-USER 1000
-
+# Defined in Dockerfile.builder
+FROM builder AS xc-admin-frontend-builder
 ARG NEXT_PUBLIC_RPC_POOL_TOKEN
-
-COPY --chown=1000:1000 target_chains/solana/sdk/js target_chains/solana/sdk/js
-COPY --chown=1000:1000 governance/xc_admin governance/xc_admin
-COPY --chown=1000:1000 pythnet/message_buffer pythnet/message_buffer
-COPY --chown=1000:1000 price_service/sdk/js price_service/sdk/js
-
-ENV NODE_ENV production
 ENV NEXT_TELEMETRY_DISABLED 1
+ENV BUILD_STANDALONE true
 ENV NEXT_PUBLIC_RPC_POOL_TOKEN $NEXT_PUBLIC_RPC_POOL_TOKEN
-
 RUN pnpm exec lerna run build --scope="@pythnetwork/xc-admin-frontend" --include-dependencies
 
-WORKDIR /home/node/governance/xc_admin/packages/xc_admin_frontend
-
-EXPOSE 3000
 
+# See https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
+# Defined in Dockerfile.runner
+FROM runner as xc-admin-frontend
+COPY --from=xc-admin-frontend-builder --chown=pyth:pyth /usr/src/pyth/governance/xc_admin/packages/xc_admin_frontend/.next/standalone ./
+COPY --from=xc-admin-frontend-builder --chown=pyth:pyth /usr/src/pyth/governance/xc_admin/packages/xc_admin_frontend/.next/static ./governance/xc_admin/packages/xc_admin_frontend/.next/static
+COPY --from=xc-admin-frontend-builder /usr/src/pyth/governance/xc_admin/packages/xc_admin_frontend/public ./governance/xc_admin/packages/xc_admin_frontend/public
+ENV NEXT_TELEMETRY_DISABLED 1
+ENV HOSTNAME 0.0.0.0
 ENV PORT 3000
-
-CMD ["pnpm", "start"]
+EXPOSE $PORT
+CMD [ "node", "governance/xc_admin/packages/xc_admin_frontend/server.js" ]

+ 1 - 0
governance/xc_admin/packages/xc_admin_frontend/next.config.js

@@ -3,6 +3,7 @@ const path = require('path')
 /** @type {import('next').NextConfig} */
 const nextConfig = {
   reactStrictMode: true,
+  output: process.env.BUILD_STANDALONE === 'true' ? 'standalone' : undefined,
   experimental: {
     externalDir: true,
   },

+ 1 - 0
governance/xc_admin/packages/xc_admin_frontend/package.json

@@ -33,6 +33,7 @@
     "react": "^18.3.1",
     "react-dom": "^18.3.1",
     "react-hot-toast": "^2.4.0",
+    "sharp": "^0.33.4",
     "use-debounce": "^9.0.2",
     "web3": "^4.8.0"
   },

+ 259 - 0
pnpm-lock.yaml

@@ -727,6 +727,9 @@ importers:
       react-hot-toast:
         specifier: ^2.4.0
         version: 2.4.0(csstype@3.1.3)(react-dom@18.3.1)(react@18.3.1)
+      sharp:
+        specifier: ^0.33.4
+        version: 0.33.4
       use-debounce:
         specifier: ^9.0.2
         version: 9.0.3(react@18.3.1)
@@ -5239,6 +5242,14 @@ packages:
     dependencies:
       '@jridgewell/trace-mapping': 0.3.9
 
+  /@emnapi/runtime@1.2.0:
+    resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==}
+    requiresBuild: true
+    dependencies:
+      tslib: 2.6.3
+    dev: false
+    optional: true
+
   /@ensdomains/address-encoder@0.1.9:
     resolution: {integrity: sha512-E2d2gP4uxJQnDu2Kfg1tHNspefzbLT8Tyjrm5sEuim32UkU2sm5xL4VXtgc2X33fmPEw9+jUMpGs4veMbf+PYg==}
     dependencies:
@@ -5936,6 +5947,194 @@ packages:
     engines: {node: '>=6.9.0'}
     dev: true
 
+  /@img/sharp-darwin-arm64@0.33.4:
+    resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==}
+    engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-darwin-arm64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-darwin-x64@0.33.4:
+    resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==}
+    engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-darwin-x64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-darwin-arm64@1.0.2:
+    resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==}
+    engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-darwin-x64@1.0.2:
+    resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==}
+    engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linux-arm64@1.0.2:
+    resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==}
+    engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linux-arm@1.0.2:
+    resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==}
+    engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linux-s390x@1.0.2:
+    resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==}
+    engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linux-x64@1.0.2:
+    resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==}
+    engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linuxmusl-arm64@1.0.2:
+    resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==}
+    engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-libvips-linuxmusl-x64@1.0.2:
+    resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==}
+    engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-linux-arm64@0.33.4:
+    resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==}
+    engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linux-arm64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-linux-arm@0.33.4:
+    resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==}
+    engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linux-arm': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-linux-s390x@0.33.4:
+    resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==}
+    engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linux-s390x': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-linux-x64@0.33.4:
+    resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==}
+    engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linux-x64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-linuxmusl-arm64@0.33.4:
+    resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==}
+    engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linuxmusl-arm64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-linuxmusl-x64@0.33.4:
+    resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==}
+    engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
+    optionalDependencies:
+      '@img/sharp-libvips-linuxmusl-x64': 1.0.2
+    dev: false
+    optional: true
+
+  /@img/sharp-wasm32@0.33.4:
+    resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==}
+    engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [wasm32]
+    requiresBuild: true
+    dependencies:
+      '@emnapi/runtime': 1.2.0
+    dev: false
+    optional: true
+
+  /@img/sharp-win32-ia32@0.33.4:
+    resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==}
+    engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
+    dev: false
+    optional: true
+
+  /@img/sharp-win32-x64@0.33.4:
+    resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==}
+    engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
+    dev: false
+    optional: true
+
   /@improbable-eng/grpc-web@0.14.1(google-protobuf@3.21.2):
     resolution: {integrity: sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw==}
     peerDependencies:
@@ -16332,11 +16531,26 @@ packages:
   /color-name@1.1.4:
     resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
 
+  /color-string@1.9.1:
+    resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+    dependencies:
+      color-name: 1.1.4
+      simple-swizzle: 0.2.2
+    dev: false
+
   /color-support@1.1.3:
     resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
     hasBin: true
     dev: true
 
+  /color@4.2.3:
+    resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
+    engines: {node: '>=12.5.0'}
+    dependencies:
+      color-convert: 2.0.1
+      color-string: 1.9.1
+    dev: false
+
   /colorette@1.4.0:
     resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
     dev: false
@@ -17429,6 +17643,11 @@ packages:
     engines: {node: '>=8'}
     dev: false
 
+  /detect-libc@2.0.3:
+    resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
+    engines: {node: '>=8'}
+    dev: false
+
   /detect-newline@3.1.0:
     resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
     engines: {node: '>=8'}
@@ -20542,6 +20761,10 @@ packages:
   /is-arrayish@0.2.1:
     resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
 
+  /is-arrayish@0.3.2:
+    resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+    dev: false
+
   /is-async-function@2.0.0:
     resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
     engines: {node: '>= 0.4'}
@@ -28020,6 +28243,36 @@ packages:
     resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==}
     dev: true
 
+  /sharp@0.33.4:
+    resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==}
+    engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+    requiresBuild: true
+    dependencies:
+      color: 4.2.3
+      detect-libc: 2.0.3
+      semver: 7.6.2
+    optionalDependencies:
+      '@img/sharp-darwin-arm64': 0.33.4
+      '@img/sharp-darwin-x64': 0.33.4
+      '@img/sharp-libvips-darwin-arm64': 1.0.2
+      '@img/sharp-libvips-darwin-x64': 1.0.2
+      '@img/sharp-libvips-linux-arm': 1.0.2
+      '@img/sharp-libvips-linux-arm64': 1.0.2
+      '@img/sharp-libvips-linux-s390x': 1.0.2
+      '@img/sharp-libvips-linux-x64': 1.0.2
+      '@img/sharp-libvips-linuxmusl-arm64': 1.0.2
+      '@img/sharp-libvips-linuxmusl-x64': 1.0.2
+      '@img/sharp-linux-arm': 0.33.4
+      '@img/sharp-linux-arm64': 0.33.4
+      '@img/sharp-linux-s390x': 0.33.4
+      '@img/sharp-linux-x64': 0.33.4
+      '@img/sharp-linuxmusl-arm64': 0.33.4
+      '@img/sharp-linuxmusl-x64': 0.33.4
+      '@img/sharp-wasm32': 0.33.4
+      '@img/sharp-win32-ia32': 0.33.4
+      '@img/sharp-win32-x64': 0.33.4
+    dev: false
+
   /shebang-command@1.2.0:
     resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
     engines: {node: '>=0.10.0'}
@@ -28112,6 +28365,12 @@ packages:
       simple-concat: 1.0.1
     dev: false
 
+  /simple-swizzle@0.2.2:
+    resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+    dependencies:
+      is-arrayish: 0.3.2
+    dev: false
+
   /sisteransi@1.0.5:
     resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
 

+ 0 - 17
price_service/client/js/Dockerfile

@@ -1,17 +0,0 @@
-# Defined in Dockerfile.lerna
-FROM lerna
-
-USER root
-RUN apt-get update && apt-get install -y ncat
-
-WORKDIR /home/node/
-USER 1000
-
-COPY --chown=1000:1000 price_service/client/js price_service/client/js
-COPY --chown=1000:1000 price_service/sdk/js price_service/sdk/js
-
-RUN pnpm exec lerna run build --scope="@pythnetwork/price-service-client" --include-dependencies
-
-WORKDIR /home/node/price_service/client/js
-
-ENTRYPOINT ["pnpm"]