#!/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)"