Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build docker images in a lerna monorepo without publishing

Tags:

The use case for this is branch building and deployments in Lerna monorepos.

The problem is that Lerna monorepos either hoist dependencies in NPM or use yarn workspaces to the same effect to collect all dependencies in the node_modules folder of the workspace/monorepo. Which means that they will not be accessible when building Dockerfiles in subfolders due to how docker build contexts work.

I imagine what is needed here is a kind of "lower" (as opposed to hoist) function to pull package dependencies into the node_modules of the Docker/package.json project before running docker build.

The question is, does anyone have a better idea, or know of an already existing method to do this?

like image 383
Gudlaugur Egilsson Avatar asked Dec 13 '19 10:12

Gudlaugur Egilsson


People also ask

Do Dockerfiles create images?

Write the DockerfileDocker builds images automatically by reading the instructions from a Dockerfile. It is a text file that contains all commands needed to build a given image.

What is Monorepo lerna?

Lerna is a tool for managing JavaScript projects with multiple packages. Lerna manages monorepos, which can hold projects containing multiple packages within itself. Monorepos can be challenging to manage because sequential builds and publishing individual packages take a long time.


Video Answer


2 Answers

For my own project, the solution is to use docker BuildKit to first build all the workspace and then build a docker image for the project workspace reusing the previous built files.

In details you have copy in the docker file the top package.json with yarn lock and then cherrypicking the package.json of the needed workspace. Then running a yarn install and a yarn build to get everything working.

Here is my project:

# base image FROM @myscope/base:latest as base  # set working directory WORKDIR /app  # add `/app/node_modules/.bin` to $PATH ENV PATH /app/node_modules/.bin:$PATH  # install and cache app dependencies COPY ["package.json","yarn.lock", "./"] COPY ./packages/server/package.json ./packages/server/ COPY ./packages/shared/package.json ./packages/shared/ COPY ./packages/app/package.json ./packages/app/  RUN yarn install --frozen-lockfile --non-interactive --production=false --ignore-scripts COPY . /app RUN yarn build    FROM nodejs:14.15 as serverapp  WORKDIR /app  COPY ["package.json","yarn.lock", "./"] COPY ./packages/server/package.json ./packages/server/ COPY ./packages/shared/package.json ./packages/shared/  RUN yarn install --frozen-lockfile --non-interactive --production=true --ignore-scripts  # copy artifact build from the 'build environment' COPY --from=base /app/packages/shared/dist /app/packages/shared/dist  COPY ["./packages/server/", "./packages/server/"]  WORKDIR /app/packages/server VOLUME ["/app/packages/server/logs", "/app/packages/server/uploads"] EXPOSE $PORT CMD ["yarn", "start"] 

shared is a private workspace that is a dependency of the server workspace.

like image 171
Mathieu Seiler Avatar answered Sep 18 '22 21:09

Mathieu Seiler


Due no answer was satisfying for me i have built an npm package, which generates a Dockerfile for lerna projects. It uses the stage feature of Docker and creates stages for each package.

Current Version:

run thr following command to let lerna-dockerize setup all required configuration.

npx lerna-dockerize init 

Original Version:

You simply need at least two Dockerfiles:

The base Dockerfile which contains the global setup

Dockerfile.base:

FROM node:14 as base COPY ./package.json ./ RUN npm i COPY ./lerna.json ./ 

and a template for the packages

Dockerfile.template:

FROM base as build COPY ./package.json ./ RUN npm install RUN --if-exists npm run build 

you can also have custom Dockerfiles for packages by simply adding your own Dockerfile inside the package. This will replace the template by the custom Dockerfile.

afterwards you can run the command over npx to generate your dockerfile:

npx lerna-dockerize 
like image 26
Michael R. Avatar answered Sep 20 '22 21:09

Michael R.