-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
92 lines (71 loc) · 3.05 KB
/
Copy pathDockerfile
File metadata and controls
92 lines (71 loc) · 3.05 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
################################################################################
# Chef stage (pre-built cargo-chef image)
################################################################################
FROM lukemathwalker/cargo-chef:latest-rust-1.96.0-alpine AS chef
WORKDIR /app
# Install build dependencies needed to compile Rust crates on Alpine
RUN apk add --no-cache clang lld git nasm dav1d-dev pkgconfig musl-dev libjxl-dev
# Disable static linking to avoid issues with libdav1d
ENV RUSTFLAGS="-C target-feature=-crt-static"
################################################################################
# Planner stage
# Analyze the project and produce a recipe file.
################################################################################
FROM chef AS planner
COPY Cargo.toml Cargo.lock ./
COPY image/Cargo.toml image/Cargo.toml
COPY foyer/ foyer/
COPY src/ src/
COPY image/src/ image/src/
RUN cargo chef prepare --recipe-path recipe.json
################################################################################
# Builder stage
# Cache dependencies and compile the application.
################################################################################
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Copy the local path dependencies needed by [patch.crates-io] and foyer
COPY image/ image/
COPY foyer/ foyer/
# Build dependencies - this is the caching Docker layer!
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
COPY tests/ tests/
RUN cargo build --locked --release && \
cp ./target/release/image-proxy /bin/image-proxy
################################################################################
# Runtime stage (DOI Alpine image)
# This stage runs the already-compiled binary with minimal dependencies.
################################################################################
FROM docker.io/library/alpine:3.23 AS runtime
# Create a non-privileged user (recommended best practice)
ARG UID=1000
# jemalloc: full-process allocator via LD_PRELOAD (Rust + native codecs).
# Returns free pages after concurrent image encode/decode free storms more
# aggressively than the system multi-arena malloc.
RUN apk add --no-cache libdav1d libgcc libjxl jemalloc
RUN adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
appuser
# Drop privileges for runtime.
USER appuser
# Set working directory
WORKDIR /app
# Copy only the compiled binary from the build stage.
COPY --from=builder /bin/image-proxy /bin/image-proxy
# Document the port your app listens on.
EXPOSE 8000
# Intercept all malloc/free (including libwebp/libjxl/dav1d).
ENV LD_PRELOAD=/usr/lib/libjemalloc.so.2
# background_thread: purge dirty pages without waiting for the next alloc storm
# dirty/muzzy_decay_ms: return free pages to the OS ~1s after they become idle
ENV MALLOC_CONF=background_thread:true,dirty_decay_ms:1000,muzzy_decay_ms:1000
# Start the application.
CMD ["/bin/image-proxy"]