#!/bin/bash # Ver: 1.0 by Endial Fang (endial@126.com) # # Docker 镜像构建脚本 (仅linux/amd64) # 编译后镜像名称 IMAGE_NAME="alpine" # 依赖镜像的仓库地址(本镜像需要依赖原生 alpine 镜像) REGISTRY_URL="swr.cn-north-4.myhuaweicloud.com/img-sync/docker.io/" # 源仓库地址(本地编译时,使用阿里云源仓库) APT_SOURCE="aliyun" APP_VER="3.23" # 获取发布版本标签 get_release_tag() { if ! git rev-parse --git-dir >/dev/null 2>&1; then echo "unknown" elif [ -n "$(git status --porcelain)" ]; then echo "latest" else # 尝试获取最近的git标签 local tag=$(git describe --tags --abbrev=0 2>/dev/null) if [ -n "$tag" ]; then echo "$tag" else local branch=$(git rev-parse --abbrev-ref HEAD) case "$branch" in master|main) echo "latest" ;; *) echo "$branch" ;; esac fi fi } # 获取镜像完整TAG get_image_tag() { local CURRENT_SUBVERSION if git rev-parse --git-dir >/dev/null 2>&1; then if [ -z "$(git status --porcelain)" ]; then CURRENT_SUBVERSION=$(git rev-parse --short=12 HEAD) else CURRENT_SUBVERSION=$(date +%Y%m%d-%H%M%S) fi local branch=$(git rev-parse --abbrev-ref HEAD) branch=$(echo "$branch" | sed -e 's/master/latest/' -e 's/main/latest/') echo "${branch}-${CURRENT_SUBVERSION}" else CURRENT_SUBVERSION=$(date +%Y%m%d-%H%M%S) echo "latest-${CURRENT_SUBVERSION}" fi } # 根据当前系统架构构建镜像 build() { local TAG=${1:-$(get_image_tag)} # 获取当前系统的架构 local ARCH=$(uname -m) local PLATFORM="" case "$ARCH" in x86_64) PLATFORM="linux/amd64" ;; aarch64|arm64) PLATFORM="linux/arm64" ;; armv7l) PLATFORM="linux/arm/v7" ;; *) PLATFORM="linux/amd64" # 默认为 amd64 ;; esac # 如果在命令中指定了TAG,则使用相同的TAG作为APP_VER if [ -n "$1" ]; then APP_VER="$1" else # 获取当前分支名并判断是否为主分支 local branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) if [ "$branch" != "master" ] && [ "$branch" != "main" ]; then # 如果不是主分支,则使用分支名或标签名 local tag=$(git describe --tags --abbrev=0 2>/dev/null) if [ -n "$tag" ] && [ "$(git rev-list -n 1 $tag 2>/dev/null)" = "$(git rev-parse HEAD)" ]; then # 如果当前提交正好是标签,则使用标签名 APP_VER="$tag" else # 否则使用分支名 APP_VER="$branch" fi fi fi # 去除APP_VER中的v前缀,仅保留数字分段部分 APP_VER=$(echo "$APP_VER" | sed 's/^v//') echo "Building image ${IMAGE_NAME}:${TAG} (${PLATFORM}) with APP_VER=${APP_VER}" podman build --platform ${PLATFORM} \ --progress plain --force-rm \ --build-arg REGISTRY_URL=${REGISTRY_URL} \ --build-arg APT_SOURCE=${APT_SOURCE} \ --build-arg APP_VER=${APP_VER} \ -t ${IMAGE_NAME}:${TAG} \ -t ${IMAGE_NAME}:latest \ . echo "Build complete" } # 清理工作空间 clean() { echo "Cleaning workspace..." # 删除所有与 IMAGE_NAME 相关的镜像标签(包括带 localhost 前缀的) podman images --format "{{.Repository}}:{{.Tag}}" | grep -E "^(${IMAGE_NAME}|localhost/${IMAGE_NAME}):" | xargs -r podman rmi -f # 删除所有已退出的容器 podman ps -a --format "{{.ID}}" --filter status=exited | xargs -r podman rm # 删除所有悬空镜像(dangling images) podman images --filter "dangling=true" -q | xargs -r podman rmi -f # 清理构建缓存 podman system prune -f } # 显示使用帮助信息 show_help() { cat << EOF Usage: $0 [COMMAND] [TAG] Docker 镜像构建和清理脚本 COMMANDS: build [tag] 构建镜像,可选择性指定标签,如未指定则自动生成 clean 清理工作空间,删除相关镜像和无用容器 help 显示此帮助信息 EXAMPLES: $0 build # 构建镜像,使用自动生成的标签 $0 build mytag # 构建镜像,使用指定标签 $0 clean # 清理工作空间 $0 help # 显示帮助信息 DESCRIPTION: 该脚本用于构建 alpine 镜像,支持自动生成标签,包含清理功能。 构建的镜像名称为 ${IMAGE_NAME},默认会同时生成 latest 标签。 脚本会根据当前系统架构自动构建对应架构的镜像,并设置 APP_VER 参数(自动去除v前缀): - 根据当前系统架构自动选择平台(linux/amd64, linux/arm64, linux/arm/v7 等) - 当在命令中指定TAG时,APP_VER使用相同的TAG值(去除v前缀) - 主分支(master/main)时使用 latest - 其他分支时使用分支名 - 标签提交时使用标签名(去除v前缀) EOF } # 主函数 main() { case "$1" in build) build "$2" ;; # 传递第二个参数作为标签 clean) clean ;; help|-h|--help) show_help ;; *) if [ -z "$1" ]; then show_help else echo "Error: Unknown command '$1'" echo "" show_help exit 1 fi ;; esac } main "$@"