This repository contains instructions on how to set up a Zcash node in a Docker container, employing Google's gVisor sandbox.
These notes are written relative to a Docker as packaged in Ubuntu 19.04 (disco) but should be easily portable to other Linux distributions as well. The best gVisor sandboxing relies on KVM (available in recent AMD/Intel CPUs), but there is also a (slower and not as thoroughly isolated) ptrace-based sandbox.
First, install Docker, download a pre-built gVisor binary and place it in /usr/local/bin:
sudo apt install docker.io
wget https://storage.googleapis.com/gvisor/releases/nightly/latest/runsc
wget https://storage.googleapis.com/gvisor/releases/nightly/latest/runsc.sha512
sha512sum -c runsc.sha512
# outputs "runsc: OK"
chmod a+x runsc
sudo mv runsc /usr/local/bin
gVisor is still in development and nightly versions sometimes contain regressions; you can download specific versions by replacing latest above with a specific yyyy-mm-dd date.
Next, add runsc runtime to your Docker configuration (see gVisor's README for more details). As I started with default Docker configuration, it amounted to creating /etc/docker/daemon.json with the following contents:
{
"default-runtime": "runsc",
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc",
"runtimeArgs": [
"--platform=kvm"
]
}
}
}
The only way to instruct Docker to use gVisor in docker build process, is to have the runsc runtime be the default runtime (e.g., as in the config above). If this is not desired, you should remove the "default-runtime": "runsc" line. With runsc as the default runtime the --runtime=runsc option in the docker run commands is superfluous but you might want to keep it to avoid running without runsc by accident (for example, in case you change dockerd config for some reason).
Finally, restart Docker daemon so that your changes take effect: sudo systemctl restart docker.
You might also want to add your own user to the docker group (sudo usermod -a -G docker $USER) and either relogin or execute the following commands within su $USER to make sure that your supplementary groups are updated (and docker appears in the output of id).
Test that gVisor is working by trying to launch a container:
docker run --runtime=runsc -it --rm hello-world
- First, clone this repository:
git clone https://github.com/madars/zcash-docker.git
- Then instruct Docker to build Zcash software and a container for running a Zcash node. On my machine the build process took about 30 minutes, so now is a good time to grab a lunch!
docker build --tag=my-zcash-node zcash-docker
You can choose the tag freely; similar for the directories in the next step.
(If your build process fails due to a network error, you might be affected by a recent Debian sid/Ubuntu disco iptables/docker packaging bug. See below for a work-around.)
- Create local directories for storing persistent data, i.e., the Zcash blockchain and the Zcash system parameters:
mkdir dot-zcash zcash-params
(Tip: when running mainnet and testnet nodes you can share the zcash-params volume between the two, and save ~1.6 GB of disk space.)
- Launch the Zcash node container we just built:
docker run --runtime=runsc -it --rm \
-v $PWD/zcash-params:/home/user/.zcash-params \
-v $PWD/dot-zcash:/home/user/.zcash \
my-zcash-node:latest /bin/bash
Adding --rm makes container be deleted upon exit; that's safe for us as all state lives in the volumes we attach.
- Finally, run
zcash-fetch-params, create.zcash/zcash.conf(if you are satisfied with defaults, an empty one works!), and launchzcashd:-)
-
We currently build the most recent git master version of Zcash. If you want a particular release version, you should specify that version in the Dockerfile by editing (
ENV ZCASH_VERSION=...line). -
We build or containers using Alpine Linux as a base. Instead of more commonly used
glibc, Alpine usesmusllibc which emphasizes POSIX compatibility. Such libc diversity helps with software quality. As of mid-January 2019, mainlinerust/cargo(includingrustup-downloaded nightlies) were incompatible withmusllibc. Therefore, at least for now, our images are build fromalpine:latestbase and its packaging of Rust. In case Zcash git master version starts to require a more recent version ofrust/cargo(not the case in mid-March 2019), you might want to adjust the Dockerfile to usealpine:edgeas a base. We might switch torustupbinaries in the future. -
The only patch we apply to Zcash adds
--with-pictolibgmpMakefile. Without this you getlibgmp.a(dive_1.o): warning: relocation against `__gmp_binvert_limb_table' in read-only section `.text'during linking. We should consult with Zcash upstream about this. -
The node container includes man pages and bash completions for Zcash software (you can run
. /etc/profileto enable these in bash; Alpine does not provide a~/.profileskeleton.) -
The final node image weighs about 540MB, whereas the peak builder image uses about 4.8 GB of space. The latter can be safely deleted, e.g. by a
docker images -f "dangling=true" -q+docker rmicombo. -
This is the first
DockerfileI have written so I'm probably not doing things "the Docker way". Patches and comments welcome! -
A recent iptables change broke outgoing network connectivity for Docker in Ubuntu disco. Potential work-around is to use
iptables-legacysystem-wide (e.g. viaupdate-alternatives --set iptables /usr/sbin/iptables-legacy) and to flush nftables ruleset potentially clobbered byiptables-nftrules (nft flush ruleset)