#!/usr/bin/env bash set -euo pipefail PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "${PROJECT_DIR}" usage() { echo "用法: $0 [端口]" echo " 端口: 可选,映射到本机 HTTP(容器内固定 5180)。也可用环境变量 HOST_PORT。" echo " 数据: 宿主机目录通过 HOST_DATA_DIR 指定,默认 <项目目录>/data,与容器 /app/data 绑定,避免重建容器丢数据。" echo "示例:" echo " $0 # 交互输入端口,默认 5180" echo " $0 8080 # 使用 8080" echo " HOST_PORT=3000 $0" echo " HOST_DATA_DIR=$HOME/vfxdemo-data $0 9000" } if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then usage exit 0 fi if ! command -v docker >/dev/null 2>&1; then echo "未检测到 docker,请先安装 Docker Desktop 或 Docker Engine。" exit 1 fi if ! docker info >/dev/null 2>&1; then echo "Docker 未启动,请先启动后重试。" exit 1 fi if docker compose version >/dev/null 2>&1; then COMPOSE_CMD=(docker compose) elif command -v docker-compose >/dev/null 2>&1; then COMPOSE_CMD=(docker-compose) else echo "未检测到 docker compose,请安装后重试。" exit 1 fi export DOCKER_BUILDKIT=1 export COMPOSE_DOCKER_CLI_BUILD=1 resolve_port() { if [ -n "${1:-}" ]; then printf '%s' "$1" return fi if [ -n "${HOST_PORT:-}" ]; then printf '%s' "${HOST_PORT}" return fi if [ -t 0 ]; then read -r -p "映射到本机的 HTTP 端口 [5180]: " _p printf '%s' "${_p:-5180}" return fi printf '%s' "5180" } HOST_PORT="$(resolve_port "${1:-}")" if ! [[ "$HOST_PORT" =~ ^[0-9]+$ ]] || [ "$HOST_PORT" -lt 1 ] || [ "$HOST_PORT" -gt 65535 ]; then echo "无效端口: ${HOST_PORT}" exit 1 fi export HOST_PORT DATA_DEFAULT="${PROJECT_DIR}/data" export HOST_DATA_DIR="${HOST_DATA_DIR:-${DATA_DEFAULT}}" mkdir -p "${HOST_DATA_DIR}" export HOST_DATA_DIR="$(cd "${HOST_DATA_DIR}" && pwd)" if command -v lsof >/dev/null 2>&1; then if lsof -nP -iTCP:"${HOST_PORT}" -sTCP:LISTEN >/dev/null 2>&1; then echo "警告: 本机端口 ${HOST_PORT} 已被占用,compose 可能启动失败。请换端口: $0 <端口>" fi fi echo "==> VFXdemo(国内镜像源构建)" echo " 本机端口: ${HOST_PORT} -> 容器 5180" echo " 数据目录: ${HOST_DATA_DIR} -> /app/data" "${COMPOSE_CMD[@]}" build --pull "${COMPOSE_CMD[@]}" up -d echo echo "访问: http://localhost:${HOST_PORT}" echo "日志: ${COMPOSE_CMD[*]} logs -f" echo "停止: ${COMPOSE_CMD[*]} down"