-
Notifications
You must be signed in to change notification settings - Fork 45
Expand file tree
/
Copy pathContainerfile
More file actions
124 lines (95 loc) · 5.06 KB
/
Copy pathContainerfile
File metadata and controls
124 lines (95 loc) · 5.06 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
# syntax=docker/dockerfile:1
# ------------------------------------------------------------------------------
# Stage 1: Build
# ------------------------------------------------------------------------------
FROM rust:1.98-alpine AS builder
ENV OPENSSL_STATIC=1
RUN apk add --no-cache musl-dev openssl-dev openssl-libs-static pkgconf cmake make g++
WORKDIR /src
# ------------------------------------------------------------------------------
# Cache Build
# ------------------------------------------------------------------------------
# Cache dependency builds: copy only manifests first, then
# create stub source files so `cargo build` resolves and
# compiles all dependencies without the real source code.
# Workspace manifests
COPY Cargo.toml Cargo.lock ./
COPY apis/Cargo.toml ./apis/Cargo.toml
COPY filters/Cargo.toml ./filters/Cargo.toml
COPY server/Cargo.toml ./server/Cargo.toml
COPY server/build_support/Cargo.toml ./server/build_support/Cargo.toml
# The server crate has a build.rs that discovers external filter
# crates via cargo metadata for build-time auto-registration,
# backed by the praxis-ai-build-support crate. build.rs is a
# build-dependency of the server crate, not an ordinary crate under
# test: cargo compiles it (and everything it depends on) up front,
# so praxis-ai-build-support needs its real source here too, not a
# stub — a stub would compile but export none of the functions
# build.rs calls, breaking compilation of the build script itself.
COPY server/build.rs ./server/build.rs
COPY server/build_support/src ./server/build_support/src
# Copy the optional llm-d ext_proc manifest and generated protobuf inputs so
# Cargo can resolve the workspace during the dependency-cache build.
COPY integrations/llmd/ext-proc/Cargo.toml ./integrations/llmd/ext-proc/Cargo.toml
COPY integrations/llmd/ext-proc/build.rs ./integrations/llmd/ext-proc/build.rs
COPY integrations/llmd/ext-proc/proto ./integrations/llmd/ext-proc/proto
# Strip workspace members not needed for the binary.
RUN sed -i '/xtask/d; /tests\//d' Cargo.toml
# Create stub source files for the crates whose real source isn't
# needed until after dependencies are cached.
RUN mkdir -p apis/src filters/src server/src integrations/llmd/ext-proc/src \
&& echo '//! stub' > apis/src/lib.rs \
&& echo '//! stub' > filters/src/lib.rs \
&& echo '//! stub' > server/src/lib.rs \
&& echo '//! stub' > integrations/llmd/ext-proc/src/lib.rs \
&& printf '//! stub\nfn main() {}\n' > server/src/main.rs
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/src/target \
cargo build --release -p praxis-ai-proxy
# ------------------------------------------------------------------------------
# Cache Tricks
# ------------------------------------------------------------------------------
# Replace stubs with real source, then rebuild. Only the project
# crates recompile; all external dependencies are cached.
# build_support/src was already real (see above), so it is not
# copied again here.
COPY apis/src ./apis/src
COPY filters/src ./filters/src
COPY server/src ./server/src
COPY integrations/llmd/ext-proc/src ./integrations/llmd/ext-proc/src
RUN find apis/src filters/src server/src integrations/llmd/ext-proc/src \
-name '*.rs' -exec touch {} +
# ------------------------------------------------------------------------------
# Build
# ------------------------------------------------------------------------------
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/src/target \
cargo build --release -p praxis-ai-proxy \
&& cp target/release/praxis-ai /usr/local/bin/praxis-ai
# ------------------------------------------------------------------------------
# Stage 2: Runtime
# ------------------------------------------------------------------------------
FROM alpine:3.24
LABEL org.opencontainers.image.source="https://github.com/praxis-proxy/ai" \
org.opencontainers.image.description="Praxis AI proxy server" \
org.opencontainers.image.licenses="Apache-2.0"
RUN apk add --no-cache ca-certificates \
&& addgroup -S praxis \
&& adduser -S -G praxis -h /nonexistent -s /sbin/nologin praxis \
&& mkdir -p /etc/praxis
# Apache-2.0 (section 4) requires object-form recipients to receive the License
# and the applicable NOTICE attributions. Ship them with the image. The root
# NOTICE references integrations/llmd/ext-proc/NOTICE relative to this
# directory, so preserve that subpath to keep the pointer resolvable.
COPY --chown=root:root --chmod=0444 LICENSE /usr/share/licenses/praxis-ai/LICENSE
COPY --chown=root:root --chmod=0444 NOTICE /usr/share/licenses/praxis-ai/NOTICE
COPY --chown=root:root --chmod=0444 integrations/llmd/ext-proc/NOTICE \
/usr/share/licenses/praxis-ai/integrations/llmd/ext-proc/NOTICE
COPY --from=builder --chown=root:root --chmod=0555 \
/usr/local/bin/praxis-ai /usr/local/bin/praxis-ai
USER praxis:praxis
WORKDIR /etc/praxis
EXPOSE 8080 9901
HEALTHCHECK --interval=5s --timeout=3s --start-period=2s \
CMD wget -qO- http://127.0.0.1:9901/healthy || exit 1
ENTRYPOINT ["praxis-ai"]