Mounting .cabal/store in a docker volume

Hi there,

Is it feasible to share the .cabal/store betweena host machine an a docker container? Tha use case is that I have a project in my host machine, but I want to build it within a docker container without the need of downloading and building a huge amount of dependencies.

I create a docker image with ghc and cabal, then run the container with two mount volumes: one for the source code and one pointing to the cabal’s store

docker run -v $(pwd):/usr/local/project -v ${HOME}/.cabal/store/:/usr/local/.cabal/store:ro -it my-imge

I mount the store’s volume as read-only (:ro) since I would expect that there is no need to do any other thing in the cabal store other than reading from it, but I might be wrong.

Within the docker’s running container I build the project using a freeze file and with dry-run just to see if It will download something.

# container's console
> cabal update
> cabal --store-dir=/usr/local/.cabal/store build all --dry-run --builddir=dist-newstyle-docke --project-file=cabal.docker-build.project 
Resolving dependencies...
Build profile: -w ghc-9.4.8 -O1
In order, the following would be built (use -v for more details):
- zip-2.0.0 (lib) (requires download & build)
 - my-project-componets (lib:my-project) (first run)
 - my-project (exe:my-project) (first run)

Surprisingly, one hackage dependency needs to be downloaded. The surprise comes from the fact that the project is already built outside the containers with the same freeze file, so I’d expect all dependencies to be on the store.

So, if something needs to be downloaded, for sure the store can’t be read-only, hence I spin up the container again mounting the store as normal, an then building the project. Now the build of the the zip library fails

# after docker run -v ${HOME}/.cabal/store/:/usr/local/.cabal/store ...
> cabal --store-dir=/usr/local/.cabal/store build all --builddir=dist-newstyle-docker --project-file=cabal.advance-options.project
Starting     zip-2.0.0 (lib)
Building     zip-2.0.0 (lib)

Failed to build zip-2.0.0.
Build log (
/root/.cache/cabal/logs/ghc-9.4.8/zip-2.0.0-cc40d6442b9486f7cc8d5bf1e8eadd52dcafcd3ea12b53054cb809dd08a19618.log
):
Configuring library for zip-2.0.0..
Preprocessing library for zip-2.0.0..
Building library for zip-2.0.0..
[1 of 5] Compiling Codec.Archive.Zip.CP437 ( Codec/Archive/Zip/CP437.hs, dist/build/Codec/Archive/Zip/CP437.o, dist/build/Codec/Archive/Zip/CP437.dyn_o )
[2 of 5] Compiling Codec.Archive.Zip.Type ( Codec/Archive/Zip/Type.hs, dist/build/Codec/Archive/Zip/Type.o, dist/build/Codec/Archive/Zip/Type.dyn_o )

Codec/Archive/Zip/Type.hs:38:1: error:
    Could not find module ‘Data.CaseInsensitive’
    There are files missing in the ‘case-insensitive-1.2.1.0’ package,
    try running 'ghc-pkg check'.
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
   |
38 | import Data.CaseInsensitive (CI)
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.
.
more errors related to missing modules in zip's dependencies.

At this point I wonder if it is possible to share the cabal’s store between host and containerfor faster builds or we are doomed to re-build everything.

BTW: I’ve tried to copy the binary directly but It fails to execute (I think some template haskell is involved)

1 Like

the second error looks like a version mismatch in the case-insensitive built in your host machine and something required by text built inside the container.

Hic sunt leones…

But. the project has being build with the same freeze file (hence, same versions) in both environments.

Semi-related: GitHub - haskell-works/cabal-cache: CI assistant

You just have to make sure the distros are somewhat binary compatible (build and target host).

1 Like

um… my docker image is ubuntu, same as the host. Still doesn’t work. Well I guess I’ll just compile the whole thing in the docker container. Thanks for the help nevertheless

my only remaining guess is that Cabal doesn’t respect the freeze file in these conditions.

I guess there is something wrong in my cabal’s store. If I compile the programm within the docker container (i.e. not sharing the store between host and container) using the same freeze file, then It works… Super rare! Maybe it is some sort of external dependency / environment condition.