180 lines
6.5 KiB
Text
180 lines
6.5 KiB
Text
|
|
# 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 ++ "\"]",
|
||
|
|
"",
|
||
|
|
]
|