provisioning/schemas/platform/templates/docker/Dockerfile.chef.ncl

180 lines
6.5 KiB
Text
Raw Normal View History

# Dockerfile Template Generator with cargo-chef Multi-Stage Build
# Generates optimized 4-stage Dockerfile with dependency caching
#
# Usage:
# Pass build config as parameter:
# let template = import "this-file.ncl" in
# let defaults = import "../../defaults/orchestrator-defaults.ncl" in
# template defaults.orchestrator.build
#
# Stages:
# 1. PLANNER - Generate cargo-chef recipe.json (dependency graph)
# 2. CACHER - Build dependencies only (cached layer)
# 3. BUILDER - Build source code (uses CACHER artifacts)
# 4. RUNTIME - Minimal runtime image with binary only
# Template function that takes build_config record
fun build_config =>
let package = build_config.package in
let binary = build_config.binary in
let base_image = build_config.base_image in
let runtime_image = build_config.runtime_image in
let port = build_config.port in
let health_path = build_config.health_path in
let features = build_config.features in
let extra_runtime_pkgs = build_config.extra_runtime_pkgs in
let user_id = build_config.user_id in
let config_file = build_config.config_file in
let chef_enabled = build_config.chef_enabled in
let sccache_enabled = build_config.sccache.enabled in
let buildkit_jobs = build_config.buildkit.parallel_jobs in
# Conditional string generation helpers
let features_arg =
if std.array.length features > 0 then
"--features " ++ (std.string.join "," features)
else
"" in
let sccache_install =
if sccache_enabled then
"RUN cargo install sccache --version 0.8.0\nENV RUSTC_WRAPPER=sccache"
else
"" in
let extra_pkgs_str =
if std.array.length extra_runtime_pkgs > 0 then
" \\\n " ++ (std.string.join " \\\n " extra_runtime_pkgs)
else
"" in
let config_copy =
if config_file != "" then
"COPY crates/" ++ package ++ "/" ++ config_file ++ " /etc/provisioning/config.defaults.toml"
else
"# No config file to copy" in
# Generate Dockerfile content
std.string.join "\n" [
"# Multi-stage build for " ++ package,
"# Generated from Nickel template - DO NOT EDIT DIRECTLY",
"# Source: provisioning/schemas/platform/templates/docker/Dockerfile.chef.ncl",
"",
"# ============================================================================",
"# Stage 1: PLANNER - Generate dependency recipe",
"# ============================================================================",
"FROM " ++ base_image ++ " AS planner",
"",
"WORKDIR /workspace",
"",
"# Install cargo-chef",
"RUN cargo install cargo-chef --version 0.1.67",
"",
"# Copy workspace manifests",
"COPY Cargo.toml Cargo.lock ./",
"COPY crates ./crates",
"COPY daemon-cli ./daemon-cli",
"COPY secretumvault ./secretumvault",
"COPY prov-ecosystem ./prov-ecosystem",
"COPY stratumiops ./stratumiops",
"",
"# Generate recipe.json (dependency graph)",
"RUN cargo chef prepare --recipe-path recipe.json --bin " ++ binary,
"",
"# ============================================================================",
"# Stage 2: CACHER - Build dependencies only",
"# ============================================================================",
"FROM " ++ base_image ++ " AS cacher",
"",
"WORKDIR /workspace",
"",
"# Install build dependencies",
"RUN apt-get update && apt-get install -y \\",
" pkg-config \\",
" libssl-dev \\",
" && rm -rf /var/lib/apt/lists/*",
"",
"# Install cargo-chef",
"RUN cargo install cargo-chef --version 0.1.67",
"",
(if sccache_enabled then sccache_install else "# sccache disabled"),
"",
"# Copy recipe from planner",
"COPY --from=planner /workspace/recipe.json recipe.json",
"",
"# Build dependencies - This layer will be cached",
"RUN cargo chef cook --release --recipe-path recipe.json " ++ features_arg,
"",
"# ============================================================================",
"# Stage 3: BUILDER - Build source code",
"# ============================================================================",
"FROM " ++ base_image ++ " AS builder",
"",
"WORKDIR /workspace",
"",
"# Install build dependencies",
"RUN apt-get update && apt-get install -y \\",
" pkg-config \\",
" libssl-dev \\",
" && rm -rf /var/lib/apt/lists/*",
"",
(if sccache_enabled then sccache_install else "# sccache disabled"),
"",
"# Copy cached dependencies from cacher stage",
"COPY --from=cacher /workspace/target target",
"COPY --from=cacher /usr/local/cargo /usr/local/cargo",
"",
"# Copy source code",
"COPY Cargo.toml Cargo.lock ./",
"COPY crates ./crates",
"COPY daemon-cli ./daemon-cli",
"COPY secretumvault ./secretumvault",
"COPY prov-ecosystem ./prov-ecosystem",
"COPY stratumiops ./stratumiops",
"",
"# Build release binary with parallelism",
"ENV CARGO_BUILD_JOBS=" ++ std.string.from_number buildkit_jobs,
"RUN cargo build --release --package " ++ package ++ " " ++ features_arg,
"",
"# ============================================================================",
"# Stage 4: RUNTIME - Minimal runtime image",
"# ============================================================================",
"FROM " ++ runtime_image,
"",
"# Install runtime dependencies",
"RUN apt-get update && apt-get install -y \\",
" ca-certificates \\",
" curl" ++ extra_pkgs_str ++ " \\",
" && rm -rf /var/lib/apt/lists/*",
"",
"# Create non-root user",
"RUN useradd -m -u " ++ std.string.from_number user_id ++ " provisioning && \\",
" mkdir -p /data /var/log/" ++ package ++ " && \\",
" chown -R provisioning:provisioning /data /var/log/" ++ package,
"",
"# Copy binary from builder",
"COPY --from=builder /workspace/target/release/" ++ binary ++ " /usr/local/bin/" ++ binary,
"RUN chmod +x /usr/local/bin/" ++ binary,
"",
config_copy,
"",
"# Switch to non-root user",
"USER provisioning",
"WORKDIR /app",
"",
"# Expose service port",
"EXPOSE " ++ std.string.from_number port,
"",
"# Environment variables",
"ENV RUST_LOG=info",
"ENV DATA_DIR=/data",
"",
"# Health check",
"HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \\",
" CMD curl -f http://localhost:" ++ std.string.from_number port ++ health_path ++ " || exit 1",
"",
"# Run the binary",
"CMD [\"" ++ binary ++ "\"]",
"",
]