Recommended recipe for deploying a Julia app in Docker with efficient precompilation?

Now that Julia 1.9/10 precompilation is doing more the first time a package is used, I’m seeing rather slow (7-8 minutes) restarts on a production docker image of my Julia app. When I run it locally with packages that have already been precompiled, the startup time is much faster.

Is there a recommended way to build Julia docker images that will

  1. Do all precompilation during image creation rather than when a image is run, and
  2. Cache as much dependency precompilation as possible, so that rebuilding a docker image only needs to update the precompilation for my app’s own code?

Simply running Pkg.instantiate in your project should do the trick. I.e something like

COPY .... # copy the sources from your project into the Docker image
RUN julia --project="/path/to/my/project" \
          -e "import Pkg; Pkg.instantiate()"

I’m less sure about this one. Perhaps you could copy the Project.toml file from your project (and perhaps also the Manifest.toml if you version it) to a temporary directory in the Docker image in an earlier stage, and Pkg.instantiate it at that time. This way, Docker should cache the results from this stage (including all precompiled packages) and when you later instantiate your real project, Julia/Pkg should find most of the dependencies already precompiled (provided their versions didn’t change inbetween).

4 Likes

Thanks! That works well and for the caching, I just copied over the Project.toml and Manifest.toml before calling Pkg.instantiate() and then copied all other project source files after. Rebuilding after source changes that don’t touch the *toml files now takes 1-2 seconds.

3 Likes

I have a solution that allows you to benefit from precompilation cache even if you are building on a different machine!

1 Like