将条件从 || 改为 &&,确保必须同时找到项目文件和 sln 文件才认定为正确的仓库根目录,防止在错误的仓库中运行脚本。 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
97 lines
3.7 KiB
Bash
Executable File
97 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 用法:在 Linux 终端执行本脚本,后台启动 TenantApi 的 dotnet watch(开发用,不需要 docker build)。
|
||
# 前置:已安装并运行 Docker。
|
||
set -euo pipefail
|
||
trap 'echo "发生错误:${BASH_COMMAND}" >&2' ERR
|
||
|
||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
container_name="${CONTAINER_NAME:-takeout.api.tenant}"
|
||
docker_network="${DOCKER_NETWORK:-web_apps}"
|
||
host_port="${HOST_PORT:-7903}"
|
||
container_port="${CONTAINER_PORT:-7903}"
|
||
sdk_image="${SDK_IMAGE:-mcr.microsoft.com/dotnet/sdk:10.0}"
|
||
nuget_volume="${NUGET_VOLUME:-takeout-nuget}"
|
||
project_path="${PROJECT_PATH:-src/Api/TakeoutSaaS.TenantApi/TakeoutSaaS.TenantApi.csproj}"
|
||
environment="${ASPNETCORE_ENVIRONMENT:-Development}"
|
||
|
||
repo_root=""
|
||
candidate_dir="${script_dir}"
|
||
for _ in 0 1 2 3 4 5; do
|
||
# 必须同时满足:项目文件存在 且 sln 文件存在
|
||
if [ -f "${candidate_dir}/${project_path}" ] && [ -f "${candidate_dir}/TakeoutSaaS.sln" ]; then
|
||
repo_root="${candidate_dir}"
|
||
break
|
||
fi
|
||
|
||
candidate_dir="$(cd "${candidate_dir}/.." && pwd)"
|
||
done
|
||
|
||
if [ -z "${repo_root}" ]; then
|
||
echo "未找到仓库根目录(需要同时存在 ${project_path} 和 TakeoutSaaS.sln),请在 TenantApi 仓库中运行该脚本。" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "工作目录:${repo_root}"
|
||
echo "使用 SDK 镜像:${sdk_image}"
|
||
echo "容器:${container_name} 端口:${host_port}:${container_port} 网络:${docker_network}"
|
||
echo "项目:${project_path} 环境:${environment}"
|
||
|
||
# 1. (空行后) 确保 network 存在(用于连接同网络内的 postgres/redis 等依赖)
|
||
if [ -n "${docker_network}" ]; then
|
||
if ! docker network inspect "${docker_network}" >/dev/null 2>&1; then
|
||
echo "Docker network 不存在,正在创建:${docker_network}"
|
||
docker network create "${docker_network}" >/dev/null
|
||
fi
|
||
fi
|
||
|
||
# 2. (空行后) 持久化 NuGet 缓存,加速 restore/build
|
||
if ! docker volume inspect "${nuget_volume}" >/dev/null 2>&1; then
|
||
echo "NuGet volume 不存在,正在创建:${nuget_volume}"
|
||
docker volume create "${nuget_volume}" >/dev/null
|
||
fi
|
||
|
||
# 3. (空行后) 替换旧容器(如存在)
|
||
if docker ps -a --format '{{.Names}}' | grep -qx "${container_name}"; then
|
||
echo "发现旧容器,正在移除:${container_name}"
|
||
docker rm -f "${container_name}" >/dev/null
|
||
fi
|
||
|
||
run_args=()
|
||
if [ -n "${docker_network}" ]; then
|
||
run_args+=(--network "${docker_network}")
|
||
fi
|
||
|
||
# 4. 代理配置(用于 dotnet restore 访问 nuget.org)
|
||
proxy_host="172.18.0.1"
|
||
proxy_port="7890"
|
||
proxy_env_args=()
|
||
if [ "${USE_PROXY:-1}" = "1" ]; then
|
||
proxy_env_args+=(-e "HTTP_PROXY=http://${proxy_host}:${proxy_port}")
|
||
proxy_env_args+=(-e "HTTPS_PROXY=http://${proxy_host}:${proxy_port}")
|
||
proxy_env_args+=(-e "http_proxy=http://${proxy_host}:${proxy_port}")
|
||
proxy_env_args+=(-e "https_proxy=http://${proxy_host}:${proxy_port}")
|
||
proxy_env_args+=(-e "NO_PROXY=localhost,127.0.0.1,::1")
|
||
proxy_env_args+=(-e "no_proxy=localhost,127.0.0.1,::1")
|
||
echo "已启用代理:http://${proxy_host}:${proxy_port}"
|
||
fi
|
||
|
||
echo "启动 dotnet watch(后台运行)..."
|
||
docker run -d --name "${container_name}" \
|
||
"${run_args[@]}" \
|
||
--restart=always \
|
||
-p "${host_port}:${container_port}" \
|
||
-v "${repo_root}":/src \
|
||
-w /src \
|
||
-v "${nuget_volume}":/root/.nuget/packages \
|
||
-e ASPNETCORE_ENVIRONMENT="${environment}" \
|
||
-e ASPNETCORE_URLS="http://+:${container_port}" \
|
||
-e DOTNET_USE_POLLING_FILE_WATCHER=1 \
|
||
-e DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER=1 \
|
||
"${proxy_env_args[@]}" \
|
||
"${sdk_image}" \
|
||
dotnet watch --project "${project_path}" run --no-launch-profile
|
||
|
||
echo "已启动。查看日志:docker logs -f ${container_name}"
|
||
echo "Swagger:http://localhost:${host_port}/api/docs (兼容入口 /swagger)"
|