-
Notifications
You must be signed in to change notification settings - Fork 209
Expand file tree
/
Copy pathDockerfile
More file actions
103 lines (85 loc) · 4.07 KB
/
Copy pathDockerfile
File metadata and controls
103 lines (85 loc) · 4.07 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
# Multi-stage Docker build for RustNet
# Base images are pinned by digest for reproducible, tamper-evident builds.
FROM rust:1.96-slim@sha256:3b05f7c617a200c41c3506097f0d15fc193a1c93bfd8f141007b47cac8f95d3c AS builder
# Install rustfmt component (required for eBPF compilation)
RUN rustup component add rustfmt
# Install build dependencies
RUN apt-get update && apt-get install -y \
libpcap-dev \
libelf-dev \
zlib1g-dev \
clang \
llvm \
make \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /app
# Copy Cargo files first for better caching
COPY Cargo.toml Cargo.lock ./
# Copy build script (manpage/completions; npcap on Windows)
COPY build.rs ./
# Copy source code
COPY src ./src
COPY benches ./benches
# Workspace member crates. rustnet-core holds the baked-in oui.gz / services
# assets (include_bytes!/include_str!); rustnet-host holds the eBPF programs and
# bundled vmlinux headers compiled by its own build.rs.
COPY crates ./crates
# Build the application in release mode (eBPF is enabled by default on Linux)
RUN cargo build --release
# Runtime stage - use trixie-slim to match GLIBC version from builder
# Pinned by digest for a reproducible, tamper-evident base image.
FROM debian:trixie-slim@sha256:4e401d95de7083948053197a9c3913343cd06b706bf15eb6a0c3ccd26f436a0e
# Install runtime dependencies
# libcap2-bin provides setcap, used below to grant packet-capture capabilities
# to the binary so it can run as a non-root user.
RUN apt-get update && apt-get install -y \
libpcap0.8 \
libelf1 \
zlib1g \
ca-certificates \
libcap2-bin \
&& rm -rf /var/lib/apt/lists/*
# Create a non-root user. The container runs as this user (see USER below);
# packet-capture privileges are granted via file capabilities on the binary
# rather than by running as root.
RUN useradd -r -s /bin/false rustnet
# Set working directory
WORKDIR /app
# Copy the binary from builder stage
COPY --from=builder /app/target/release/rustnet /usr/local/bin/rustnet
# Copy the services asset for reference (the binary already embeds it at build time)
COPY --from=builder /app/crates/rustnet-core/assets/services ./assets/services
# Create logs directory
RUN mkdir -p /app/logs && chown rustnet:rustnet /app/logs
# Set executable permissions and grant CAP_NET_RAW as a file capability so the
# binary can capture packets as a non-root user. NET_RAW is in Docker's default
# capability bounding set, so `docker run rustnet` works without extra flags.
#
# Only NET_RAW is baked in on purpose: a file capability that is NOT also in the
# container's bounding set makes execve() fail with EPERM. BPF/PERFMON are not
# in Docker's default set, so eBPF is handled at runtime instead (see below).
RUN chmod +x /usr/local/bin/rustnet \
&& setcap 'cap_net_raw=ep' /usr/local/bin/rustnet
# Expose no ports by default (rustnet is for monitoring, not serving)
# Network access is handled via host networking or packet capture capabilities
# Add labels for better image metadata
LABEL org.opencontainers.image.title="RustNet"
LABEL org.opencontainers.image.description="A cross-platform network monitoring tool with deep packet inspection"
LABEL org.opencontainers.image.source="https://github.com/domcyrus/rustnet"
LABEL org.opencontainers.image.licenses="Apache License, Version 2.0"
# RustNet runs as the non-root 'rustnet' user. CAP_NET_RAW is baked into the
# binary as a file capability and is part of Docker's default bounding set, so
# basic packet capture works out of the box:
# docker run rustnet
# eBPF-based process attribution needs BPF+PERFMON, which are NOT in the default
# bounding set and can't be granted to a non-root user via file capabilities.
# Enable eBPF by running as root with the extra caps (modern kernels 5.8+):
# docker run --user root --cap-add=BPF --cap-add=PERFMON rustnet
# Older kernels use CAP_SYS_ADMIN instead of BPF+PERFMON:
# docker run --user root --cap-add=SYS_ADMIN rustnet
# Without those, rustnet falls back to /proc-based process detection.
# CAP_NET_ADMIN is NOT required (read-only, non-promiscuous capture).
USER rustnet
ENTRYPOINT ["rustnet"]