dcrd/contrib/docker/Dockerfile
Dave Collins 563e89099e
build/contrib: Improve docker support.
This significantly reworks the docker support to provide build a
lightweight non-root distroless container image based on scratch.  It
employs a multi-stage build that downloads and builds the latest source
code, compresses the resulting binaries, and then produces the final
image based on scratch that only includes the Decred-specific binaries.

It must be noted that there are some still remaining TODO items in the
documentation as well as the Dockerfile that will need to be handled by
a future commit, but the changes are being submitted now to allow
another contributor to finish up those aspects.

The following is an overview of the changes:

- Removes existing Dockerfile and Dockerfile.alpine
- Introduces a new Dockerfile under contrib/docker with the following
  properties:
  - 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
- Introduces code to build an entrypoint for the image since it is based
  on scratch and thus has no shell for that purpose
- Adds contrib/docker/README.md
- Updates README.md in the main directory to account for changes
  - There is still outstanding work to be done here and thus has several
    TODOs
- Updates contrib/README.md to call out the new addition
2021-09-18 13:17:41 -05:00

84 lines
2.6 KiB
Docker

# TODO: Needs some documentation here about the RPC server, logging via docker
# logs, mounting a volume, the conf file, etc...
###############
# Builder Stage
###############
# Basic Go environment with git, SSL CA certs, and upx.
# golang:1.17.1-alpine (linux/amd64)
FROM golang@sha256:13919fb9091f6667cb375d5fdf016ecd6d3a5d5995603000d422b04583de4ef9 AS builder
RUN apk add --no-cache git ca-certificates upx
# Empty directory to be copied into place in the production image since it will
# run as a non-root container and thus not have permissions to create
# directories or change ownership of anything outside of the structure already
# created for it.
RUN mkdir /emptydatadir
# New unprivileged user for use in production image below to improve security.
ENV USER=decred
ENV UID=10000
RUN adduser \
--disabled-password \
--gecos "" \
--home="/home/${USER}" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
"${USER}"
# Build dcrd and other commands it provides
WORKDIR /go/src/github.com/decred/dcrd
RUN git clone https://github.com/decred/dcrd . && \
CGO_ENABLED=0 GOOS=linux \
go install -trimpath -tags safe,netgo,timetzdata \
-ldflags="-s -w" \
. ./cmd/gencerts ./cmd/promptsecret
# Build dcrctl
WORKDIR /go/src/github.com/decred/dcrctl
RUN git clone https://github.com/decred/dcrctl . && \
CGO_ENABLED=0 GOOS=linux \
go install -trimpath -tags safe,netgo -ldflags="-s -w"
# Build entrypoint helper for the production image.
WORKDIR /go/src/github.com/decred/dcrd/contrib/docker/entrypoint
COPY ./contrib/docker/entrypoint/entrypoint.go .
RUN go mod init entrypoint && \
go mod tidy && \
CGO_ENABLED=0 GOOS=linux \
go install -trimpath -tags netgo,timetzdata -ldflags="-s -w" .
# Compress bins
RUN upx -9 /go/bin/*
##################
# Production image
##################
# Minimal scratch-based environment.
FROM scratch
ENV DECRED_DATA=/home/decred
#ENV DCRD_EXPOSE_RPC=false # TODO: Want something like this?
ENV DCRD_NO_FILE_LOGGING=true
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /go/bin/* /bin/
COPY --from=builder --chown=decred /emptydatadir /tmp
# Use an unprivileged user.
USER decred
# Ports for the p2p and json-rpc of mainnet, testnet, and simnet, respectively.
EXPOSE 9108 9109 19108 19109 18555 19556
ENTRYPOINT [ "/bin/entrypoint" ]
RUN [ "dcrd", "--version" ]
# TODO: Want this or not? I've seen conflicting info and I'm not a docker expert...
#VOLUME [ "/home/decred" ]