fix(docker): allow the `zebra` user access to relevant dirs

When runnning a Zebra node using Docker without a privileged user, you won't be able to modify some files and directories, not even the ones in the current directory, as the `zebra` user has no permission to `/`.

The best way to solve this is making the `/opt/zebrad` the current `WORKDIR`. This also requires moving the `entrypoint.sh` from the root `/` directory to `/etc/zebrad` as this directory is used to save configuration, and other files.

An `APP_HOME` ARG is used as not all platforms where a Docker container is deployed allows writting permissions to the `/opt` directory. This allow some users to re-build the image with a custom `WORKDIR`
This commit is contained in:
Gustavo Valverde 2024-08-29 19:33:25 +01:00
parent 2b63b77644
commit f7cd3f8f81
1 changed files with 25 additions and 15 deletions

View File

@ -19,10 +19,14 @@ ARG FEATURES="default-release-binaries"
ARG TEST_FEATURES="lightwalletd-grpc-tests zebra-checkpoints" ARG TEST_FEATURES="lightwalletd-grpc-tests zebra-checkpoints"
ARG EXPERIMENTAL_FEATURES="" ARG EXPERIMENTAL_FEATURES=""
ARG APP_HOME="/opt/zebrad"
# This stage implements cargo-chef for docker layer caching # This stage implements cargo-chef for docker layer caching
FROM rust:bookworm as chef FROM rust:bookworm as chef
RUN cargo install cargo-chef --locked RUN cargo install cargo-chef --locked
WORKDIR /opt/zebrad
ARG APP_HOME
ENV APP_HOME=${APP_HOME}
WORKDIR ${APP_HOME}
# Analyze the current project to determine the minimum subset of files # Analyze the current project to determine the minimum subset of files
# (Cargo.lock and Cargo.toml manifests) required to build it and cache dependencies # (Cargo.lock and Cargo.toml manifests) required to build it and cache dependencies
@ -38,7 +42,7 @@ RUN cargo chef prepare --recipe-path recipe.json
# We set defaults for the arguments, in case the build does not include this information. # We set defaults for the arguments, in case the build does not include this information.
FROM chef AS deps FROM chef AS deps
SHELL ["/bin/bash", "-xo", "pipefail", "-c"] SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
COPY --from=planner /opt/zebrad/recipe.json recipe.json COPY --from=planner ${APP_HOME}/recipe.json recipe.json
# Install zebra build deps and Dockerfile deps # Install zebra build deps and Dockerfile deps
RUN apt-get -qq update && \ RUN apt-get -qq update && \
@ -90,7 +94,7 @@ ARG SHORT_SHA
# https://github.com/ZcashFoundation/zebra/blob/9ebd56092bcdfc1a09062e15a0574c94af37f389/zebrad/src/application.rs#L179-L182 # https://github.com/ZcashFoundation/zebra/blob/9ebd56092bcdfc1a09062e15a0574c94af37f389/zebrad/src/application.rs#L179-L182
ENV SHORT_SHA=${SHORT_SHA:-} ENV SHORT_SHA=${SHORT_SHA:-}
ENV CARGO_HOME="/opt/zebrad/.cargo/" ENV CARGO_HOME="${APP_HOME}/.cargo/"
# In this stage we build tests (without running then) # In this stage we build tests (without running then)
# #
@ -128,17 +132,16 @@ RUN cargo chef cook --tests --release --features "${ENTRYPOINT_FEATURES}" --work
# Undo the source file changes made by cargo-chef. # Undo the source file changes made by cargo-chef.
# rsync invalidates the cargo cache for the changed files only, by updating their timestamps. # rsync invalidates the cargo cache for the changed files only, by updating their timestamps.
# This makes sure the fake empty binaries created by cargo-chef are rebuilt. # This makes sure the fake empty binaries created by cargo-chef are rebuilt.
COPY --from=planner /opt/zebrad zebra-original COPY --from=planner ${APP_HOME} zebra-original
RUN rsync --recursive --checksum --itemize-changes --verbose zebra-original/ . RUN rsync --recursive --checksum --itemize-changes --verbose zebra-original/ .
RUN rm -r zebra-original RUN rm -r zebra-original
# Build Zebra test binaries, but don't run them # Build Zebra test binaries, but don't run them
RUN cargo test --locked --release --features "${ENTRYPOINT_FEATURES}" --workspace --no-run RUN cargo test --locked --release --features "${ENTRYPOINT_FEATURES}" --workspace --no-run
RUN cp /opt/zebrad/target/release/zebrad /usr/local/bin RUN cp ${APP_HOME}/target/release/zebrad /usr/local/bin
RUN cp /opt/zebrad/target/release/zebra-checkpoints /usr/local/bin RUN cp ${APP_HOME}/target/release/zebra-checkpoints /usr/local/bin
COPY ./docker/entrypoint.sh / COPY ./docker/entrypoint.sh /etc/zebrad/entrypoint.sh
RUN chmod u+x /entrypoint.sh
# Entrypoint environment variables # Entrypoint environment variables
ENV ENTRYPOINT_FEATURES=${ENTRYPOINT_FEATURES} ENV ENTRYPOINT_FEATURES=${ENTRYPOINT_FEATURES}
@ -147,7 +150,7 @@ ARG EXPERIMENTAL_FEATURES="shielded-scan journald prometheus filter-reload"
ENV ENTRYPOINT_FEATURES_EXPERIMENTAL="${ENTRYPOINT_FEATURES} ${EXPERIMENTAL_FEATURES}" ENV ENTRYPOINT_FEATURES_EXPERIMENTAL="${ENTRYPOINT_FEATURES} ${EXPERIMENTAL_FEATURES}"
# By default, runs the entrypoint tests specified by the environmental variables (if any are set) # By default, runs the entrypoint tests specified by the environmental variables (if any are set)
ENTRYPOINT [ "/entrypoint.sh" ] ENTRYPOINT [ "/etc/zebrad/entrypoint.sh" ]
# In this stage we build a release (generate the zebrad binary) # In this stage we build a release (generate the zebrad binary)
# #
@ -167,15 +170,14 @@ ARG FEATURES
RUN cargo chef cook --release --features "${FEATURES}" --package zebrad --bin zebrad --recipe-path recipe.json RUN cargo chef cook --release --features "${FEATURES}" --package zebrad --bin zebrad --recipe-path recipe.json
# Undo the source file changes made by cargo-chef, so the fake empty zebrad binary is rebuilt. # Undo the source file changes made by cargo-chef, so the fake empty zebrad binary is rebuilt.
COPY --from=planner /opt/zebrad zebra-original COPY --from=planner ${APP_HOME} zebra-original
RUN rsync --recursive --checksum --itemize-changes --verbose zebra-original/ . RUN rsync --recursive --checksum --itemize-changes --verbose zebra-original/ .
RUN rm -r zebra-original RUN rm -r zebra-original
# Build zebrad # Build zebrad
RUN cargo build --locked --release --features "${FEATURES}" --package zebrad --bin zebrad RUN cargo build --locked --release --features "${FEATURES}" --package zebrad --bin zebrad
COPY ./docker/entrypoint.sh / COPY ./docker/entrypoint.sh ./
RUN chmod u+x /entrypoint.sh
# This stage is only used when deploying nodes or when only the resulting zebrad binary is needed # This stage is only used when deploying nodes or when only the resulting zebrad binary is needed
# #
@ -183,6 +185,11 @@ RUN chmod u+x /entrypoint.sh
# binary from the `release` stage # binary from the `release` stage
FROM debian:bookworm-slim AS runtime FROM debian:bookworm-slim AS runtime
# Set the default path for the zebrad binary
ARG APP_HOME
ENV APP_HOME=${APP_HOME}
WORKDIR ${APP_HOME}
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
@ -220,13 +227,16 @@ ENV FEATURES=${FEATURES}
ENV ZEBRA_CONF_DIR=${ZEBRA_CONF_DIR:-/etc/zebrad} ENV ZEBRA_CONF_DIR=${ZEBRA_CONF_DIR:-/etc/zebrad}
ENV ZEBRA_CONF_FILE=${ZEBRA_CONF_FILE:-zebrad.toml} ENV ZEBRA_CONF_FILE=${ZEBRA_CONF_FILE:-zebrad.toml}
COPY --from=release /opt/zebrad/target/release/zebrad /usr/local/bin RUN mkdir -p ${ZEBRA_CONF_DIR} && chown ${UID}:${UID} ${ZEBRA_CONF_DIR} \
COPY --from=release /entrypoint.sh / && chown ${UID}:${UID} ${APP_HOME}
COPY --from=release ${APP_HOME}/target/release/zebrad /usr/local/bin
COPY --from=release ${APP_HOME}/entrypoint.sh /etc/zebrad
# Expose configured ports # Expose configured ports
EXPOSE 8233 18233 EXPOSE 8233 18233
# Update the config file based on the Docker run variables, # Update the config file based on the Docker run variables,
# and launch zebrad with it # and launch zebrad with it
ENTRYPOINT [ "/entrypoint.sh" ] ENTRYPOINT [ "/etc/zebrad/entrypoint.sh" ]
CMD ["zebrad"] CMD ["zebrad"]