I have written a Haskell program that runs with a very specific version of Cabal and GHC. What is the best way to distribute it within a Docker container?
I am trying the following, but the build process seems to freeze at the step “Installing GHC (this may take a while)”
# Use the official Alpine Linux image
FROM alpine:latest
# Install necessary dependencies
RUN apk update && apk add --no-cache \
bash curl git make m4 gcc g++ ocaml \
ocaml-compiler-libs opam findutils \
linux-headers gmp-dev \
binutils-gold libc-dev libffi-dev musl-dev ncurses-dev perl tar xz
# download and install ghcup
RUN curl -L https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup -o /usr/bin/ghcup && \
chmod +x /usr/bin/ghcup
ENV PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
RUN ghcup install cabal 3.10.2.1 && \
ghcup install ghc 9.4.8 && \
ghcup set 9.4.8
If your goal is to distribute the specific versions of GHC and Cabal, then this should be fine. Given that you are using Alpine, you may want to check out benz0li/ghc-musl for inspiration. You may also want to check out the Dockerfile in one of my projects, which does some things to reduce the size of the image.
If your goal is to distribute your program, then you may want to configure a multi-stage build and copy only your program and its dependencies into the final image.
I don’t really understand the purpose of the ghc-musl images.
I think that ghc-musl images are convenient for use in software that integrates with Docker. For example, VS Code Dev Containers and Stack’s Docker integration are easy to use with Docker containers.
@benz0li can probably explain the purpose better, however.
Both GHC and GHCup support alpine linux.
Thank you very much for your work on GHCup. I enjoy using it in general, and the working Alpine builds are great!
If you’re worried about space, ghcup gc --help has some tricks.
Indeed. The Dockerfile that I linked to does the following:
Disables apk cache
Removes unneeded *_p.a and *.p_hi files
Uses ghcup gc
Removes ghcup, as any further GHCup usage warrants building a new image
I deleted the containers/images which were lingering on my machine and tried rebuilding. I am getting the following error this time:
➜ alexee git:(main) ✗ sudo docker build --progress=plain -t alexee .
#0 building with "desktop-linux" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 2.18kB done
#1 DONE 0.0s
#2 [internal] load metadata for docker.io/library/alpine:latest
#2 DONE 0.0s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [1/4] FROM docker.io/library/alpine:latest
#4 DONE 0.0s
#5 [2/4] RUN apk update && apk add --no-cache bash curl git make m4 gcc g++ ocaml ocaml-compiler-libs opam findutils linux-headers gmp-dev binutils-gold libc-dev libffi-dev musl-dev ncurses-dev perl tar xz
#5 CACHED
#6 [3/4] RUN curl -L https://downloads.haskell.org/~ghcup/x86_64-linux-ghcup -o /usr/bin/ghcup && chmod +x /usr/bin/ghcup
#6 CACHED
#7 [4/4] RUN ghcup install cabal 3.10.2.1 && ghcup install ghc 9.4.8 && ghcup set 9.4.8
#7 0.840 [ Info ] downloading: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-0.0.8.yaml as file /root/.ghcup/cache/ghcup-0.0.8.yaml
#7 0.907 % Total % Received % Xferd Average Speed Time Time Time Current
#7 0.907 Dload Upload Total Spent Left Speed
100 454k 100 454k 0 0 2639k 0 --:--:-- --:--:-- --:--:-- 2644k
#7 1.232 [ Info ] downloading: https://downloads.haskell.org/~ghcup/unofficial-bindists/cabal/3.10.2.1/cabal-install-3.10.2.1-x86_64-linux-alpine319.tar.xz as file /root/.ghcup/tmp/ghcup-363b9854eb378800/cabal-install-3.10.2.1-x86_64-linux-alpine319.tar.xz
#7 1.237 % Total % Received % Xferd Average Speed Time Time Time Current
#7 1.237 Dload Upload Total Spent Left Speed
100 7543k 100 7543k 0 0 22.3M 0 --:--:-- --:--:-- --:--:-- 22.3M
#7 1.575 [ Info ] verifying digest of: cabal-install-3.10.2.1-x86_64-linux-alpine319.tar.xz
#7 1.629 [ Info ] Unpacking: cabal-install-3.10.2.1-x86_64-linux-alpine319.tar.xz to /root/.ghcup/tmp/ghcup-469a8ee054f91903
#7 2.207 [ Info ] Installing cabal
#7 2.254 [ Info ] Cabal installation successful
#7 2.254 [ Info ] cabal run is currently partially broken on Windows, please see https://github.com/haskell/cabal/issues/9334
#7 2.416 [ Warn ] New cabal version available. If you want to install this latest version, run 'ghcup install cabal 3.12.1.0'
#7 2.423 [ Info ] downloading: https://downloads.haskell.org/~ghc/9.4.8/ghc-9.4.8-x86_64-alpine3_12-linux.tar.xz as file /root/.ghcup/tmp/ghcup-f378398765729087/ghc-9.4.8-x86_64-alpine3_12-linux.tar.xz
#7 2.429 % Total % Received % Xferd Average Speed Time Time Time Current
#7 2.429 Dload Upload Total Spent Left Speed
100 202M 100 202M 0 0 26.6M 0 0:00:07 0:00:07 --:--:-- 28.4M
#7 10.01 [ Info ] verifying digest of: ghc-9.4.8-x86_64-alpine3_12-linux.tar.xz
#7 10.98 [ Info ] Unpacking: ghc-9.4.8-x86_64-alpine3_12-linux.tar.xz to /root/.ghcup/tmp/ghcup-7f0c7cf4e3a8c8bf
#7 28.46 [ Info ] Installing GHC (this may take a while)
#7 29.86
#7 29.86
#7 29.86
#7 29.86
#7 29.86
#7 51.57 [ Error ] [GHCup-00841] Process "gmake" with arguments ["DESTDIR=/root/.ghcup/tmp/ghcup-b8f43f0690cb0035",
#7 51.57 [ ... ] "install"] failed with exit code 2.
#7 51.57 [ Error ] Also check the logs in /root/.ghcup/logs
#7 ERROR: process "/bin/sh -c ghcup install cabal 3.10.2.1 && ghcup install ghc 9.4.8 && ghcup set 9.4.8" did not complete successfully: exit code: 3
------
> [4/4] RUN ghcup install cabal 3.10.2.1 && ghcup install ghc 9.4.8 && ghcup set 9.4.8:
28.46
29.86
29.86
29.86
29.86
29.86
51.57 [ Error ] [GHCup-00841] Process "gmake" with arguments ["DESTDIR=/root/.ghcup/tmp/ghcup-b8f43f0690cb0035",
51.57 [ ... ] "install"] failed with exit code 2.
51.57 [ Error ] Also check the logs in /root/.ghcup/logs
------
Dockerfile:17
--------------------
16 |
17 | >>> RUN ghcup install cabal 3.10.2.1 && \
18 | >>> ghcup install ghc 9.4.8 && \
19 | >>> ghcup set 9.4.8
20 |
--------------------
ERROR: failed to solve: process "/bin/sh -c ghcup install cabal 3.10.2.1 && ghcup install ghc 9.4.8 && ghcup set 9.4.8" did not complete successfully: exit code: 3
View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/tsdhj1ikzwp4k995pqm42up61
These are the contents of ghc-make.log
278b3e61038f:~/.ghcup/logs# tail ghc-make.log
# The rts package doesn't actually supply haddocks, so we stop advertising them
# altogether.
((echo "system-cxx-std-lib" | grep rts) && (cat '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf.copy' | sed 's|haddock-.*||' > '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf.copy.copy')) || (cat '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf.copy' > '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf.copy.copy')
# We finally replace the original file.
mv '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf.copy.copy' '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf'
# Fix the mode, in case umask is set
chmod 644 '/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d/system-cxx-std-lib-1.0.conf'
'/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/bin/ghc-pkg' --global-package-db "/root/.ghcup/tmp/ghcup-89fc5029c36a1a48/root/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/package.conf.d" recache
rosetta error: failed to open elf at /lib/ld-musl-x86_64.so.1
gmake: *** [Makefile:232: update_package_db] Trace/breakpoint trap
The multi-arch (linux/amd64, linux/arm64/v8) quay.io/benz0li/ghc-musl images were created as a replacement for the utdemir/ghc-musl images (linux/amd64 only) to build the statically linked Linux amd64 and arm64 binary releases of Pandoc. Back in 2021 there were no Linux arm64 bindists of GHC available.
My reason for asking is that I tried to use the GHC project’s own GHC 9.8.2 for Alpine Linux 3.18/AArch64 in an Alpine Linux 3.19.1 VM on macOS/AArch64 to build a statically-linked Stack, but it fell over.
I was hoping that the official Alpine Linux[/AArch64] releases would work correctly – and make my project obsolete.