-
Notifications
You must be signed in to change notification settings - Fork 247
Expand file tree
/
Copy pathDockerfile
More file actions
271 lines (225 loc) · 10.5 KB
/
Copy pathDockerfile
File metadata and controls
271 lines (225 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# syntax=docker/dockerfile:1
# check=skip=UndefinedVar,UserExist # We use setpriv in the entrypoint instead of USER directive
# If you want to include a file in the Docker image, add it to .dockerignore.
#
# We use 4 (TODO: 5) stages:
# - deps: installs build dependencies and sets default values
# - tests: prepares a test image
# - release: builds release binaries
# - runtime: prepares the release image
# - TODO: Add a `monitoring` stage
#
# We first set default values for build arguments used across the stages.
# Each stage must define the build arguments (ARGs) it uses.
ARG RUST_VERSION=1.91.0
ARG FEATURES="default-release-binaries"
ARG UID=10001
ARG GID=${UID}
ARG USER="zebra"
ARG HOME="/home/${USER}"
ARG CARGO_HOME="${HOME}/.cargo"
ARG CARGO_TARGET_DIR="${HOME}/target"
# This stage prepares Zebra's build deps and captures build args as env vars.
# rust:1.91.0-trixie
FROM rust:${RUST_VERSION}-trixie@sha256:a0dba1c1b2c90585fc44421b55ddf8063323760dc644ba1d35f5b389ad3e8e14 AS deps
SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
# Make the build platform available as a variable
ARG BUILDPLATFORM
# Forwarded from the caller workflow so rustc, dpkg, and other tools honour it.
# A non-empty default is required: an empty value makes clang and usermod error.
ARG SOURCE_DATE_EPOCH=0
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
# Install zebra build deps
RUN apt-get -qq update && \
apt-get -qq install -y --no-install-recommends \
libclang-dev=1:19.0-* \
protobuf-compiler=3.21.12-* \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/log/* /var/cache/ldconfig/aux-cache
# Build arguments and variables
ARG CARGO_INCREMENTAL
ENV CARGO_INCREMENTAL=${CARGO_INCREMENTAL:-0}
ARG CARGO_HOME
ENV CARGO_HOME=${CARGO_HOME}
ARG CARGO_TARGET_DIR
ENV CARGO_TARGET_DIR=${CARGO_TARGET_DIR}
# This stage builds tests without running them.
#
# We also download needed dependencies for tests to work, from other images.
# An entrypoint.sh is only available in this step for easier test handling with variables.
FROM deps AS tests
SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
ARG SHORT_SHA
ARG FEATURES
ENV FEATURES=${FEATURES}
# Skip IPv6 tests by default, as some CI environment don't have IPv6 available
ARG SKIP_IPV6_TESTS
ENV SKIP_IPV6_TESTS=${SKIP_IPV6_TESTS:-1}
# This environment setup is almost identical to the `runtime` target so that the
# `tests` target differs minimally. In fact, a subset of this setup is used for
# the `runtime` target.
ARG UID
ENV UID=${UID}
ARG GID
ENV GID=${GID}
ARG USER
ENV USER=${USER}
ARG HOME
ENV HOME=${HOME}
RUN addgroup --quiet --gid ${GID} ${USER} && \
adduser --quiet --gid ${GID} --uid ${UID} --home ${HOME} ${USER} --disabled-password --gecos ""
# Set the working directory for the build.
WORKDIR ${HOME}
ARG CARGO_HOME
ARG CARGO_TARGET_DIR
# Download and install cargo-nextest, curl and librocksdb-dev.
RUN apt-get -qq update && \
apt-get -qq install -y --no-install-recommends librocksdb-dev=9.10.0-* curl=8.14.1-* && \
mkdir -p "${CARGO_HOME}/bin" && \
case ${BUILDPLATFORM:-linux/$(uname -m)} in \
"linux/amd64"|"linux/x86_64") ARCH="linux" ;; \
"linux/arm64"|"linux/aarch64") ARCH="linux-arm" ;; \
*) echo "Unsupported architecture: ${BUILDPLATFORM:-linux/$(uname -m)}"; exit 1 ;; \
esac && \
curl -LsSf "https://get.nexte.st/latest/${ARCH}" | tar zxf - -C "${CARGO_HOME}/bin" && \
apt-get -qq remove --purge -y curl && \
apt-get -qq autoremove -y && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/log/* /var/cache/ldconfig/aux-cache
# Link RocksDB dynamically for faster test builds.
ENV ROCKSDB_LIB_DIR="/usr/lib/"
# Copy source code first to ensure consistent timestamps
COPY --link --chown=${UID}:${GID} ./ ${HOME}
# Build Zebra test binaries using nextest, but don't run them.
# This also copies the necessary binaries to /usr/local/bin.
RUN [ -n "${SHORT_SHA}" ] && export SHORT_SHA="${SHORT_SHA}" || true; \
cargo nextest run --locked --release --no-run --features "${FEATURES}" && \
# Copy binaries to standard location
cp ${CARGO_TARGET_DIR}/release/zebrad /usr/local/bin && \
# Only copy zebra-checkpoints if the feature is enabled
if echo "${FEATURES}" | grep -q "zebra-checkpoints"; then \
cp ${CARGO_TARGET_DIR}/release/zebra-checkpoints /usr/local/bin; \
fi && \
# Set proper ownership
chown -R ${UID}:${GID} ${CARGO_HOME} && \
chown -R ${UID}:${GID} ${CARGO_TARGET_DIR}
# Copy the lightwalletd binary and source files to be able to run tests
COPY --link --from=electriccoinco/lightwalletd:v0.4.17 /usr/local/bin/lightwalletd /usr/local/bin/
COPY --link --chown=${UID}:${GID} ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT [ "entrypoint.sh", "test" ]
CMD [ "cargo", "test" ]
# This stage builds the zebrad release binary.
#
# It also adds `cache mounts` as this stage is completely independent from the
# `test` stage. The resulting zebrad binary is used in the `runtime` stage.
FROM deps AS release
ARG SHORT_SHA
ARG FEATURES
ENV FEATURES=${FEATURES}
# Set the working directory for the build.
ARG HOME
WORKDIR ${HOME}
ARG CARGO_HOME
ARG CARGO_TARGET_DIR
# Strip absolute build paths from the binary so it doesn't depend on the build layout.
ENV RUSTFLAGS="--remap-path-prefix=${HOME}=/zebra --remap-path-prefix=${CARGO_HOME}=/cargo"
RUN --mount=type=bind,source=tower-batch-control,target=tower-batch-control \
--mount=type=bind,source=tower-fallback,target=tower-fallback \
--mount=type=bind,source=zebra-chain,target=zebra-chain \
--mount=type=bind,source=zebra-consensus,target=zebra-consensus \
--mount=type=bind,source=zebra-network,target=zebra-network \
--mount=type=bind,source=zebra-node-services,target=zebra-node-services \
--mount=type=bind,source=zebra-rpc,target=zebra-rpc \
--mount=type=bind,source=zebra-script,target=zebra-script \
--mount=type=bind,source=zebra-state,target=zebra-state \
--mount=type=bind,source=zebra-test,target=zebra-test \
--mount=type=bind,source=zebra-utils,target=zebra-utils \
--mount=type=bind,source=zebrad,target=zebrad \
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
--mount=type=cache,target=${CARGO_TARGET_DIR} \
--mount=type=cache,target=${CARGO_HOME} \
[ -n "${SHORT_SHA}" ] && export SHORT_SHA="${SHORT_SHA}" || true; \
cargo build --locked --release --features "${FEATURES}" --package zebrad --bin zebrad && \
cp ${CARGO_TARGET_DIR}/release/zebrad /usr/local/bin
# This stage starts from scratch using Debian and copies the built zebrad binary
# from the `release` stage along with other binaries and files.
# debian:trixie-slim
FROM debian:trixie-slim@sha256:28de0877c2189802884ccd20f15ee41c203573bd87bb6b883f5f46362d24c5c2 AS runtime
ARG FEATURES
ENV FEATURES=${FEATURES}
ARG SOURCE_DATE_EPOCH=0
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
# Create a non-privileged user for running `zebrad`.
#
# We use a high UID/GID (10001) to avoid overlap with host system users.
# This reduces the risk of container user namespace conflicts with host accounts,
# which could potentially lead to privilege escalation if a container escape occurs.
#
# We do not use the `--system` flag for user creation since:
# 1. System user ranges (100-999) can collide with host system users
# (see: https://github.com/nginx/docker-nginx/issues/490)
# 2. There's no value added and warning messages can be raised at build time
# (see: https://github.com/dotnet/dotnet-docker/issues/4624)
#
# The high UID/GID values provide an additional security boundary in containers
# where user namespaces are shared with the host.
ARG UID
ENV UID=${UID}
ARG GID
ENV GID=${GID}
ARG USER
ENV USER=${USER}
ARG HOME
ENV HOME=${HOME}
# Install curl for healtchecks and adduser for user/group creation
RUN apt-get -q update && \
apt-get -q install -y --no-install-recommends \
adduser=3.152* \
curl=8.14.1-* \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/log/* /var/cache/ldconfig/aux-cache
RUN addgroup --quiet --gid ${GID} ${USER} && \
adduser --quiet --gid ${GID} --uid ${UID} --home ${HOME} ${USER} --disabled-password --gecos ""
WORKDIR ${HOME}
RUN chown -R ${UID}:${GID} ${HOME}
# We're explicitly NOT using the USER directive here.
# Instead, we run as root initially and use setpriv in the entrypoint.sh
# to step down to the non-privileged user. This allows us to change permissions
# on mounted volumes before running the application as a non-root user.
# User with UID=${UID} is created above and used via setpriv in entrypoint.sh.
# setpriv is part of util-linux, already included in debian:trixie-slim.
COPY --link --from=release /usr/local/bin/zebrad /usr/local/bin/
COPY --link --chown=${UID}:${GID} ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT [ "entrypoint.sh" ]
CMD ["zebrad"]
# TODO: Add a `monitoring` stage
#
# This stage will be based on `runtime`, and initially:
#
# - run `zebrad` on Testnet
# - with mining enabled using S-nomp and `nheqminer`.
#
# We can add further functionality to this stage for further purposes.
# zcashd-compat runtime image: the runtime image plus the hash-pinned zcashd
# wallet sidecar (and its RPC client) from the ZcashFoundation/zcashd
# `zebra-compat` release, for the supervised sidecar configuration
# (`zebrad start --zcashd-compat` with `manage_zcashd = true`).
#
# The sidecar release only ships x86_64 Linux binaries, so this stage is
# amd64-only (CI already builds non-`runtime` targets for amd64 only).
# Override the ARGs to bake in a different sidecar release.
FROM runtime AS runtime-zcashd-compat
ARG ZCASHD_COMPAT_ARCHIVE_URL="https://github.com/ZcashFoundation/zcashd/releases/download/zebra-compat-v1.1.0/zcashd-zebra-compat-v1.1.0-linux-x86_64.tar.gz"
ARG ZCASHD_COMPAT_ARCHIVE_SHA256="92f47c6ff84a99cf6c911f47c03d70d4a5181870cdc87dcb49036d1d4c346567"
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# ca-certificates is needed for the HTTPS download: curl is installed above
# with --no-install-recommends, which skips it.
RUN apt-get -q update && \
apt-get -q install -y --no-install-recommends \
ca-certificates=20250419 \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/log/* /var/cache/ldconfig/aux-cache \
&& curl -fsSL "${ZCASHD_COMPAT_ARCHIVE_URL}" -o /tmp/zcashd.tar.gz \
&& echo "${ZCASHD_COMPAT_ARCHIVE_SHA256} /tmp/zcashd.tar.gz" | sha256sum -c - \
&& tar -xzf /tmp/zcashd.tar.gz -C /tmp ./bin/zcashd ./bin/zcash-cli \
&& install -m 0755 /tmp/bin/zcashd /tmp/bin/zcash-cli /usr/local/bin/ \
&& rm -rf /tmp/zcashd.tar.gz /tmp/bin \
&& /usr/local/bin/zcashd --version \
&& /usr/local/bin/zcash-cli --version