本文目录导读:

Shell脚本在多阶段构建Docker镜像中主要用于自动化构建流程,以下是几种常见的实现方式:
基础多阶段构建脚本
#!/bin/bash
# 多阶段构建Docker镜像
set -e
# 构建参数
APP_NAME="myapp"
VERSION=$(date +%Y%m%d-%H%M%S)
# 构建阶段
docker build \
--build-arg BUILD_VERSION=${VERSION} \
-t ${APP_NAME}:build \
-f Dockerfile.multistage \
--target builder \
.
# 最终阶段
docker build \
--build-arg BUILD_VERSION=${VERSION} \
-t ${APP_NAME}:${VERSION} \
-t ${APP_NAME}:latest \
-f Dockerfile.multistage \
--target final \
.
echo "镜像构建完成: ${APP_NAME}:${VERSION}"
带缓存的优化脚本
#!/bin/bash
set -e
# 配置
REGISTRY="registry.example.com"
APP="myapp"
TAG=$(git rev-parse --short HEAD)
# 利用缓存加速构建
docker build \
--cache-from ${REGISTRY}/${APP}:build-cache \
--cache-from ${REGISTRY}/${APP}:latest \
--target builder \
-t ${REGISTRY}/${APP}:build-cache \
-f Dockerfile.multistage \
.
docker build \
--cache-from ${REGISTRY}/${APP}:build-cache \
--cache-from ${REGISTRY}/${APP}:latest \
--target final \
-t ${REGISTRY}/${APP}:${TAG} \
-t ${REGISTRY}/${APP}:latest \
-f Dockerfile.multistage \
.
# 推送镜像
docker push ${REGISTRY}/${APP}:${TAG}
docker push ${REGISTRY}/${APP}:latest
对应的Dockerfile示例
# Dockerfile.multistage
# 第一阶段:构建阶段
FROM golang:1.21-alpine AS builder
ARG BUILD_VERSION
WORKDIR /app
# 复制依赖文件
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-X main.Version=${BUILD_VERSION}" \
-o /app/myapp .
# 第二阶段:测试阶段(可选)
FROM builder AS test
RUN go test ./... -v
# 第三阶段:最终镜像
FROM alpine:3.19 AS final
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/myapp .
# 配置运行时
EXPOSE 8080
USER nobody
ENTRYPOINT ["./myapp"]
高级多阶段构建脚本
#!/bin/bash
set -euo pipefail
# 配置
REPO="${REPO:-myapp}"
TAG="${TAG:-$(git describe --tags --always)}"
PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
log() {
echo -e "${GREEN}[INFO]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# 参数处理
while [[ $# -gt 0 ]]; do
case $1 in
--push) PUSH=true ;;
--no-cache) NO_CACHE="--no-cache" ;;
*) error "未知参数: $1" ;;
esac
shift
done
# 构建函数
build_stage() {
local target=$1
local tag=$2
local cache_from=""
if [ -z "${NO_CACHE:-}" ]; then
cache_from="--cache-from ${REPO}:${target}-cache"
fi
docker buildx build \
${cache_from} \
${NO_CACHE:-} \
--platform ${PLATFORMS} \
--target ${target} \
-t ${REPO}:${tag} \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=$(git rev-parse --short HEAD) \
${PUSH:+--push} \
.
}
# 清理旧缓存
log "清理旧的构建缓存..."
docker builder prune -f 2>/dev/null || true
# 多阶段构建
log "开始多阶段构建..."
# 阶段1: 依赖安装
log "阶段1: 安装依赖"
build_stage "dependencies" "deps-cache"
# 阶段2: 编译
log "阶段2: 编译项目"
build_stage "builder" "build-cache"
# 阶段3: 测试
log "阶段3: 运行测试"
build_stage "test" "test"
# 阶段4: 最终镜像
log "阶段4: 创建最终镜像"
build_stage "final" "${TAG}"
build_stage "final" "latest"
log "多阶段构建完成!"
支持多架构的构建脚本
#!/bin/bash set -e # 创建构建器 docker buildx create --name multiarch --use || true docker buildx inspect --bootstrap # 并行构建所有阶段 docker buildx build \ --platform linux/amd64,linux/arm64,linux/arm/v7 \ --target builder \ -t app:build-cache \ --cache-to type=inline \ . docker buildx build \ --platform linux/amd64,linux/arm64,linux/arm/v7 \ --target final \ -t app:latest \ -t app:$(git rev-parse --short HEAD) \ --cache-from app:build-cache \ --push \ .
CI/CD集成示例
# .gitlab-ci.yml
variables:
IMAGE_TAG: $CI_COMMIT_SHORT_SHA
stages:
- build
build_image:
stage: build
script:
- |
./build.sh \
--registry $CI_REGISTRY \
--tag $IMAGE_TAG \
--push
only:
- main
最佳实践:
- 使用
set -e确保脚本在错误时停止 - 合理使用构建缓存加速构建
- 分离开发和构建阶段,优化最终镜像大小
- 使用环境变量管理配置
- 添加适当的日志输出和错误处理