Files
thebet365/docs/docker/build-and-export-images.sh
2026-06-13 22:16:14 +08:00

158 lines
4.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 构建 api / player / admin 生产镜像并导出为 tar
# 用法:
# ./docs/docker/build-and-export-images.sh
# ./docs/docker/build-and-export-images.sh --tag v1.2.3
# ./build-and-export-images.sh --use-cache
# ./build-and-export-images.sh --export-only
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$ROOT"
COMPOSE_FILE="docker-compose.prod.yml"
ENV_FILE=".env.docker"
OUTPUT=""
SERVICES=(api player admin)
NO_CACHE=1
EXPORT_ONLY=0
TAG="${IMAGE_TAG:-}"
default_tag() {
if command -v git >/dev/null 2>&1 && git rev-parse --short HEAD >/dev/null 2>&1; then
git rev-parse --short HEAD
else
date +%Y%m%d-%H%M%S
fi
}
validate_tag() {
printf '%s' "$1" | grep -Eq '^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$' ||
{ echo "错误: 镜像 tag 不合法: $1" >&2; exit 1; }
}
usage() {
cat <<'EOF'
用法: docs/docker/build-and-export-images.sh [选项]
选项:
--tag TAG 镜像 tag默认当前 git 短提交号;非 git 目录则用时间戳)
--use-cache 构建时使用 Docker 缓存(默认 --no-cache
--export-only 跳过构建,仅导出已有指定 tag 镜像
--output PATH 导出文件路径(默认项目根目录 thebet365-images-<tag>.tar
-h, --help 显示帮助
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--tag)
TAG="${2:?缺少 --tag 参数值}"
shift 2
;;
--use-cache) NO_CACHE=0; shift ;;
--export-only) EXPORT_ONLY=1; shift ;;
--output)
OUTPUT="${2:?缺少 --output 参数值}"
shift 2
;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1" >&2; usage; exit 1 ;;
esac
done
if [[ ! -f "$COMPOSE_FILE" ]]; then
echo "错误: 未找到 ${COMPOSE_FILE}(目录: ${ROOT}" >&2
exit 1
fi
if [[ ! -f "$ENV_FILE" ]]; then
if [[ -f ".env.docker.example" ]]; then
echo "警告: 未找到 ${ENV_FILE},将使用 .env.docker.example生产部署请复制为 .env.docker 并修改密钥)"
ENV_FILE=".env.docker.example"
else
echo "错误: 未找到 ${ENV_FILE} 或 .env.docker.example" >&2
exit 1
fi
fi
TAG="${TAG:-$(default_tag)}"
validate_tag "$TAG"
OUTPUT="${OUTPUT:-thebet365-images-$TAG.tar}"
if [[ "$EXPORT_ONLY" -eq 0 ]]; then
echo "==> 构建镜像: ${SERVICES[*]} (tag: $TAG)"
BUILD_ARGS=(compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build)
if [[ "$NO_CACHE" -eq 1 ]]; then
BUILD_ARGS+=(--no-cache)
fi
BUILD_ARGS+=("${SERVICES[@]}")
IMAGE_TAG="$TAG" docker "${BUILD_ARGS[@]}"
fi
OUTPUT_PATH="$OUTPUT"
if [[ "$OUTPUT" != /* ]] && [[ "$OUTPUT" != [A-Za-z]:* ]]; then
OUTPUT_PATH="$ROOT/$OUTPUT"
fi
echo "==> 导出镜像 -> $OUTPUT_PATH"
docker save \
"thebet365-api:$TAG" \
"thebet365-player:$TAG" \
"thebet365-admin:$TAG" \
-o "$OUTPUT_PATH"
MANIFEST_PATH="${OUTPUT_PATH%.tar}.manifest.txt"
BUILT_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
GIT_COMMIT="unknown"
GIT_DIRTY="unknown"
if command -v git >/dev/null 2>&1 && git rev-parse HEAD >/dev/null 2>&1; then
GIT_COMMIT="$(git rev-parse HEAD)"
if git diff --quiet && git diff --cached --quiet; then
GIT_DIRTY="false"
else
GIT_DIRTY="true"
fi
fi
CHECKSUM="unavailable"
if command -v sha256sum >/dev/null 2>&1; then
CHECKSUM="$(sha256sum "$OUTPUT_PATH" | awk '{print $1}')"
elif command -v shasum >/dev/null 2>&1; then
CHECKSUM="$(shasum -a 256 "$OUTPUT_PATH" | awk '{print $1}')"
fi
{
echo "tag=$TAG"
echo "built_at=$BUILT_AT"
echo "git_commit=$GIT_COMMIT"
echo "git_dirty=$GIT_DIRTY"
echo "tar=$(basename "$OUTPUT_PATH")"
echo "tar_sha256=$CHECKSUM"
echo "api_image=thebet365-api:$TAG"
echo "api_image_id=$(docker image inspect "thebet365-api:$TAG" --format '{{.Id}}')"
echo "player_image=thebet365-player:$TAG"
echo "player_image_id=$(docker image inspect "thebet365-player:$TAG" --format '{{.Id}}')"
echo "admin_image=thebet365-admin:$TAG"
echo "admin_image_id=$(docker image inspect "thebet365-admin:$TAG" --format '{{.Id}}')"
} > "$MANIFEST_PATH"
if command -v du >/dev/null 2>&1; then
SIZE="$(du -h "$OUTPUT_PATH" | awk '{print $1}')"
echo "完成: $OUTPUT_PATH ($SIZE)"
else
echo "完成: $OUTPUT_PATH"
fi
echo "Manifest: $MANIFEST_PATH"
cat <<EOF
服务器首次部署:
./scripts/deploy-first.sh --images $(basename "$OUTPUT_PATH") --tag $TAG
服务器后续更新:
./scripts/deploy-update.sh --images $(basename "$OUTPUT_PATH") --tag $TAG
EOF