diff options
Diffstat (limited to '.extras/image-builder/build-full-image.sh')
| -rwxr-xr-x | .extras/image-builder/build-full-image.sh | 233 |
1 files changed, 0 insertions, 233 deletions
diff --git a/.extras/image-builder/build-full-image.sh b/.extras/image-builder/build-full-image.sh deleted file mode 100755 index 24cbe1d..0000000 --- a/.extras/image-builder/build-full-image.sh +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/bash -# build-full-image.sh — sbo-full:{ver} FROM sbo-base:{ver}, all series. -# Adapted from forge slackware/docker-images. No root needed. -set -euo pipefail -HERE="$(cd "$(dirname "$0")" && pwd)" -source "${HERE}/config" -LOG_TAG=full -source "${HERE}/lib.sh" - -BASE_IMAGE="${REGISTRY}/sbo-base" -FULL_IMAGE="${REGISTRY}/sbo-full" -DIGEST_LABEL="sbo.full.base-digest" - -# ============================================================================ -# Argument parsing -# ============================================================================ - -FORCE=false -OPT_VERSION="" -while [[ $# -gt 0 ]]; do - case "$1" in - --version) OPT_VERSION="$2"; shift 2 ;; - --force) FORCE=true; shift ;; - *) _err "unknown argument: $1" ;; - esac -done -if [[ -n "${OPT_VERSION}" ]]; then - BUILD_VARIANTS=("${OPT_VERSION}") -else - BUILD_VARIANTS=("${VARIANTS[@]}") -fi - -# ============================================================================ -# Tag derivation -# ============================================================================ - -# derive_tags VERSION -# Sets globals BASE_TAG and FULL_TAG for the given variant. -derive_tags() { - local VERSION="$1" - BASE_TAG="${BASE_IMAGE}:${VERSION}" - FULL_TAG="${FULL_IMAGE}:${VERSION}" -} - -# ============================================================================ -# Rebuild detection -# -# After pulling the latest base image, its digest is compared with the -# digest stored in the DIGEST_LABEL on the current full image. If -# they differ the base image has been updated and the full must be -# rebuilt to incorporate slackpkg package updates shipped with the new base. -# ============================================================================ - -needs_rebuild() { - local BASE_TAG="$1" FULL_TAG="$2" - - if [[ "${FORCE}" == "true" ]]; then - _log " --force specified; rebuilding unconditionally." - return 0 - fi - - # Digest of the base image we just pulled - local BASE_DIGEST - BASE_DIGEST=$(docker inspect --format '{{index .RepoDigests 0}}' \ - "${BASE_TAG}" 2>/dev/null || echo "") - if [[ -z "${BASE_DIGEST}" ]]; then - _warn " Could not determine base image digest; rebuilding to be safe." - return 0 - fi - - # Digest recorded in the full image's label (empty if image doesn't exist) - local RECORDED_DIGEST - RECORDED_DIGEST=$(docker inspect \ - --format "{{index .Config.Labels \"${DIGEST_LABEL}\"}}" \ - "${FULL_TAG}" 2>/dev/null || echo "") - - if [[ "${BASE_DIGEST}" == "${RECORDED_DIGEST}" ]]; then - _log " Base image unchanged (${BASE_DIGEST:0:40}...); skipping." - return 1 - fi - - _log " Base image changed; rebuilding." - _log " Was : ${RECORDED_DIGEST:0:60}..." - _log " Now : ${BASE_DIGEST:0:60}..." - return 0 -} - -# ============================================================================ -# Build one variant -# ============================================================================ - -build_variant() { - local VERSION="$1" - local REPO_KEY="slackware64-${VERSION}" - require_mount "${VERSION}" # NFS must be up: we serve it over HTTP below - derive_tags "${VERSION}" - - _log "=== ${FULL_TAG} ===" - - # Pull the latest base image so digest comparison is against the current - # state of the registry, not a stale local cache. - _log " Pulling base image ${BASE_TAG}..." - docker pull "${BASE_TAG}" - - if ! needs_rebuild "${BASE_TAG}" "${FULL_TAG}"; then - return 0 - fi - - # Record the base image digest for the label - local BASE_DIGEST - BASE_DIGEST=$(docker inspect --format '{{index .RepoDigests 0}}' "${BASE_TAG}") - - local WORKDIR - WORKDIR="$(mktemp -d /tmp/slackware-full.XXXXXX)" - - # Serve the NFS mirror over HTTP on the docker bridge for the duration of - # the build, so slackpkg in the build container fetches packages from LAN - # instead of the internet. Killed (with WORKDIR cleanup) on any exit. - local MIRROR_ROOT; MIRROR_ROOT="$(strip_scheme "$(mirror_path "${MIRROR}" "${REPO_KEY}")")" - [[ -f "${MIRROR_ROOT}/PACKAGES.TXT" ]] \ - || _err "mirror root has no PACKAGES.TXT: ${MIRROR_ROOT}" - python3 -m http.server "${HTTP_MIRROR_PORT}" \ - --bind "${HTTP_MIRROR_HOST}" --directory "${MIRROR_ROOT}" \ - >/dev/null 2>&1 & - local HTTP_PID=$! - # shellcheck disable=SC2064 - trap "kill ${HTTP_PID} 2>/dev/null; rm -rf '${WORKDIR}'" EXIT - # Wait for the server to accept connections before building. - local i - for i in 1 2 3 4 5 6 7 8 9 10; do - curl -sf -o /dev/null "http://${HTTP_MIRROR_HOST}:${HTTP_MIRROR_PORT}/PACKAGES.TXT" && break - [[ $i -eq 10 ]] && _err "HTTP mirror did not come up on ${HTTP_MIRROR_HOST}:${HTTP_MIRROR_PORT}" - sleep 0.5 - done - - # Generate the Dockerfile for this variant - cat > "${WORKDIR}/Dockerfile" <<DOCKERFILE -FROM ${BASE_TAG} -LABEL maintainer="Eric Hameleers <alien@slackware.com>" - -# Import the Slackware GPG key against THIS mirror first: without it slackpkg -# cannot verify CHECKSUMS.md5 and silently installs almost nothing (only the -# packages already in base). 'yes YES |' answers the import prompt. -RUN yes YES | LC_ALL=C slackpkg -batch=on -default_answer=y update gpg - -# Update the slackpkg package list before installing so that we always -# get the versions current at build time, not the versions cached in the -# base image. -RUN LC_ALL=C slackpkg -batch=on -default_answer=y update - -# Download and install each individual package (thanks aclemons): -RUN sed -i 's/DOWNLOAD_ALL=on/DOWNLOAD_ALL=off/' /etc/slackpkg/slackpkg.conf - -# We don't care about a big firmware package: -RUN mv /etc/slackpkg/blacklist{,.keep} && \\ - echo kernel-firmware > /etc/slackpkg/blacklist - -# Install the full Slackware: -# All packages are installed in a single RUN layer to keep the image lean. -RUN export LC_ALL=C && \\ - for series in a ap d e f k kde l n t tcl x xap xfce y ; do \\ - slackpkg -delall=on -batch=on -default_answer=y install "\$series"/* ; done - -# And back to defaults: -RUN sed -i 's/DOWNLOAD_ALL=off/DOWNLOAD_ALL=on/' /etc/slackpkg/slackpkg.conf -RUN mv /etc/slackpkg/blacklist{.keep,} - - -# Delete package cache: -RUN rm -rf /var/cache/packages/* - -# Rebuild the linker cache after adding new libraries -RUN /sbin/ldconfig - -LABEL org.opencontainers.image.created="$(date -u +%Y-%m-%dT%H:%M:%SZ)" -LABEL org.opencontainers.image.title="Slackware Linux ${VERSION} full (x86_64)" -LABEL org.opencontainers.image.description="Slackware Linux ${VERSION} full image with all packages installed (x86_64)" -LABEL org.opencontainers.image.vendor="Slackware Linux" -LABEL org.opencontainers.image.licenses="GPL-2.0-or-later AND LGPL-2.1-or-later" -LABEL org.opencontainers.image.url="http://www.slackware.com" -LABEL org.opencontainers.image.source="https://forge.slackware.nl/slackware/docker-images" -LABEL org.opencontainers.image.revision="${VERSION}" -LABEL slackware.version="${VERSION}" -LABEL slackware.arch="x86_64" -LABEL ${DIGEST_LABEL}="${BASE_DIGEST}" -CMD ["/bin/bash"] -DOCKERFILE - - local BUILD_FLAGS=() - [[ "${FORCE}" == "true" ]] && BUILD_FLAGS+=(--no-cache) - - # Explicit exit checks: build_variant runs in an `if ! (...)` condition - # (see Main), which suppresses `set -e` inside this subshell, so a failed - # docker build would otherwise fall through to push a nonexistent tag and - # log "Done". Check each step and return non-zero on failure. - _log " Building ${FULL_TAG}..." - if ! docker build "${BUILD_FLAGS[@]}" \ - -t "${FULL_TAG}" \ - "${WORKDIR}"; then - _warn " build failed for ${FULL_TAG}; not pushing." - return 1 - fi - - _log " Pushing ${FULL_TAG}..." - if ! docker push "${FULL_TAG}"; then - _warn " push failed for ${FULL_TAG}." - return 1 - fi - - _log "=== Done: ${FULL_TAG} ===" -} - -# ============================================================================ -# Main -# ============================================================================ - -# A --force build passes --no-cache, so the stale build cache is dead weight: -# it still loads the containerd snapshotter's lease/lock bookkeeping and has -# raced the layer export ("failed to open writer: ref ... locked ... unavailable"). -# Prune it first to shrink that surface. Best-effort; never fail the build on it. -if [[ "${FORCE}" == "true" ]]; then - _log " --force: pruning build cache before rebuild" - docker builder prune -f >/dev/null 2>&1 || _warn " builder prune failed (ignored)" -fi - -rc=0 -for VERSION in "${BUILD_VARIANTS[@]}"; do - if ! ( build_variant "${VERSION}" ); then - _warn "variant ${VERSION} failed; continuing." - rc=1 - fi -done -exit "${rc}" |
