Dockerfile 5.06 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# SPDX-FileCopyrightText:  Copyright The Kubernetes Authors.
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#  #
#  http://www.apache.org/licenses/LICENSE-2.0
#  #
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#  Modifications Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES

# Dynamo EPP Dockerfile
19
# Self-contained 3-stage build: Rust FFI library → Go binary → Runtime
20
#
21
22
23
24
25
26
27
28
29
30
31
# Uses two build contexts (requires Docker BuildKit):
#   - Default context (.): the epp/ Go project
#   - Named context "dynamo": the Dynamo repository root (Rust workspace)
#
# Build via Makefile (recommended):
#   make image-load
#
# Build manually:
#   docker buildx build \
#     --build-context dynamo=../../.. \
#     -t dynamo/dynamo-epp:dev .
32

33
ARG RUST_IMAGE=rust:1.93.1
34
ARG BUILDER_IMAGE=golang:1.24
35
36
37
ARG BASE_IMAGE=ubuntu:24.04

# =============================================================================
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Stage 1: Build Dynamo FFI static library (Rust)
# =============================================================================
FROM ${RUST_IMAGE} AS rust-builder

# TARGETARCH is provided automatically by buildx for multi-platform builds.
# Used here only for per-platform cache isolation.
ARG TARGETARCH

# etcd-client crate requires protoc to compile proto files
RUN apt-get update && apt-get install -y --no-install-recommends \
    protobuf-compiler \
    libclang-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /dynamo

# Copy Cargo workspace manifests, lockfile, and README (some crates inherit
# readme.workspace = true, so cargo needs README.md at the workspace root)
56
COPY --from=dynamo .cargo/ .cargo/
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
COPY --from=dynamo Cargo.toml Cargo.lock README.md ./

# Copy all workspace crates (libdynamo_llm depends transitively on many)
COPY --from=dynamo lib/ lib/

# Build the static library; use BuildKit cache mounts for cargo registry and
# build artifacts so incremental Docker rebuilds are fast.
# Cache IDs are keyed by TARGETARCH so multi-platform builds don't collide.
# Artifacts are copied to /out/ because the target/ cache mount is ephemeral.
RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry-${TARGETARCH} \
    --mount=type=cache,target=/usr/local/cargo/git,id=cargo-git-${TARGETARCH} \
    --mount=type=cache,target=/dynamo/target,id=cargo-target-${TARGETARCH} \
    cargo build --release -p libdynamo_llm && \
    mkdir -p /out && \
    cp target/release/libdynamo_llm_capi.a /out/ && \
72
73
    HEADER=$(find target/release/build -name llm_engine.h -path "*/out/*" | head -1) && \
    [ -n "$HEADER" ] && cp "$HEADER" /out/ || { echo "ERROR: llm_engine.h not found in target/"; exit 1; }
74
75
76

# =============================================================================
# Stage 2: Build Go EPP binary
77
# =============================================================================
78
FROM ${BUILDER_IMAGE} AS go-builder
79
80
81
82
83
84
85
86
87
88
89

# Docker buildx provides these automatically for multi-platform builds
ARG TARGETOS=linux
ARG TARGETARCH

ARG COMMIT_SHA
ARG BUILD_REF

WORKDIR /workspace

# Install build dependencies for CGO
90
RUN apt-get update && apt-get install -y --no-install-recommends \
91
92
93
94
95
    gcc \
    g++ \
    libc-dev \
    && rm -rf /var/lib/apt/lists/*

96
# Copy go mod files first for better caching (from default context = epp/)
97
COPY go.mod go.sum ./
98
99
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download
100

101
# Copy Go source (from default context = epp/)
102
103
COPY . .

104
105
106
# Place Rust artifacts where CGO expects them (see plugin.go #cgo directives)
COPY --from=rust-builder /out/libdynamo_llm_capi.a pkg/plugins/dynamo_kv_scorer/lib/
COPY --from=rust-builder /out/llm_engine.h pkg/plugins/dynamo_kv_scorer/include/
107

108
109
110
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    CGO_ENABLED=1 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build \
111
112
113
114
115
    -ldflags="-X sigs.k8s.io/gateway-api-inference-extension/version.GitVersion=${BUILD_REF} \
              -X sigs.k8s.io/gateway-api-inference-extension/version.GitCommit=${COMMIT_SHA}" \
    -o epp ./cmd/epp

# =============================================================================
116
# Stage 3: Runtime
117
118
119
# =============================================================================
FROM ${BASE_IMAGE}

120
RUN apt-get update && apt-get install -y --no-install-recommends \
121
122
123
124
125
126
    ca-certificates \
    libstdc++6 \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /

127
COPY --from=go-builder /workspace/epp .
128
129
130
131
132
133
134
135

# Note: EPP config is mounted via Kubernetes ConfigMap at runtime
# See helm/dynamo-gaie/templates/epp-configmap.yaml

RUN useradd -r -u 65532 -g nogroup nonroot
USER 65532:65534

ENTRYPOINT ["/epp"]