Cardano logo
Cardano Stake Pool [PHL]

Creating a minimal Docker container for cardano-node

theodus - 2021/09/25



Not all stake pool operators use Docker containers to deploy cardano-node, and that's great. I think that a diverse set of infrastructure between pools is beneficial for the overall robustness of the Cardano network. But for those that do, this can hopefully be a useful reference. This could also be an additional reference for those that want to build the cardano-node from source.

First things first, the Dockerfile described in this post is on the PhillyStake GitHub at github.com/philly-stake/cardano-node and anyone can pull a public image of the container from Docker Hub at hub.docker.com/r/theodus/cardano-node .

If you're unfamiliar with Docker containers, they're a convenient way to package and deploy applications without having to manage the dependencies of the application on the host where they will be running.

IOHK actually has their own Docker image, described in the cardano-node README . We recommend using the Docker image for cardano-node provided by IOHK. The Docker image described below is for educational purposes only. Use it in production at your own risk!

  1. Start the build phase with the debian:latest base image. Also define the cardano-node, GHC, and Cabal versions we'll be using.

      FROM debian:latest AS build
    
      ARG VERSION="1.29.0"
      ARG GHC_VERSION="8.10.7"
      ARG CABAL_VERSION="3.6.0.0"
              
  2. Install all build dependencies and set the working directory to /opt.

      RUN apt-get update && apt-get install -y \
        autoconf \
        automake \
        build-essential \
        curl \
        git \
        libffi-dev \
        libgmp-dev \
        libssl-dev \
        libtinfo-dev \
        libsystemd-dev \
        libncursesw5 \
        libtool \
        pkg-config \
        zlib1g-dev
    
      WORKDIR /opt
              
  3. Install Haskell & Cabal using ghcup.

      ENV BOOTSTRAP_HASKELL_NONINTERACTIVE=1
      RUN curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
      ENV PATH=${PATH}:/root/.local/bin
      ENV PATH=${PATH}:/root/.ghcup/bin
      RUN ghcup upgrade && \
        ghcup install ghc ${GHC_VERSION} && ghcup set ghc ${GHC_VERSION} && \
        ghcup install cabal ${CABAL_VERSION} && ghcup set cabal ${CABAL_VERSION} && \
        cabal update
              
  4. Build and install the required libsodium version.

      RUN git clone https://github.com/input-output-hk/libsodium \
        && cd libsodium \
        && git checkout 66f017f1 \
        && ./autogen.sh \
        && ./configure \
        && make -j16 \
        && make install
      ENV LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
      ENV PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH"
              
  5. Build and install input-output-hk/cardano-node

      RUN git clone https://github.com/input-output-hk/cardano-node.git \
        && cd cardano-node \
        && git fetch --all --recurse-submodules --tags \
        && git tag && git checkout tags/${VERSION} \
        && cabal configure --with-compiler=ghc-${GHC_VERSION} \
        && echo "package cardano-crypto-praos" >>  cabal.project.local \
        && echo "  flags: -external-libsodium-vrf" >>  cabal.project.local \
        && cabal build -j16 all \
        && mkdir /opt/bin/ \
        && cp -p dist-newstyle/build/x86_64-linux/ghc-${GHC_VERSION}/cardano-node-${VERSION}/x/cardano-node/build/cardano-node/cardano-node /opt/bin/ \
        && cp -p dist-newstyle/build/x86_64-linux/ghc-${GHC_VERSION}/cardano-cli-${VERSION}/x/cardano-cli/build/cardano-cli/cardano-cli /opt/bin/
              
  6. Create a new minimal container and define the user for this container.

      FROM debian:bullseye-slim
    
      ARG USERNAME="cardano"
      ARG USERID="1000"
      ARG GROUPID="1024"
              
  7. Copy and install the created executable and necessary libraries from the build stage.

      COPY --from=build /usr/local/lib/libsodium.so* /usr/local/lib/
      COPY --from=build /opt/bin/cardano-cli /usr/local/bin/
      COPY --from=build /opt/bin/cardano-node /usr/local/bin/
    
      ENV LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
              
  8. Install the remaining dependencies for running cardano-node.

      RUN apt-get update && apt-get install -y --no-install-recommends \
        netbase \
        libc-dev \
        && rm -rf /var/lib/apt/lists/*
              
  9. Create the user.

      RUN groupadd -g ${GROUPID} -r ${USERNAME} \
        && useradd --no-log-init -r --gid ${GROUPID} -u ${USERID} ${USERNAME} \
        && mkdir /home/${USERNAME} \
        && chown -R ${USERID}:${GROUPID} /home/${USERNAME} \
        && echo ${USERNAME}:${USERNAME} | chpasswd
    
      USER ${USERNAME}
              
  10. Set the entrypoint.

      ENTRYPOINT ["cardano-node"]
              


Now that we've defined the Docker container, here's an example for running the cardano-node within the container. This assumes all configuration files are placed in /var/lib/cardano on the host with appropriate permissions for the cardano user (UID 1000, GID 1024).

  docker run --rm --name cardano-node \
    -v /var/lib/cardano:/home/cardano/ \
    -p 3000:3000 \
    -p 12798:12798 \
    theodus/cardano-node run \
      --host-addr 0.0.0.0 \
      --port 3000 \
      --database-path /home/cardano/cardano-node/db/ \
      --socket-path /home/cardano/cardano-node/db/node.socket \
      --config /home/cardano/cardano-node/mainnet-config.json \
      --topology /home/cardano/cardano-node/mainnet-topology.json