skip to Main Content

I have a turborepo monorepo, using yarn workspaces which looks like this

├── packages

│ ├── server-common

├── services

│ ├── auth

Services/auth is dependant on packages/server-common and using yarn workspaces, imports it like so

  "dependencies": {
    "server-common": "*",
  }

I want to build a docker image out of services/auth, however packages/server-common is not hosted on npm, it is a local package.

Hence, when building the following dockerfile

FROM node:16-alpine

WORKDIR /app
COPY package.json .
RUN yarn install --production
COPY . .

CMD ["npm", "start"]

It fails on the yarn install stage, because docker is trying to download a package from npm, when it is a local package.

#9 8.441 error Received malformed response from registry for "server-common". The registry may be down.

Is there a way that this local package can be included in the docker build?

2

Answers


  1. A solution would be to copy your local package into the container.

    FROM node:16-alpine
    
    COPY path/to/server-common .
    WORKDIR /app
    COPY package.json .
    RUN yarn install --production
    COPY . .
    
    CMD ["npm", "start"]
    
    "dependencies": {
        "server-common": "file:../server-common"
    }
    
    Login or Signup to reply.
  2. Ran into a similar issue using yarn workspaces. I ended up just building the package I want to use in my app and reproducing the directory setup to support symlinks used by yarn workspaces.

    This was my setup:

    PROJECT ROOT

    - package.json
    - packages/
      - common/ (directory I want to install in either app1/app2)
      - app1/
      - app2/
    - Dockerfile
    

    package.json

    {
       "private": true,
      "workspaces": [
        "packages/*"
      ],
      "scripts": {
        "build:common": "yarn workspace @monorepo/common build",
        "build:app1": "yarn workspace @monorepo/app1 build",
        "start:app1": "yarn workspace @monorepo/app start",
        "build:app2": "yarn workspace @monorepo/app2 build",
        "start:app2": "yarn workspace @monorepo/app2 start",
      },
      "name": "monorepo",
    }
    

    Dockerfile

    ARG BUILD_CONTEXT
    
    FROM node:18.12.0-alpine AS builder
    ARG BUILD_CONTEXT
    ENV ENV_BUILD_CONTEXT=$BUILD_CONTEXT
    WORKDIR /usr/app
    COPY package.json ./
    COPY yarn.lock ./
    COPY packages/${BUILD_CONTEXT} /usr/app/packages/${BUILD_CONTEXT}
    COPY packages/common /usr/app/packages/common
    RUN yarn install
    RUN yarn run build:common
    RUN yarn run build:${BUILD_CONTEXT}
    
    
    FROM node:18.12.0-alpine AS final
    ARG BUILD_CONTEXT
    ENV ENV_BUILD_CONTEXT=$BUILD_CONTEXT
    WORKDIR /usr/app
    COPY --from=builder ./usr/app/packages/${BUILD_CONTEXT}/build ./packages/${BUILD_CONTEXT}/build
    COPY --from=builder ./usr/app/packages/common/build ./packages/common/build
    COPY --from=builder ./usr/app/packages/common/package.json ./packages/common
    COPY packages/${BUILD_CONTEXT}/package.json ./packages/${BUILD_CONTEXT}
    COPY package.json .
    COPY yarn.lock .
    RUN yarn install --production
    CMD yarn run start:${ENV_BUILD_CONTEXT}
    

    If you want to build an image for app1, simply run this: docker build -t image-name --build-arg BUILD_CONTEXT=app1 -f Dockerfile .

    This should work.

    NB. For this to work, you want your script names to match up with the names of the packages.

    Hope this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search