Haskell tooling in a Docker container

Create a Docker image with Debian Linux in which you can install and use Haskell tooling (e.g. Stack) and that uses your computer's native GUI. This can be useful because using Stack under NixOS can be somewhat cumbersome.

On the Docker host computer, if you run the container manually, do not forget to use xhost to allow access to the X-server, as follows.

1xhost +LOCAL:

See the Makefile for an easier way to to build and start the container.

The below project is on github: maridonkers/haskell-tooling-docker. I use it under NixOS.

Shared files with container

This is done via bind mounts for the ~/src and ~/Development subdirectories (change these for your environment). Check if your uid is 1000 via the id command. If it is not then find and change all uid instances in the files of the project and change the 1000 to your uid value.

Define the image via a Dockerfile

The Dockerfile:

 1# Haskell tooling (a.o. stack & cabal) in a Docker container.
 2# See e.g.: https://docs.haskellstack.org/en/stable/install_and_upgrade/
 3# To manually set up your tooling from within this container (`make shell`).
 4
 5FROM debian:latest
 6
 7# Timezone is also in docker-compose file.
 8ENV HOME /root
 9ENV TZ Europe/Amsterdam
10ENV SHELL /bin/bash
11
12# Install dependencies that are likely required for the tooling.
13RUN apt-get update; \
14    apt-get upgrade -y; \
15    apt-get install -y procps lsof sudo curl less vim-nox zip git build-essential \
16                       g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils \
17                       pkg-config zlib1g-dev git gnupg netbase; \
18    apt-get clean
19
20RUN sed -i "s#\smain\s*\$# main contrib non-free#" /etc/apt/sources.list
21
22# https://vsupalov.com/docker-build-pass-environment-variables/
23# ARG DOCKER_HASKELL_PASSWORD
24# ENV ENV_DOCKER_HASKELL_PASSWORD=$DOCKER_HASKELL_PASSWORD
25
26# Create a non-root account to run Haskell tooling with.
27RUN useradd -ms /bin/bash --uid 1000 --gid 100 haskell; \
28    usermod -G audio,video,sudo haskell; \
29    echo "haskell:putapasswordhereforsudo" | chpasswd
30    # TODO Doesn't work?
31    # echo "haskell:$ENV_DOCKER_HASKELL_PASSWORD" | chpasswd
32
33USER haskell
34WORKDIR /home/haskell
35RUN mkdir -p /home/haskell/bin
36ENV HOME /home/haskell
37ENV PATH="${PATH}:/home/haskell/bin:/home/haskell/.local/bin"
38ENV LC_ALL=C.UTF-8
39ENV DISPLAY=":0"
40
41# ENTRYPOINT ["/bin/bash"]

The Docker compose file

 1version: "2.0"
 2services:
 3  "haskell":
 4    image: tooling-haskell
 5    build: .
 6    stdin_open: true
 7    tty: true
 8    privileged: true
 9    ipc: host
10    # https://docs.docker.com/compose/environment-variables/
11    # TODO Doesn't work?
12    environment:
13      - TZ=Europe/Amsterdam
14      # - ENV_DOCKER_HASKELL_PASSWORD=${DOCKER_HASKELL_PASSWORD}
15    network_mode: host
16    volumes:
17      - "./.stack/:/home/haskell/.stack/:rw"
18      - "./.cabal:/home/haskell/.cabal:rw"
19      - "./.local/:/home/haskell/.local/:rw"
20      - "./usr/local/:/usr/local/:rw"
21      - "~/src/:/home/haskell/src/:rw"
22      - "~/Development/:/home/haskell/Development/:rw"
23      - "~/.Xauthority:/home/haskell/.Xauthority:rw"
24      - "/tmp/.X11-unix/:/tmp/.X11-unix/:ro"

Makefile

Use the make command to build the Docker container and bring it up. The Makefile is shown below. Initially use make rebuild to create the container. Then simply use make to run it in the background and make shell for an interactive shell. To bring it down completely, use make down.

 1# Brings up the Haskell Tooling as a Docker container.
 2# Use make shell to get an interactive shell.
 3#
 4
 5CONTAINER="docker_haskell_1"
 6
 7all: up 
 8
 9up:
10    xhost +LOCAL:
11    mkdir -p .cabal .local .stack usr/local
12    docker-compose up --detach
13
14down:
15    sync
16    docker-compose down
17
18# If problems persist after a force-down then manually restart Docker daemon.
19force-down:
20    sync
21    docker rm -f $(CONTAINER)
22
23ls:
24    docker ps -a
25
26images:
27    docker images
28
29rebuild:
30    docker-compose build --no-cache
31
32build:
33    docker-compose build
34
35attach:
36    xhost +LOCAL:
37    docker attach $(CONTAINER)
38
39shell:
40    xhost +LOCAL:
41    docker exec -it $(CONTAINER) /bin/bash

Posts in this Series