117 lines
3.1 KiB
Bash
Executable File
117 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
sed -n '2,22p' "$0"
|
|
}
|
|
|
|
# Build and publish a Docker image with buildx.
|
|
#
|
|
# Usage:
|
|
# publish.sh --registry HOST --repository PATH --tag TAG --platform PLATFORMS [options]
|
|
#
|
|
# Options:
|
|
# --registry HOST Registry host, without a URL scheme
|
|
# --repository PATH Repository path, such as team/service
|
|
# --tag TAG Image tag
|
|
# --platform LIST Comma-separated platforms
|
|
# --file PATH Dockerfile path (default: Dockerfile)
|
|
# --context PATH Build context (default: .)
|
|
# --builder NAME Existing buildx builder
|
|
# --load Load a single-platform image instead of pushing
|
|
# --dry-run Print the resolved build without executing it
|
|
# --help Show this help
|
|
|
|
registry=
|
|
repository=
|
|
tag=
|
|
platform=
|
|
dockerfile=Dockerfile
|
|
build_context=.
|
|
builder=
|
|
mode=push
|
|
dry_run=false
|
|
|
|
while (($#)); do
|
|
case "$1" in
|
|
--registry) registry=${2-}; shift 2 ;;
|
|
--repository) repository=${2-}; shift 2 ;;
|
|
--tag) tag=${2-}; shift 2 ;;
|
|
--platform) platform=${2-}; shift 2 ;;
|
|
--file) dockerfile=${2-}; shift 2 ;;
|
|
--context) build_context=${2-}; shift 2 ;;
|
|
--builder) builder=${2-}; shift 2 ;;
|
|
--load) mode=load; shift ;;
|
|
--dry-run) dry_run=true; shift ;;
|
|
--help|-h) usage; exit 0 ;;
|
|
*) printf 'Unknown argument: %s\n' "$1" >&2; usage >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
for required_name in registry repository tag platform; do
|
|
if [[ -z ${!required_name} ]]; then
|
|
printf 'Missing required option: --%s\n' "$required_name" >&2
|
|
exit 2
|
|
fi
|
|
done
|
|
|
|
if [[ $registry == *://* || $registry == */* ]]; then
|
|
printf '%s\n' 'Registry must be a host without a URL scheme or path.' >&2
|
|
exit 2
|
|
fi
|
|
if [[ $repository == /* || $repository == */ || $repository != */* ]]; then
|
|
printf '%s\n' 'Repository must look like namespace/image.' >&2
|
|
exit 2
|
|
fi
|
|
if [[ $tag == *:* || $tag == */* ]]; then
|
|
printf '%s\n' 'Tag must not contain ":" or "/".' >&2
|
|
exit 2
|
|
fi
|
|
if [[ $mode == load && $platform == *,* ]]; then
|
|
printf '%s\n' '--load supports only one platform.' >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! -f $dockerfile ]]; then
|
|
printf 'Dockerfile not found: %s\n' "$dockerfile" >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! -d $build_context ]]; then
|
|
printf 'Build context not found: %s\n' "$build_context" >&2
|
|
exit 2
|
|
fi
|
|
if [[ $dry_run == false ]] && ! command -v docker >/dev/null 2>&1; then
|
|
printf '%s\n' 'docker is not installed or not available in PATH.' >&2
|
|
exit 127
|
|
fi
|
|
|
|
image_ref="${registry}/${repository}:${tag}"
|
|
build_cmd=(docker buildx build --file "$dockerfile" --platform "$platform" --tag "$image_ref")
|
|
if [[ -n $builder ]]; then
|
|
build_cmd+=(--builder "$builder")
|
|
fi
|
|
if [[ $mode == push ]]; then
|
|
build_cmd+=(--push)
|
|
else
|
|
build_cmd+=(--load)
|
|
fi
|
|
build_cmd+=("$build_context")
|
|
|
|
printf 'Image: %s\n' "$image_ref"
|
|
printf 'Platform: %s\n' "$platform"
|
|
printf 'Dockerfile: %s\n' "$dockerfile"
|
|
printf 'Context: %s\n' "$build_context"
|
|
printf 'Mode: %s\n' "$mode"
|
|
|
|
if [[ $dry_run == true ]]; then
|
|
printf 'Command:'
|
|
printf ' %q' "${build_cmd[@]}"
|
|
printf '\n'
|
|
exit 0
|
|
fi
|
|
|
|
"${build_cmd[@]}"
|
|
|
|
if [[ $mode == push ]]; then
|
|
docker buildx imagetools inspect "$image_ref"
|
|
fi
|