5

I am dockerizing our applications to have the environments recreatable. As a process of dockerizing, we will be required to do the below steps:

  • Build the application.
  • Prepare the environment as the container.
  • Deploy the application to the container.

Is it fine to have the application build, inside the docker, as part of docker building? In that way we need not install the build dependencies in local.

But the trade-off is, we have to build the complete docker for the even a small code change that we build. I understand this can be optimized to a level with multi-staged build.

1

4 Answers 4

4

I understand this can be optimized to a level with multi-staged build.

This is an understatement - you do not "optimize" that, but that's just the way you do it.

To answer your question: yes, by all means run the build inside a docker container. How else would you be sure that at build time every library or dependency is the same? There is no reason whatsoever not to do it.

Of course you need to pay a bit of attention when writing the Dockerfile. Ideally, whatever you change in your source code day-to-day, the only thing that happens when you re-run your build is the very last step of actually compiling your code and doing whatever it is you do with it afterwards (creating your deliverable archive...).

You need to use multi-staged builds afterwards to get rid of all the intermediate steps, and especially all the compile-time-only components (and it's pretty easy as well).

Note that there's usually some parts of your setup which are used by both the compile-time and run-time (unless you are just creating a .war file and sending that off to a webserver). I.e., if you have a ruby-on-rails application, the "ruby-on-rails" part could well be shared between compile-time and run-time. You want to make sure to put everything that is shared in this way very early in the process, and have a clean cut-off point that you can use as a FROM later on, copying the compiled files in as needed.

2

There are significant performance gains to be had in some projects by not building inside the docker containers. If you are building multiple images you can benefit from shared package caches and shared build artefacts which is not possible when you are building every app in isolation inside it's own container.

In a previous project I worked on, we were building the same shared libraries 5 times in 5 different images. Building and running for example tests outside docker really helped speed up our CI/CD.

This is especially true when you are using cloud pipelines like Github actions where downloading and re-hydrating a full docker cache can take as much time as building it from scratch.

1

The answer depends on your deployment. It sounds like you are wanting to create a generic "environment image" and then do something like mount whatever you want to run with a volume. In this case a multi stage build like doesn't much for you but it may still benefit you.

If you are going to containerize each application then a multi staged build makes the most sense I think. It does keep your final images "clean" since the build was done in a separate container.

The "trade-off" you mentioned should not be an issue. You should work to get your infrastructure to a point where deploying a new image isn't such a big deal therefore negating this problem.

1

But the trade-off is, we have to build the complete docker for the even a small code change that we build.

No, not usually. Generally in your Dockerfile the application build process will be after all of the system configuration (installing libraries and such), and so Docker will reuse cached layers for those.

If your concern is that you'll have to rebuild the entire application each time, rather than use some sort of build object caching in your build system, then yes, that does happen. In development you can often mitigate this by using live-reload auto-rebuild systems that watch the filesystem for changes, combined with a Docker directory mount of the code from the local development machine. This way when a developer saves a file, the changes are propagated to the running container, where the autobuild notices and rebuilds and restarts the application.

The other thing you should be careful of are bloated images. If you install a bunch of development tools in the container, then even if you uninstall them later in the Dockerfile, the resultant image will include layers with them, which can increase the overall size of the image.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.