Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting up docker nodejs application with local npm dependencies

We want to start containerizing our applications, but we have stumbled upon some issues with local dependencies.

We have a single git repository, in which we have numerous node packages, under "shared" folder, and applications that require these packages.

So let's say our folder structure is as follows:

src/
├── apps
│   └── my_app
└── shared
    └── shared_module

in my_app package.json we have the following dependency:

{
  "dependencies": {
    "shared-module": "file:../../shared/shared_module"
  }
}

The issue here is that because we want to move "my_app" to run in a container, we need to npm install our local dependency.

Can this be done?

like image 826
RomanY Avatar asked Jun 20 '17 13:06

RomanY


1 Answers

Yes, it's possible but a little bit ugly. The problem for you is that Docker is very restrictive when it comes to its build context. I'm not sure how familiar you are already with that concept, so here is the introduction from the documentation:

The docker build command builds an image from a Dockerfile and a context.

For example, docker build . uses . as its build context, and since it's not specified otherwise, ./Dockerfile as the Dockerfile. Files or paths outside the build context cannot be referenced in the Dockerfile (so no COPY ..).

The issue for you is that during a Docker build, the build context cannot be left. If you have multiple applications that you want to build, you would normally add a Dockerfile for each app.

src/
├── apps   
│   ├── my_app
│   │   └── Dockerfile
│   └── my_other_app
│       └── Dockerfile
└── shared
    └── shared_module

Naturally, you would cd into my_app and use docker build . to build the application's Docker image. The issue with this is that you can't access ../../shared from the build, since it's outside of the context.

So you need to make sure both apps and shared is in the build context. One way would be to place all Dockerfile in src like so:

src/
├── Dockerfile.my_app
├── Dockerfile.my_other
├── apps
│   ├── my_app
│   └── my_other_app
└── shared
    └── shared_module

You can then build the applications by explicitly specifying the context and the Dockerfile:

src$ docker build -f Dockerfile.my_app .

Alternatively, you can keep the Dockerfiles inside my_app and my_other_app, and point to them:

src$ docker build -f apps/my_app/Dockerfile .

That should also work. In both cases, the build is executed from within src, which means you need to pay a little attention to the paths in the Dockerfile. The working directory is still src:

COPY ./apps/my_app /src/apps/my_app

By mirroring the folder structure you have locally, you should be able to make your dependencies work without any changes:

RUN mkdir -p /src
COPY ./shared /src/shared
COPY ./apps/my_app /src/apps/my_app
RUN cd /src/apps/my_app && npm install

Hope that helps you get started.

like image 113
jdno Avatar answered Oct 31 '22 19:10

jdno