5

When creating production build with docker what is the strategy people uses about compiling and bundling the code.

So outside the docker world, I would create a build (using some sort of npm command) which will create a dist. code (without any source code, uglified and compressed javascript for e.g.) and then I point a web server to the dist folder.

In docker world where would you build the code, Is it in docker image or on host os and just copy the dist folder to the docker image? Basically I do not want the whole npm_modules and all source code files in the docker image/container.

Any idea how to achieve this?

Thanks

activebiz
  • 6,000
  • 9
  • 41
  • 64
  • 1
    You may also be interested in [multi-stage Docker builds](https://docs.docker.com/develop/develop-images/multistage-build/). – Oliver Charlesworth Apr 16 '18 at 08:35
  • "Basically I do not want the whole npm_modules and all source code files in the docker image/container." - why not? – Constantin Galbenu Apr 16 '18 at 10:57
  • 1
    Thats because, it makes the image size bigger, the node_modules is not used when the app is running and deploying source code to production is bad practice in general. – activebiz Apr 16 '18 at 11:00
  • "the node_modules is not used when the app is running" - how so? there are modules used in production that are loaded from that directory – Constantin Galbenu Apr 16 '18 at 11:06
  • 1
    @ConstantinGalbenu - It certainly feels like good practice to not have your `devDependencies` in production. And in a world where you're running a Webpack-like asset pipeline, you don't need the `dependencies` either, as your production artifact is an asset bundle. – Oliver Charlesworth Apr 16 '18 at 18:23
  • @OliverCharlesworth nothing forces you to install them to production (https://stackoverflow.com/a/9276112/2575224). Also, my answer stands: your image should contain all it needs to run on any machine. – Constantin Galbenu Apr 16 '18 at 18:29

2 Answers2

2

It sounds like you're worried about two different, valid, problems:

  1. Ensuring an isolated/reproducible production environment.
  2. Ensuring an isolated/reproducible build environment (for building #1).

You can achieve both with the approach you suggested - have the build steps run as part of your Dockerfile. But this has the disadvantages that you mention - you're left with all of your source/development artifacts at runtime, unless you take explicit steps to remove them all.

Docker introduced multi-stage builds to somewhat alleviate this issue - it effectively allows you to "squash" multiple layers into one. But it doesn't eliminate the problem of needing to explicitly clean up.

So in my experience, the most common solution is indeed to build your artifact externally, and then COPY it into your production image.

That solves problem #1, but not #2. So go one step further - build your Docker image inside a Docker container! CI platforms are increasingly supporting this approach as a first-class concept - see e.g. Circle CI's Docker executor.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

In Docker, in general, you want to create an image of your software that contains all that is necessary for your Application to run on any machine. This is what Docker is used for: bind the Application and its dependencies into a single artifact so that it can run everywhere where Docker is installed.

The self-sufficient image is very handy when you use an orchestrator like Docker swarm. The orchestrator can run the container on any machine that is part of the network (i.e. the swarm) by pulling the image and starting a container. If nor the image neither the host contain all that it needs then the container fails.

There are cases where you need to change very easy the files inside the container as it runs, for example in development. In that case you mount a local directory from the host into the container (see volumes); in this way you just modify the files in the host and the modification is propagated immediately inside the container. Even in this case, your image should contain the files needed to run the Application on other machine; using a volume just hides them in the development environment.

Constantin Galbenu
  • 16,951
  • 3
  • 38
  • 54