[#2] master模块离线构建方式

This commit is contained in:
yuyr 2025-09-24 09:25:06 +00:00
parent 12cfb9751b
commit 798419bbf9
9 changed files with 175 additions and 13 deletions

View File

@ -3,6 +3,7 @@ FROM python:3.11-slim
SHELL ["/bin/bash", "-c"] SHELL ["/bin/bash", "-c"]
ARG PIP_INDEX_URL= ARG PIP_INDEX_URL=
ARG USE_OFFLINE=0
ENV PIP_NO_CACHE_DIR=1 \ ENV PIP_NO_CACHE_DIR=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PYTHONPATH=/app PYTHONPATH=/app
@ -10,12 +11,18 @@ ENV PIP_NO_CACHE_DIR=1 \
WORKDIR /app WORKDIR /app
COPY requirements.txt ./ COPY requirements.txt ./
COPY offline_wheels/ /opt/offline_wheels/
RUN set -euxo pipefail \ RUN set -euxo pipefail \
&& python -m pip install --upgrade pip \ && if [[ "$USE_OFFLINE" == "1" ]]; then \
python -m pip install --no-index --find-links /opt/offline_wheels -r requirements.txt; \
else \
python -m pip install --upgrade pip \
&& if [[ -n "$PIP_INDEX_URL" ]]; then \ && if [[ -n "$PIP_INDEX_URL" ]]; then \
PIP_INDEX_URL="$PIP_INDEX_URL" python -m pip install -r requirements.txt; \ PIP_INDEX_URL="$PIP_INDEX_URL" python -m pip install -r requirements.txt; \
else \ else \
python -m pip install -r requirements.txt; \ python -m pip install -r requirements.txt; \
fi; \
fi fi
COPY app ./app COPY app ./app

View File

@ -14,6 +14,22 @@ cd src/master
./scripts/build_images.sh # 生成 argus-master:dev 镜像 ./scripts/build_images.sh # 生成 argus-master:dev 镜像
``` ```
如需离线构建,先在有网环境运行准备脚本:
```bash
cd src/master
./scripts/prepare_offline_wheels.sh --pip-version 25.2 # 可选 --clean
```
脚本会把 `requirements.txt` 及 pip 指定版本全部下载到 `offline_wheels/`。随后将源码目录(含该子目录)与基础镜像一并拷贝到内网,执行:
```bash
cd src/master
./scripts/build_images.sh --offline --tag argus-master:dev
```
若内网缺少 `python:3.11-slim`,请提前在外网 `docker save` 后通过离线介质 `docker load`
本仓库提供的端到端测试会使用 `src/master/tests/docker-compose.yml` 启动示例环境: 本仓库提供的端到端测试会使用 `src/master/tests/docker-compose.yml` 启动示例环境:
```bash ```bash
@ -124,6 +140,13 @@ cd src/master/tests
- `GET /healthz`:进程存活检查。 - `GET /healthz`:进程存活检查。
- `GET /readyz`:数据库可用性检查(会尝试访问 `DB_PATH`)。 - `GET /readyz`:数据库可用性检查(会尝试访问 `DB_PATH`)。
如需验证离线镜像,可使用自动化脚本:
```bash
cd src/master/tests
./scripts/00_e2e_test_offline.sh # 构建离线镜像并执行完整 E2E
```
## 端到端测试场景 ## 端到端测试场景
执行 `src/master/tests/scripts/00_e2e_test.sh` 会串联以下用例(脚本 0110 执行 `src/master/tests/scripts/00_e2e_test.sh` 会串联以下用例(脚本 0110
@ -146,4 +169,3 @@ cd src/master/tests
- 测试用例中的 `tests/private/``tests/tmp/` 会随脚本自动清理,避免污染后续运行。 - 测试用例中的 `tests/private/``tests/tmp/` 会随脚本自动清理,避免污染后续运行。
如需在生产环境运行,可将镜像推送到私有仓库,或参考测试 Compose 配置自行部署;只需确保上述环境变量在容器内正确设置即可。 如需在生产环境运行,可将镜像推送到私有仓库,或参考测试 Compose 配置自行部署;只需确保上述环境变量在容器内正确设置即可。

View File

View File

@ -2,13 +2,21 @@
set -euo pipefail set -euo pipefail
usage() { usage() {
echo "Usage: $0 [--intranet] [--tag <image_tag>]" >&2 cat >&2 <<'USAGE'
Usage: $0 [--intranet] [--offline] [--tag <image_tag>]
Options:
--intranet 使用指定的 PyPI 镜像源(默认清华镜像)。
--offline 完全离线构建,依赖 offline_wheels/ 目录中的离线依赖包。
--tag <image_tag> 自定义镜像标签,默认 argus-master:dev。
USAGE
} }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
IMAGE_TAG="${IMAGE_TAG:-argus-master:dev}" IMAGE_TAG="${IMAGE_TAG:-argus-master:dev}"
BUILD_ARGS=() BUILD_ARGS=()
OFFLINE_MODE=0
while [[ "$#" -gt 0 ]]; do while [[ "$#" -gt 0 ]]; do
case "$1" in case "$1" in
@ -17,6 +25,11 @@ while [[ "$#" -gt 0 ]]; do
BUILD_ARGS+=("--build-arg" "PIP_INDEX_URL=${INTRANET_INDEX}") BUILD_ARGS+=("--build-arg" "PIP_INDEX_URL=${INTRANET_INDEX}")
shift shift
;; ;;
--offline)
OFFLINE_MODE=1
BUILD_ARGS+=("--build-arg" "USE_OFFLINE=1")
shift
;;
--tag) --tag)
[[ $# -ge 2 ]] || { usage; exit 1; } [[ $# -ge 2 ]] || { usage; exit 1; }
IMAGE_TAG="$2" IMAGE_TAG="$2"
@ -34,6 +47,17 @@ while [[ "$#" -gt 0 ]]; do
esac esac
done done
if [[ "$OFFLINE_MODE" -eq 1 ]]; then
WHEELS_DIR="$PROJECT_ROOT/offline_wheels"
if [[ ! -d "$WHEELS_DIR" ]]; then
echo "[ERROR] offline_wheels 目录不存在: $WHEELS_DIR" >&2
exit 1
fi
if ! find "$WHEELS_DIR" -maxdepth 1 -type f -name '*.whl' -print -quit >/dev/null; then
echo "[WARN] offline_wheels 目录为空,请确保已提前下载所需的 wheel 包" >&2
fi
fi
echo "[INFO] Building image $IMAGE_TAG" echo "[INFO] Building image $IMAGE_TAG"
docker build "${BUILD_ARGS[@]}" -t "$IMAGE_TAG" "$PROJECT_ROOT" docker build "${BUILD_ARGS[@]}" -t "$IMAGE_TAG" "$PROJECT_ROOT"
echo "[OK] Image $IMAGE_TAG built" echo "[OK] Image $IMAGE_TAG built"

View File

@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat >&2 <<'USAGE'
Usage: $0 [--pip-version <version>] [--clean] [--local]
Options:
--pip-version <version> 额外下载指定版本的 pip wheel例如 25.2)。
--clean 清理 offline_wheels/*.whl 后重新下载。
--local 使用本地 python 执行下载(默认通过 docker python:3.11-slim
USAGE
}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
REQUIREMENTS_FILE="$PROJECT_ROOT/requirements.txt"
WHEEL_DIR="$PROJECT_ROOT/offline_wheels"
PIP_VERSION=""
CLEAN=0
USE_LOCAL=0
while [[ $# -gt 0 ]]; do
case "$1" in
--pip-version)
[[ $# -ge 2 ]] || { usage; exit 1; }
PIP_VERSION="$2"
shift 2
;;
--clean)
CLEAN=1
shift
;;
--local)
USE_LOCAL=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage
exit 1
;;
esac
done
if [[ ! -f "$REQUIREMENTS_FILE" ]]; then
echo "[ERROR] requirements.txt not found at $REQUIREMENTS_FILE" >&2
exit 1
fi
mkdir -p "$WHEEL_DIR"
if [[ "$CLEAN" -eq 1 ]]; then
echo "[INFO] Cleaning existing wheels in $WHEEL_DIR"
find "$WHEEL_DIR" -maxdepth 1 -type f -name '*.whl' -delete
fi
run_with_python() {
local cmd=("python" "-m" "pip" "$@")
eval "${cmd[@]}"
}
if [[ "$USE_LOCAL" -eq 1 ]]; then
PYTHON_BIN=${PYTHON_BIN:-python3}
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
echo "[ERROR] $PYTHON_BIN not found" >&2
exit 1
fi
echo "[INFO] Using local python ($PYTHON_BIN) to download wheels"
"$PYTHON_BIN" -m pip download -r "$REQUIREMENTS_FILE" -d "$WHEEL_DIR"
if [[ -n "$PIP_VERSION" ]]; then
"$PYTHON_BIN" -m pip download "pip==${PIP_VERSION}" -d "$WHEEL_DIR"
fi
else
if ! command -v docker >/dev/null 2>&1; then
echo "[ERROR] docker not found; rerun with --local or安装 docker" >&2
exit 1
fi
echo "[INFO] Using docker image python:3.11-slim 下载 wheel"
docker run --rm \
-v "$WHEEL_DIR":/wheels \
-v "$REQUIREMENTS_FILE":/tmp/requirements.txt \
python:3.11-slim \
bash -c "set -euo pipefail && python -m pip install --upgrade pip && python -m pip download -r /tmp/requirements.txt -d /wheels"
if [[ -n "$PIP_VERSION" ]]; then
docker run --rm \
-v "$WHEEL_DIR":/wheels \
python:3.11-slim \
bash -c "set -euo pipefail && python -m pip download pip==${PIP_VERSION} -d /wheels"
fi
fi
echo "[INFO] Offline wheels prepared at $WHEEL_DIR"

View File

@ -1,6 +1,6 @@
services: services:
master: master:
image: argus-master:dev image: ${MASTER_IMAGE_TAG:-argus-master:dev}
container_name: argus-master-e2e container_name: argus-master-e2e
environment: environment:
- OFFLINE_THRESHOLD_SECONDS=6 - OFFLINE_THRESHOLD_SECONDS=6

View File

@ -17,7 +17,7 @@ SCRIPTS=(
for script in "${SCRIPTS[@]}"; do for script in "${SCRIPTS[@]}"; do
echo "[TEST] Running $script" echo "[TEST] Running $script"
"$SCRIPT_DIR/$script" MASTER_IMAGE_TAG="${MASTER_IMAGE_TAG:-argus-master:dev}" "$SCRIPT_DIR/$script"
echo "[TEST] $script completed" echo "[TEST] $script completed"
echo echo
done done

View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
MASTER_ROOT="$(cd "$MODULE_ROOT/.." && pwd)"
# 准备离线依赖并构建镜像
pushd "$MASTER_ROOT" >/dev/null
./scripts/prepare_offline_wheels.sh --clean --pip-version 25.2
./scripts/build_images.sh --offline --tag argus-master:offline
popd >/dev/null
# 使用离线镜像执行既有端到端用例
MASTER_IMAGE_TAG="argus-master:offline" ./scripts/00_e2e_test.sh

View File

@ -29,13 +29,9 @@ mkdir -p "$PRIVATE_ROOT/argus/master"
mkdir -p "$PRIVATE_ROOT/argus/metric/prometheus" mkdir -p "$PRIVATE_ROOT/argus/metric/prometheus"
mkdir -p "$TMP_ROOT" mkdir -p "$TMP_ROOT"
pushd "$MODULE_ROOT" >/dev/null
./scripts/build_images.sh --tag argus-master:dev
popd >/dev/null
pushd "$TEST_ROOT" >/dev/null pushd "$TEST_ROOT" >/dev/null
compose down --remove-orphans || true compose down --remove-orphans || true
compose up -d MASTER_IMAGE_TAG="${MASTER_IMAGE_TAG:-argus-master:dev}" compose up -d
popd >/dev/null popd >/dev/null
echo "[INFO] Master container is up on http://localhost:31300" echo "[INFO] Master container is up on http://localhost:31300"