I have a fairly run-of-the-mill Dream project. When I do incremental compiles with dune, it’s super-fast. When I do a Docker build and the previous build’s cache is invalidated, it takes about 16 minutes to download and build my dependency cone:
This is on macOS 12.6 M1. The Dockerfile is nothing crazy, just a few layers:
# https://hub.docker.com/layers/ocaml/opam/ubuntu-22.04-ocaml-4.14/images/sha256-73f7c5dd28f7b757de325d915562a3f89903a64e763c0e334914fb56e082f5cb?context=explore
FROM ocaml/opam:ubuntu-22.04-ocaml-4.14@sha256:73f7c5dd28f7b757de325d915562a3f89903a64e763c0e334914fb56e082f5cb as build-deps
RUN sudo apt-get update && sudo apt-get install -y libev-dev libssl-dev libsqlite3-dev pkg-config nodejs
WORKDIR zk
ADD zk.opam ./
RUN opam init
RUN opam exec -- opam update && opam exec -- opam install --deps-only --with-test -y .
Does this match up with people’s experiences? Any suggestions on how to cache the opam deps in a more granular way so that changing a single dependency doesn’t blow away the entire cache?
EDIT: wait, I just remembered, I get a message in the logs about upgrading to the latest opam which apparently has many performance improvements. I’m happy to upgrade but kinda puzzled that I would need to in the first place, because I’m using an image that was uploaded 5 days ago with pretty recent versions of Ubuntu and OCaml: Docker
Thanks! I think the key here is running opam install dep1 dep2 ... depN directly in the Dockerfile instead of allowing it to install the deps listed in my_project.opam file. I took a middle ground, I figured since Dream pulls in the largest dependency cone out of everything installed, so doing RUN opam exec -- opam install dream in an earlier layer should cache almost all the dependencies.
And that does work, although in a later layer when I install the rest of the deps, annoyingly some of the earlier-installed ones are forced to recompile.
But at least now the build time is down to about 6 minutes even if I change anything in my opam file.