Shell脚本如何多阶段构建镜像

wen 实用脚本 2

本文目录导读:

Shell脚本如何多阶段构建镜像

  1. 基础多阶段构建脚本
  2. 带缓存的优化脚本
  3. 对应的Dockerfile示例
  4. 高级多阶段构建脚本
  5. 支持多架构的构建脚本
  6. CI/CD集成示例

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 确保脚本在错误时停止
  • 合理使用构建缓存加速构建
  • 分离开发和构建阶段,优化最终镜像大小
  • 使用环境变量管理配置
  • 添加适当的日志输出和错误处理

抱歉,评论功能暂时关闭!