This provides all of the necessary files to build your own lightweight non-root
container image based on scratch
that provides dcrd
, dcrctl
,
promptsecret
and gencerts
.
The approach used by the primary Dockerfile
is to employ a multi-stage build
that downloads and builds the latest source code, compresses the resulting
binaries, and then produces a final image based on scratch
that only includes
the Decred-specific binaries.
The provided Dockerfile
places a strong focus on security as follows:
- Runs as a non-root user
- Uses a static UID:GID of 10000:10000
- Note that using UIDs/GIDs below 10000 for container users is a security risk on several systems since a hypothetical attack which allows escalation outside of the container might otherwise coincide with an existing user's UID or existing group's GID which has additional permissions
- The image is based on
scratch
image (aka completely empty) and only includes the Decred-specific binaries which means there is no shell or any other binaries available if an attacker were to somehow manage to find a remote execution vulnerability exploit in a Decred binary
-
DECRED_DATA
(Default:/home/decred
):
The directory where data is stored inside the container. This typically does not need to be changed. -
DCRD_NO_FILE_LOGGING
(Default:true
):
Controls whether or not dcrd additionally logs to files underDECRED_DATA
. Logging is only done via stdout by default in the container since that is standard practice for containers. -
DCRD_ALT_DNSNAMES
: (Default: None) Adds alternate server DNS names to the server certificate that is automtically generated for the RPC server. This is important when attempting to access the RPC from external sources because TLS is required and clients verify the server name matches the certificate.
The following are typical commands to get up and going quickly. The remaining sections describe things more in depth.
Note: These series of commands have you define and use environment variables
in order to help make it clear exactly what every command line argument refers
to. However, this means that if you close the shell, the commands will no
longer work as written because those environment variables will no longer exist.
You may wish to replace all instances of "${...}"
with the associated concrete
value.
-
Build the base image with a tag to make it easy to reference later. These commands all use
yourusername/dcrd
for the image tag, but you should replaceyourusername
with your username or something else unique to you so you can easily identify it as being one of your images:$ DCRD_IMAGE_NAME="yourusername/dcrd" $ docker build -t "${DCRD_IMAGE_NAME}" -f contrib/docker/Dockerfile .
NOTE: This MUST be run from the main directory of the dcrd code repo.
-
Create a data volume and change its ownership to the user id of the user inside of the container so it has the necessary permissions to write to it:
$ docker volume create decred-data $ DECRED_DATA_VOLUME=$(docker volume inspect decred-data -f '{{.Mountpoint}}') $ sudo chown -R 10000:10000 "${DECRED_DATA_VOLUME}"
NOTE: The data volume only needs to be created once.
-
Run
dcrd
ontestnet
in the background using the aforementioned data volume to store the blockchain and configuration data along with a name to make it easy to reference later:$ DCRD_CONTAINER_NAME="dcrd-testnet" $ docker run -d --read-only \ --name "${DCRD_CONTAINER_NAME}" \ -v decred-data:/home/decred \ "${DCRD_IMAGE_NAME}" --testnet --altdnsnames "${DCRD_CONTAINER_NAME}"
-
View the output logs of
dcrd
with the docker logs command:$ docker logs "${DCRD_CONTAINER_NAME}"
$ docker stop "${DCRD_CONTAINER_NAME}"
$ docker start "${DCRD_CONTAINER_NAME}"
TODO: Explain about non-root permissions, network, etc
TODO: Finish documenting all the details here
- Dockerfile
Provides a user-contributed configuration file for building a container image that consists ofdcrd
,dcrctl
,gencerts
, andpromptsecret
along with exposed ports for dcrd's RPC server. It is based onscratch
and runs as a non-root container.
TODO: It would probably be nice to provide some variants such as:
Dockerfile.release
that either grabs the latest release code or checks out the latest release tag instead of building the master branchDockerfile.local
that builds an image using the code in the build context instead of cloning and building the latest master branch
Assuming the environment variables and configuration matches what was outlined in the quick start section:
$ docker run --rm --network container:"${DCRD_CONTAINER_NAME}" --read-only \
-v decred-data:/home/decred \
"${DCRD_IMAGE_NAME}" dcrctl --testnet getblockchaininfo
Assuming the environment variables and configuration matches what was outlined in the quick start section:
TODO: Would need to remove existing container and start new one with --network decred
as follows...
NOTE: The network volume only needs to be created once.
$ docker network create decred
$ docker stop "${DCRD_CONTAINER_NAME}"
$ docker rm "${DCRD_CONTAINER_NAME}"
$ docker run -d --read-only \
--network decred \
--name "${DCRD_CONTAINER_NAME}" \
-v decred-data:/home/decred \
"${DCRD_IMAGE_NAME}" --testnet --altdnsnames "${DCRD_CONTAINER_NAME}"
$ docker run --rm --read-only \
--network decred \
-v decred-data:/home/decred \
"${DCRD_IMAGE_NAME}" dcrctl --testnet --rpcserver "${DCRD_CONTAINER_NAME}" getblockchaininfo
TODO: Needs to be running with port mapped...aka:
$ docker run -d --read-only \
--name "${DCRD_CONTAINER_NAME}" \
-v decred-data:/home/decred \
-p 127.0.0.1:19109:19109 \
"${DCRD_IMAGE_NAME}" --testnet --altdnsnames "${DCRD_CONTAINER_NAME}"
TODO: From other machine such as the host machine (not inside a docker container)...
TODO: sudo required here because the data volume needs the perms of the uid/gid
inside the container which the local user on the host won't have access too..
could alternatively use docker cp
to copy the cert and conf file out of the container...
$ dcrdrpcuser=$(sudo cat "${DECRED_DATA_VOLUME}/.dcrd/dcrd.conf" | grep rpcuser= | cut -c9-)
$ dcrdrpcpass=$(sudo cat "${DECRED_DATA_VOLUME}/.dcrd/dcrd.conf" | grep rpcpass= | cut -c9-)
$ sudo curl --cacert "${DECRED_DATA_VOLUME}/.dcrd/rpc.cert" --user "${dcrdrpcuser}:${dcrdrpcpass}" \
--data-binary '{"jsonrpc":"1.0","id":"1","method":"getbestblock","params":[]}' \
https://127.0.0.1:19109
TODO
TODO
TODO