No plans atm. Squash was never taken out of experimental and is only supported in moby outside the builder component. You should squash layers with a multi-stage dockerfile(if you are sure you know what you are doing and need to squash at all).
#!/bin/sh ################################################################################ # The setups in this file belong to https://code.shin.company/docker-squash # I appreciate you respecting my intellectual efforts in creating them. # If you intend to copy or use ideas from this project, please credit properly. # Author: SHIN Company <shin@shin.company> # License: https://code.shin.company/docker-squash/blob/main/LICENSE ################################################################################
# Check if Docker is installed, if not exit if [ ! -x "$(command -v docker)" ]; then echo"Docker is not installed. Please install Docker and try again." >&2 exit 1 fi
usage() { cat <<EOF Combines Docker image layers into a single layer, reducing storage space and improving runtime performance by decreasing mount points. Usage: ${0##*/} <source_image> [build_options] Arguments: source_image The original image ID or name:tag to be squashed. An absolute path to your Dockerfile can also be used. build_options Optional Docker build options like --build-arg, --label, etc. Author: SHIN Company <shin@shin.company> License: https://code.shin.company/docker-squash/blob/main/LICENSE EOF }
if [ -z "$id" ]; then echo"Invalid docker image: $1. Please build or pull the image first." >&2 exit 1 fi
local base="scratch" localalias="temp-$id" local tag="$(get_name "$id")" local labels="$(get_labels "$id")" local shell="$(get_shell "$id")" local envs="$(get_envs "$id")" local onbuilds="$(get_onbuilds "$id")" local exposes="$(get_exposes "$id")" local workdir="$(get_workdir "$id")" local user="$(get_user "$id")" local volumes="$(get_volumes "$id")" local entrypoint="$(get_entrypoint "$id")" local cmd="$(get_cmd "$id")" local stopsignal="$(get_stopsignal "$id")" local healthcheck="$(get_healthcheck "$id")"
awk NF <<Dockerfile ################################################################################ # Base image: $tag (Image ID: $id) # Created at: $(date -u +"%Y-%m-%dT%H:%M:%SZ") # Created by: https://code.shin.company/docker-squash ################################################################################ # CLEANING UP THE SOURCE IMAGE. ################################################ # Enable SBOM attestations # See: https://docs.docker.com/build/attestations/sbom/ ARG BUILDKIT_SBOM_SCAN_CONTEXT=true FROM $tag AS $alias ARG BUILDKIT_SBOM_SCAN_STAGE=true # Pre-squash scripts may be useful to clean the source image before squashing. # Use build argument to add your pre-squash scripts, and run them in this stage. # Example: # ${0##*/} $tag --build-arg PRESQUASH_SCRIPTS="rm -rf /tmp/*" # ${0##*/} $tag --build-arg PRESQUASH_SCRIPTS="/path/to/script.sh" ARG PRESQUASH_SCRIPTS="\${PRESQUASH_SCRIPTS:-rm -rf /tmp/* /usr/share/doc/* /var/cache/* /var/lib/apt/lists/* /var/log/*}" RUN [ ! -z "\$PRESQUASH_SCRIPTS" ] && sh -c "\$PRESQUASH_SCRIPTS" || true ################################################################################ # BUILDING SQUASHED IMAGE FROM SCRATCH. ######################################## FROM $base AS squashed-$id ARG BUILDKIT_SBOM_SCAN_STAGE=true COPY --link --from=$alias / / $(if [ -n "$labels" ]; then echo "$labels"; fi) $(if [ -n "$shell" ]; then echo "SHELL $shell"; fi) $(if [ -n "$envs" ]; then echo "$envs"; fi) $(if [ -n "$onbuilds" ]; then echo "$onbuilds"; fi) $(if [ -n "$exposes" ]; then echo "$exposes"; fi) $(if [ -n "$workdir" ]; then echo "WORKDIR $workdir"; fi) $(if [ -n "$user" ]; then echo "USER $user"; fi) $(if [ -n "$volumes" ]; then echo "$volumes"; fi) $(if [ -n "$entrypoint" ]; then echo "ENTRYPOINT $entrypoint"; fi) $(if [ -n "$cmd" ]; then echo "CMD $cmd"; fi) $(if [ -n "$stopsignal" ]; then echo "STOPSIGNAL $stopsignal"; fi) $(if [ -n "$healthcheck" ]; then echo "HEALTHCHECK $healthcheck"; fi) # FINISH. ###################################################################### ################################################################################ Dockerfile }
# Check Source Image / Build From Dockerfile ################################################################################
# Enable debug mode if [ ! -z "$DEBUG" ]; thenset -ex; fi
# Build tempoprary image from Dockerfile if [ -f "$dockerfile" ]; then hash="$(sha256sum "$dockerfile")/$(echo $@ | sha256sum)" temptag="docker-squash-build-$(echo $hash | sha256sum | head -c 8)" context="$(dirname "$dockerfile")"
if ! docker build -f "$dockerfile""$context""$@" -t "$temptag"; then echo"Failed to build image from $dockerfile." >&2 exit 1 fi
source="$temptag" cleanup="${CLEAR_TEMP_BUILD:-1}" else # try pulling the docker image from Docker Hub if [ -z "$(get_name "$dockerfile")" ]; then docker pull "$dockerfile" 2>&1 fi
source="$(get_name "$dockerfile")" fi
# Check if source exists if [ -z "$source" ]; then echo"Invalid image data from '$dockerfile'. Please build or pull the image first." >&2 exit 1 fi
# Squash / Output to New Dockerfile ################################################################################
# Print Dockerfile to stdout if [ ! -z "$print" ]; then generate "$source" exit 0 fi
# Use Docker buildx if available BUILD_CMD="docker build" if docker buildx version &>/dev/null; then BUILD_CMD="docker buildx build" fi
FROM $tag AS $alias ARG BUILDKIT_SBOM_SCAN_STAGE=true # Pre-squash scripts may be useful to clean the source image before squashing. # Use build argument to add your pre-squash scripts, and run them in this stage. # Example: # ${0##*/} $tag --build-arg PRESQUASH_SCRIPTS="rm -rf /tmp/*" # ${0##*/} $tag --build-arg PRESQUASH_SCRIPTS="/path/to/script.sh" ARG PRESQUASH_SCRIPTS="\${PRESQUASH_SCRIPTS:-rm -rf /tmp/* /usr/share/doc/* /var/cache/* /var/lib/apt/lists/* /var/log/*}" RUN [ ! -z "\$PRESQUASH_SCRIPTS" ] && sh -c "\$PRESQUASH_SCRIPTS" || true
################################################################################ # BUILDING SQUASHED IMAGE FROM SCRATCH. ######################################## FROM $base AS squashed-$id ARG BUILDKIT_SBOM_SCAN_STAGE=true COPY --link --from=$alias / / $(if [ -n "$labels" ]; then echo "$labels"; fi) $(if [ -n "$shell" ]; then echo "SHELL $shell"; fi) $(if [ -n "$envs" ]; then echo "$envs"; fi) $(if [ -n "$onbuilds" ]; then echo "$onbuilds"; fi) $(if [ -n "$exposes" ]; then echo "$exposes"; fi) $(if [ -n "$workdir" ]; then echo "WORKDIR $workdir"; fi) $(if [ -n "$user" ]; then echo "USER $user"; fi) $(if [ -n "$volumes" ]; then echo "$volumes"; fi) $(if [ -n "$entrypoint" ]; then echo "ENTRYPOINT $entrypoint"; fi) $(if [ -n "$cmd" ]; then echo "CMD $cmd"; fi) $(if [ -n "$stopsignal" ]; then echo "STOPSIGNAL $stopsignal"; fi) $(if [ -n "$healthcheck" ]; then echo "HEALTHCHECK $healthcheck"; fi)
Create a minimal base image using scratch
The reserved, minimal scratch image serves as a starting point for building containers. Using the scratch image signals to the build process that you want the next command in the Dockerfile to be the first filesystem layer in your image.