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?
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.
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.
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.
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.
run thr following command to let lerna-dockerize setup all required configuration.
npx lerna-dockerize init
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With