forked from F1R3FLY-io/f1r3node-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
186 lines (156 loc) · 7.65 KB
/
Dockerfile
File metadata and controls
186 lines (156 loc) · 7.65 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
# Multi-stage Dockerfile for Rust F1r3fly Node
# Equivalent to build.sbt Docker configuration
FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx
# ============================================================================
# Stage 1: Builder - Build node binary (Cargo handles all dependencies)
# ============================================================================
FROM --platform=$BUILDPLATFORM rust:bookworm AS builder
# Declare build arguments at the top to ensure consistent caching
ARG TARGETARCH
# Install build dependencies for Debian/glibc cross-compilation
# Include cross-compiler toolchains for both amd64 and arm64 targets
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
libclang-dev \
clang \
build-essential \
protobuf-compiler \
curl \
cmake \
gcc-x86-64-linux-gnu \
g++-x86-64-linux-gnu \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY --from=xx / /
# Install library dependencies for target architectures using xx-apt
# This ensures cross-compilers can find necessary headers and libraries for the target
RUN xx-apt-get update && xx-apt-get install -y \
libc6-dev \
libssl-dev \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
# Copy workspace files first for better caching
COPY Cargo.toml Cargo.lock ./
COPY rust-toolchain.toml ./
# Create directory structure and copy only Cargo.toml files from all workspace members
# This allows us to cache dependencies separately from source code
RUN mkdir -p models crypto rholang rholang/src/main/tree_sitter shared casper comm rspace++ rspace++/libs/rspace_rhotypes block-storage graphz node
# Now copy all source code (this layer invalidates when source changes)
# Copy in dependency order to maximize cache hits - base dependencies first
COPY shared/ ./shared/
COPY crypto/ ./crypto/
COPY models/ ./models/
COPY graphz/ ./graphz/
COPY block-storage/ ./block-storage/
COPY rspace++/ ./rspace++/
COPY casper/ ./casper/
COPY comm/ ./comm/
COPY rholang/ ./rholang/
COPY node/ ./node/
# Configure pkg-config for cross-compilation to find target OpenSSL libraries
# xx-apt installs target libs in the xx sysroot, we need to tell pkg-config where they are
# Enable AES CPU features for gxhash dependency (required by PathMap crate).
# +sse2 is x86-only; on aarch64 only +aes is valid (avoids warning spam on ARM hosts).
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/build/build \
export TARGET_TRIPLE=$(xx-cargo --print-target-triple) && \
export PKG_CONFIG_SYSROOT_DIR=$(xx-info sysroot) && \
export PKG_CONFIG_PATH=$(xx-info sysroot)/usr/lib/$(xx-info triple)/pkgconfig:$(xx-info sysroot)/usr/share/pkgconfig && \
export PKG_CONFIG_ALLOW_CROSS=1 && \
case "${TARGET_TRIPLE}" in \
aarch64*) export RUSTFLAGS="-C target-feature=+aes" ;; \
*) export RUSTFLAGS="-C target-feature=+aes,+sse2" ;; \
esac && \
xx-cargo build --release -p node --target-dir ./build && \
xx-verify ./build/${TARGET_TRIPLE}/release/node && \
cp ./build/${TARGET_TRIPLE}/release/node /build/node_binary && \
chmod +x /build/node_binary
# ============================================================================
# Stage 2: Runtime base - Install runtime dependencies (cached independently)
# ============================================================================
FROM debian:bookworm-slim AS runtime-base
# Install runtime dependencies
# Note: grpcurl and jq for healthcheck (matching build.sbt healthcheck)
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
libc6 \
libjemalloc2 \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install grpcurl and jq for healthcheck (matching build.sbt)
# Note: These are installed in the runtime stage, architecture will be detected at runtime
RUN GRPCURL_VERSION="1.8.9" && \
ARCH=$(dpkg --print-architecture) && \
case "$ARCH" in \
amd64) GRPCURL_ARCH="x86_64" ;; \
arm64) GRPCURL_ARCH="arm64" ;; \
*) GRPCURL_ARCH="x86_64" ;; \
esac && \
curl -L "https://github.com/fullstorydev/grpcurl/releases/download/v${GRPCURL_VERSION}/grpcurl_${GRPCURL_VERSION}_linux_${GRPCURL_ARCH}.tar.gz" -o /tmp/grpcurl.tar.gz && \
tar -xzf /tmp/grpcurl.tar.gz -C /tmp && \
find /tmp -name grpcurl -type f -executable -exec mv {} /usr/local/bin/ \; && \
chmod +x /usr/local/bin/grpcurl && \
rm -rf /tmp/grpcurl* || true && \
ARCH=$(dpkg --print-architecture) && \
case "$ARCH" in \
amd64) JQ_ARCH="linux64" ;; \
arm64) JQ_ARCH="linuxarm64" ;; \
*) JQ_ARCH="linux64" ;; \
esac && \
curl -L "https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-${JQ_ARCH}" -o /usr/local/bin/jq && \
chmod +x /usr/local/bin/jq || true
# ============================================================================
# Stage 3: Runtime - Final image, starts at WORKDIR with artifacts from builder
# ============================================================================
FROM runtime-base
# Use existing daemon user (matching build.sbt: daemonUser in Docker := "daemon")
# Note: daemon user already exists in debian:12-slim, so we just ensure it has the right UID
# RUN id -u daemon >/dev/null 2>&1 || useradd -r -s /bin/false -u 1 daemon
# Set up directory structure (matching build.sbt defaultLinuxInstallLocation)
WORKDIR /opt/docker
# Create bin directory first
RUN mkdir -p /opt/docker/bin
# Copy node binary (using node_binary from builder to avoid conflict with node/ directory)
# Verify it's a file before copying
COPY --from=builder --chmod=755 /build/node_binary /opt/docker/bin/node
# Copy node resources (defaults.conf, kamon.conf, logback.xml, etc.)
# The node executable expects these at node/src/main/resources relative to current directory
COPY --from=builder /build/node/src/main/resources ./node/src/main/resources
# Copy casper resources (Registry.rho, ListOps.rho, etc.)
# The node executable needs these at runtime to create genesis blocks
COPY --from=builder /build/casper/src/main/resources ./casper/src/main/resources
# Copy rholang examples (matching build.sbt: directory((baseDirectory in rholang).value / "examples"))
COPY --from=builder /build/rholang/examples ./examples
# Create entrypoint script for Rust (adapted from docker-entrypoint.sh)
# Copy the Rust-specific entrypoint script from node directory
# Note: This Dockerfile should be built from workspace root
COPY node/docker-entrypoint-rust.sh /opt/docker/bin/docker-entrypoint.sh
# Set permissions (matching build.sbt: withUser "daemon" withGroup "daemon")
RUN if [ ! -f /opt/docker/bin/node ]; then \
echo "ERROR: /opt/docker/bin/node is not a file!" >&2 && \
exit 1; \
fi && \
chown -R daemon:daemon /opt/docker && \
chmod +x /opt/docker/bin/node && \
chmod +x /opt/docker/bin/docker-entrypoint.sh
# Expose ports (matching build.sbt: dockerExposedPorts)
EXPOSE 40400 40401 40402 40403 40404
# Healthcheck (matching build.sbt healthcheck, adapted for Rust)
# Note: The original uses grpcurl and curl with jq
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD grpcurl -plaintext 127.0.0.1:40401 casper.v1.DeployService.status | jq -e && \
curl -s 127.0.0.1:40403/status | jq -e || exit 1
# Labels (matching build.sbt)
LABEL maintainer="F1r3fly.io LCA https://f1r3fly.io/"
LABEL version="0.1.0"
# Switch to daemon user (matching build.sbt: daemonUser in Docker := "daemon")
USER daemon
# Entrypoint (matching build.sbt: dockerEntrypoint)
ENTRYPOINT ["/opt/docker/bin/docker-entrypoint.sh"]
# Default command (matching build.sbt: ExecCmd("CMD", "run"))
CMD ["run"]