Speed up scratch image builds with publish-first contexts

This commit is contained in:
master
2026-03-09 07:37:24 +02:00
parent c9686edf07
commit f218ec82ec
8 changed files with 358 additions and 38 deletions

View File

@@ -1,6 +1,10 @@
#!/usr/bin/env bash
# Build hardened images for the core services using the shared template/matrix (DOCKER-44-001)
# Build hardened images for the core services using the shared template/matrix.
# The default path publishes .NET services locally and builds runtime-only
# images from small temporary contexts to avoid repeatedly sending the full
# monorepo into Docker.
set -uo pipefail
FAILED=()
SUCCEEDED=()
@@ -10,6 +14,12 @@ REGISTRY=${REGISTRY:-"stellaops"}
TAG_SUFFIX=${TAG_SUFFIX:-"dev"}
SDK_IMAGE=${SDK_IMAGE:-"mcr.microsoft.com/dotnet/sdk:10.0-noble"}
RUNTIME_IMAGE=${RUNTIME_IMAGE:-"mcr.microsoft.com/dotnet/aspnet:10.0-noble"}
USE_LEGACY_REPO_CONTEXT=${USE_LEGACY_REPO_CONTEXT:-"false"}
PUBLISH_NO_RESTORE=${PUBLISH_NO_RESTORE:-"false"}
SERVICES=${SERVICES:-""}
FAST_CONTEXT_ROOT=${FAST_CONTEXT_ROOT:-"${TMPDIR:-/tmp}/stellaops-fast-images"}
RUNTIME_DOCKERFILE="${ROOT}/devops/docker/Dockerfile.hardened.runtime"
HEALTHCHECK_SCRIPT="${ROOT}/devops/docker/healthcheck.sh"
if [[ ! -f "${MATRIX}" ]]; then
echo "matrix file not found: ${MATRIX}" >&2
@@ -17,9 +27,75 @@ if [[ ! -f "${MATRIX}" ]]; then
fi
echo "Building services from ${MATRIX} -> ${REGISTRY}/<service>:${TAG_SUFFIX}" >&2
if [[ -n "${SERVICES}" ]]; then
echo "Service filter: ${SERVICES}" >&2
fi
cleanup_context() {
local context_dir="${1:-}"
[[ -n "${context_dir}" && -d "${context_dir}" ]] && rm -rf "${context_dir}"
}
should_build_service() {
local service="$1"
[[ -z "${SERVICES}" ]] && return 0
IFS=',' read -r -a requested <<< "${SERVICES}"
for candidate in "${requested[@]}"; do
local trimmed="${candidate// /}"
[[ "${trimmed}" == "${service}" ]] && return 0
done
return 1
}
build_published_service_image() {
local service="$1"
local project="$2"
local binary="$3"
local port="$4"
local image="$5"
local context_dir="${FAST_CONTEXT_ROOT}/${service}"
cleanup_context "${context_dir}"
mkdir -p "${context_dir}/app"
local publish_args=(
publish "${ROOT}/${project}"
-c Release
-o "${context_dir}/app"
/p:UseAppHost=false
/p:PublishTrimmed=false
--nologo
)
if [[ "${PUBLISH_NO_RESTORE}" == "true" ]]; then
publish_args+=(--no-restore)
fi
dotnet "${publish_args[@]}" || {
cleanup_context "${context_dir}"
return 1
}
cp "${RUNTIME_DOCKERFILE}" "${context_dir}/Dockerfile"
cp "${HEALTHCHECK_SCRIPT}" "${context_dir}/healthcheck.sh"
docker build \
-f "${context_dir}/Dockerfile" "${context_dir}" \
--build-arg "RUNTIME_IMAGE=${RUNTIME_IMAGE}" \
--build-arg "APP_BINARY=${binary}" \
--build-arg "APP_PORT=${port}" \
-t "${image}"
local build_status=$?
cleanup_context "${context_dir}"
return ${build_status}
}
while IFS='|' read -r service dockerfile project binary port; do
[[ -z "${service}" || "${service}" =~ ^# ]] && continue
should_build_service "${service}" || continue
image="${REGISTRY}/${service}:${TAG_SUFFIX}"
df_path="${ROOT}/${dockerfile}"
if [[ ! -f "${df_path}" ]]; then
@@ -28,13 +104,15 @@ while IFS='|' read -r service dockerfile project binary port; do
fi
if [[ "${dockerfile}" == *"Dockerfile.console"* ]]; then
# Angular console build uses its dedicated Dockerfile
echo "[console] ${service} -> ${image}" >&2
docker build \
-f "${df_path}" "${ROOT}" \
--build-arg APP_DIR="${project}" \
--build-arg APP_PORT="${port}" \
-t "${image}"
elif [[ "${USE_LEGACY_REPO_CONTEXT}" != "true" && "${dockerfile}" == *"Dockerfile.hardened.template"* ]]; then
echo "[service fast] ${service} -> ${image}" >&2
build_published_service_image "${service}" "${project}" "${binary}" "${port}" "${image}"
else
echo "[service] ${service} -> ${image}" >&2
docker build \
@@ -53,7 +131,6 @@ while IFS='|' read -r service dockerfile project binary port; do
FAILED+=("${service}")
echo "FAILED: ${service}" >&2
fi
done < "${MATRIX}"
echo "" >&2
@@ -65,4 +142,5 @@ if [[ ${#FAILED[@]} -gt 0 ]]; then
echo "Some builds failed. Fix the issues and re-run." >&2
exit 1
fi
echo "Build complete. Remember to enforce readOnlyRootFilesystem at deploy time and run sbom_attest.sh (DOCKER-44-002)." >&2