I've recently started using lerna to manage a monorepo, and in development it works fine.
Lerna creates symlinks between my various packages, and so tools like 'tsc --watch' or nodemon work fine for detecting changes in the other packages.
But I've run into a problem with creating docker images in this environment.
Let's say we have a project with this structure:
root
packages
common → artifact is a private npm package, this depends on utilities, something-specific
utilities → artifact is a public npm package
something-specific -> artifact is a public npm package
frontend → artifact is a docker image, depends on common
backend → artifact is a docker image, depends on common and utilities
In this scenario, in development, everything is fine. I'm running some kind of live reload server and the symlinks work such that the dependencies are working.
Now let's say I want to create a docker image from backend.
I'll walk through some scenarios:
I
ADD
package.json in my Dockerfile, and then run npm install.Doesn't work, as the common and utilities packages are not published.
I run my build command in backend, ADD /build and /node_modules in the docker file.
Doesn't work, as my built backend has
require('common')
andrequire('utilities')
commands, these are in node_modules (symlinked), but Docker will just ignore these symlinked folders.Workaround: using
cp --dereference
to 'unsymlink' the node modules works. See this AskUbuntu question.Step 1, but before I build my docker image, I publish the npm packages.
This works ok, but for someone who is checking out the code base, and making a modification to
common
orutilities
, it's not going to work, as they don't have privledges to publish the npm package.I configure the
build
command ofbackend
to not treatcommon
orutilities
as an external, andcommon
to not treatsomething-specific
as an external.I think first build
something-specific
, and thencommon
, and thenutilities
, and thenbackend
.This way, when the build is occuring, and using this technique with webpack, the bundle will include all of the code from
something-specfic
, common andutilities
.But this is cumbersome to manage.
It seems like quite a simple problem I'm trying to solve here. The code that is currently working on my machine, I want to pull out and put into a docker container.
Remember the key thing we want to achieve here, is for someone to be able to check out the code base, modify any of the packages, and then build a docker image, all from their development environment.
Is there an obvious lerna technique that I'm missing here, or otherwise a devops frame of reference I can use to think about solving this problem?
cp --dereference
method only works for simple cases where there are no uses of incompatible versions of the same library in the monorepo.