一键化部署

news2025/5/27 16:52:50

好的,我明白了。你希望脚本变得更简洁,主要负责:

  1. 代码克隆:从 GitHub 克隆你的后端和前端项目,并在克隆前确保目标目录为空。
  2. 文件复制:将你预先准备好Dockerfile (后端和前端各一个)、前端的 nginx.conf 以及 docker-compose.yml 文件从你本地的指定位置复制到新创建的项目目录结构中。
  3. 数据库脚本处理:尝试从克隆的后端项目中复制 db.sql
  4. 一键部署:使用复制过来的 docker-compose.yml 文件启动服务。

这样,Dockerfiledocker-compose.yml 的具体内容就由你维护在本地文件中,脚本只负责“组装”和执行。


步骤 1: 准备你的本地配置文件

在运行脚本之前,你需要在你的电脑上准备好以下文件。假设你将这些文件统一存放在一个地方,例如 ~/my_docker_configs/ 目录下 (你可以选择任何你方便的路径,并在脚本中配置)。

  1. 后端 Dockerfile (~/my_docker_configs/Dockerfile.backend):

    • 这个 Dockerfile 用于构建你的 Spring Boot 应用。
    • 不应该包含 git clone 指令。
    • 内容可以参考我们之前讨论过的后端 Dockerfile (没有 git clone 的版本)。例如: Dockerfile

      # ~/my_docker_configs/Dockerfile.backend
      FROM openjdk:17-jdk-slim
      WORKDIR /app
      COPY .mvn/ .mvn
      COPY mvnw .
      COPY pom.xml .
      RUN ./mvnw dependency:go-offline -B
      COPY src ./src
      RUN ./mvnw package -DskipTests
      FROM openjdk:17-jre-slim
      WORKDIR /app
      COPY --from=0 /app/target/*.jar app.jar
      EXPOSE 8080
      ENTRYPOINT ["java", "-jar", "app.jar"]
      
  2. 前端 Dockerfile (~/my_docker_configs/Dockerfile.frontend):

    • 这个 Dockerfile 用于构建你的 React 应用并配置 Nginx。
    • 不应该包含 git clone 指令。
    • 内容可以参考我们之前讨论过的前端 Dockerfile (没有 git clone 的版本)。例如: Dockerfile

      # ~/my_docker_configs/Dockerfile.frontend
      FROM node:18-alpine as builder
      WORKDIR /app
      COPY package*.json ./
      RUN npm install
      COPY . .
      RUN npm run build
      FROM nginx:stable-alpine
      COPY --from=builder /app/dist /usr/share/nginx/html
      COPY nginx.conf /etc/nginx/conf.d/default.conf # nginx.conf 将被脚本复制到构建上下文中
      EXPOSE 80
      CMD ["nginx", "-g", "daemon off;"]
      
  3. 前端 Nginx 配置文件 (~/my_docker_configs/nginx.conf):

    • 这是 Nginx 用来服务 React 应用的配置文件。
    • 内容可以参考我们之前讨论过的 nginx.conf。例如: Nginx

      # ~/my_docker_configs/nginx.conf
      server {
          listen 80;
          server_name localhost;
          root /usr/share/nginx/html;
          index index.html index.htm;
          location / {
              try_files $uri $uri/ /index.html;
          }
      }
      
  4. Docker Compose 文件 (~/my_docker_configs/docker-compose.yml.template):

    • 这是核心的编排文件。注意,我建议将其命名为 docker-compose.yml.template,脚本会将其复制并重命名为 docker-compose.yml
    • 重要: 这个 docker-compose.yml 文件中的 build.context 应该指向脚本克隆代码后并放入 Dockerfile 的目录。
    • 内容可以参考我们之前讨论过的 docker-compose.yml,但 build 部分是关键。例如: YAML

      # ~/my_docker_configs/docker-compose.yml.template
      version: '3.8'
      
      services:
        backend:
          build:
            context: ./backend  # 脚本会将代码克隆到 'backend', Dockerfile 也会被复制到 'backend/Dockerfile'
            dockerfile: Dockerfile
          container_name: my-springboot-app
          ports:
            - "8080:8080"
          environment:
            # 保持你的数据库环境变量配置
            - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydatabase?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
            - SPRING_DATASOURCE_USERNAME=myuser
            - SPRING_DATASOURCE_PASSWORD=mypassword
            - SPRING_JPA_HIBERNATE_DDL_AUTO=update
          depends_on:
            db:
              condition: service_healthy
          networks:
            - my-app-network
      
        frontend:
          build:
            context: ./frontend # 脚本会将代码克隆到 'frontend', Dockerfile 和 nginx.conf 也会被复制到这里
            dockerfile: Dockerfile
          container_name: my-react-app
          ports:
            - "80:80"
          depends_on:
            - backend
          networks:
            - my-app-network
      
        db:
          image: mysql:8.0
          container_name: my-mysql-db
          restart: unless-stopped
          environment:
            MYSQL_DATABASE: mydatabase
            MYSQL_USER: myuser
            MYSQL_PASSWORD: mypassword
            MYSQL_ROOT_PASSWORD: rootpassword # 请使用强密码
          volumes:
            - mysql_data_volume:/var/lib/mysql
            - ./db_init/init.sql:/docker-entrypoint-initdb.d/init.sql # 脚本会尝试创建这个文件
          healthcheck:
            test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u$${MYSQL_USER}", "-p$${MYSQL_PASSWORD}"]
            interval: 10s
            timeout: 5s
            retries: 5
            start_period: 30s
          networks:
            - my-app-network
      
      networks:
        my-app-network:
          driver: bridge
      
      volumes:
        mysql_data_volume:
      

步骤 2: 部署脚本 (setup_and_deploy_local_files.sh)

将以下内容保存为一个名为 setup_and_deploy_local_files.sh 的文件:

Bash

#!/bin/bash

# --- 配置项 ---
# !!! 请修改以下 GitHub 仓库 URL 为你自己的项目 URL !!!
BACKEND_REPO_URL="https://github.com/YOUR_USERNAME/YOUR_BACKEND_SPRINGBOOT_REPO.git"
FRONTEND_REPO_URL="https://github.com/YOUR_USERNAME/YOUR_FRONTEND_REACT_REPO.git"

# !!! 请修改以下路径为你本地存放 Dockerfile 和 docker-compose.yml 模板文件的实际路径 !!!
LOCAL_CONFIG_BASE_PATH="${HOME}/my_docker_configs" # 示例路径: 用户家目录下的 my_docker_configs
DOCKERFILE_BACKEND_SOURCE="${LOCAL_CONFIG_BASE_PATH}/Dockerfile.backend"
DOCKERFILE_FRONTEND_SOURCE="${LOCAL_CONFIG_BASE_PATH}/Dockerfile.frontend"
NGINX_CONF_SOURCE="${LOCAL_CONFIG_BASE_PATH}/nginx.conf"
DOCKER_COMPOSE_YML_SOURCE="${LOCAL_CONFIG_BASE_PATH}/docker-compose.yml.template"

# 项目目录名称
MAIN_PROJECT_DIR="my_fullstack_app_from_local_configs" # 最终部署的项目会在这里创建
BACKEND_CODE_DIR="backend"  # 代码会克隆到 MAIN_PROJECT_DIR/backend
FRONTEND_CODE_DIR="frontend" # 代码会克隆到 MAIN_PROJECT_DIR/frontend
DB_INIT_DIR="db_init"

# --- 脚本检查 ---
function check_file_exists() {
    if [ ! -f "$1" ]; then
        echo "❌ 错误: 必需的配置文件 '$1' 未找到。"
        echo "请确保已按照说明准备好所有本地配置文件,并正确设置脚本中的路径。"
        exit 1
    fi
}

check_file_exists "${DOCKERFILE_BACKEND_SOURCE}"
check_file_exists "${DOCKERFILE_FRONTEND_SOURCE}"
check_file_exists "${NGINX_CONF_SOURCE}"
check_file_exists "${DOCKER_COMPOSE_YML_SOURCE}"

# --- 脚本开始 ---
echo "🚀 开始使用本地配置文件部署全栈项目..."

# 1. 创建主项目目录
echo "创建主项目目录: ${MAIN_PROJECT_DIR}"
mkdir -p "${MAIN_PROJECT_DIR}"
cd "${MAIN_PROJECT_DIR}" || exit # 进入主项目目录,后续操作都在此目录下进行

# 2. 清理并克隆后端仓库
echo "🔄 清理并克隆后端仓库到 ./${BACKEND_CODE_DIR}/ ..."
if [ -d "${BACKEND_CODE_DIR}" ]; then
    echo "删除已存在的后端代码目录: ${BACKEND_CODE_DIR}"
    rm -rf "${BACKEND_CODE_DIR}"
fi
mkdir -p "${BACKEND_CODE_DIR}"
git clone "${BACKEND_REPO_URL}" "${BACKEND_CODE_DIR}"
if [ $? -ne 0 ]; then
    echo "❌ 克隆后端仓库失败!请检查 URL 或网络连接。"
    exit 1
fi
echo "✅ 后端仓库克隆完成。"

# 3. 清理并克隆前端仓库
echo "🔄 清理并克隆前端仓库到 ./${FRONTEND_CODE_DIR}/ ..."
if [ -d "${FRONTEND_CODE_DIR}" ]; then
    echo "删除已存在的前端代码目录: ${FRONTEND_CODE_DIR}"
    rm -rf "${FRONTEND_CODE_DIR}"
fi
mkdir -p "${FRONTEND_CODE_DIR}"
git clone "${FRONTEND_REPO_URL}" "${FRONTEND_CODE_DIR}"
if [ $? -ne 0 ]; then
    echo "❌ 克隆前端仓库失败!请检查 URL 或网络连接。"
    exit 1
fi
echo "✅ 前端仓库克隆完成。"

# 4. 复制本地 Dockerfile 和配置文件到相应位置
echo "📝 复制本地配置文件..."
cp "${DOCKERFILE_BACKEND_SOURCE}" "./${BACKEND_CODE_DIR}/Dockerfile"
echo "  > 后端 Dockerfile 已复制到 ./${BACKEND_CODE_DIR}/Dockerfile"

cp "${DOCKERFILE_FRONTEND_SOURCE}" "./${FRONTEND_CODE_DIR}/Dockerfile"
echo "  > 前端 Dockerfile 已复制到 ./${FRONTEND_CODE_DIR}/Dockerfile"

cp "${NGINX_CONF_SOURCE}" "./${FRONTEND_CODE_DIR}/nginx.conf"
echo "  > Nginx 配置文件已复制到 ./${FRONTEND_CODE_DIR}/nginx.conf"

cp "${DOCKER_COMPOSE_YML_SOURCE}" "./docker-compose.yml"
echo "  > Docker Compose 文件已复制到 ./docker-compose.yml"
echo "✅ 本地配置文件复制完毕。"

# 5. 创建数据库初始化目录并尝试复制 db.sql
echo "📝 创建数据库初始化目录 (./${DB_INIT_DIR}) 并尝试复制 db.sql..."
mkdir -p "${DB_INIT_DIR}"
DB_SQL_SOURCE_PATH="./${BACKEND_CODE_DIR}/src/main/resources/db.sql" # 假设的 db.sql 路径
DB_SQL_DEST_PATH="./${DB_INIT_DIR}/init.sql"

if [ -f "${DB_SQL_SOURCE_PATH}" ]; then
    cp "${DB_SQL_SOURCE_PATH}" "${DB_SQL_DEST_PATH}"
    echo "✅ db.sql 已从 ${DB_SQL_SOURCE_PATH} 复制到 ${DB_SQL_DEST_PATH}"
else
    echo "⚠️ 未在 ${DB_SQL_SOURCE_PATH} 找到 db.sql。"
    echo "👉 请手动将你的数据库初始化脚本命名为 init.sql 并放置在 ${MAIN_PROJECT_DIR}/${DB_INIT_DIR}/ 目录下。"
    echo "   (如果不需要数据库初始化脚本,可以忽略此消息)"
fi

# 6. 构建并启动 Docker Compose 服务
echo "🐳 构建并启动 Docker 服务 (docker-compose up -d --build)..."
docker-compose up -d --build

if [ $? -eq 0 ]; then
    echo "🎉 项目部署成功!"
    echo "前端应用应该可以通过 http://localhost 访问 (如果80端口未被占用)"
    echo "后端应用应该可以通过 http://localhost:8080 访问 (如果8080端口未被占用)"
    echo "MySQL 数据库正在运行。"
    echo "使用 'docker-compose logs -f' 查看日志。"
    echo "使用 'docker-compose down' 停止服务。"
else
    echo "❌ Docker Compose 启动失败。请查看上面的错误日志。"
fi

echo "🚀 部署脚本执行完毕。"

步骤 3: 如何使用脚本

  1. 准备文件: 确保你已经按照 步骤 1 创建并保存了 Dockerfile.backend, Dockerfile.frontend, nginx.conf, 和 docker-compose.yml.template 在你本地的某个目录下 (例如 ~/my_docker_configs/)。
  2. 保存脚本: 将 步骤 2 中的脚本代码复制并粘贴到一个新文件中,例如 setup_and_deploy_local_files.sh
  3. 修改脚本配置:
    • 打开 setup_and_deploy_local_files.sh 文件。
    • 必须修改:
      • BACKEND_REPO_URLFRONTEND_REPO_URL 为你的 GitHub 仓库地址。
      • LOCAL_CONFIG_BASE_PATH 为你在步骤 1 中存放配置文件的实际路径。
    • (可选)你可以修改 MAIN_PROJECT_DIR 来更改最终生成的项目目录名称。
  4. 授予执行权限: 在终端中,进入脚本所在的目录,然后运行: Bash

    chmod +x setup_and_deploy_local_files.sh
    
  5. 运行脚本: Bash

    ./setup_and_deploy_local_files.sh
    

脚本执行流程

  1. 检查本地文件: 脚本会先检查你在 LOCAL_CONFIG_BASE_PATH 中指定的 Dockerfile、nginx.conf 和 docker-compose.yml 模板文件是否存在,如果不存在则会报错退出。
  2. 创建主目录: 创建 MAIN_PROJECT_DIR 并进入该目录。
  3. 克隆代码: 清理可能已存在的 backendfrontend 子目录,然后从 GitHub 克隆你的项目代码到这两个目录中。
  4. 复制配置文件:
    • LOCAL_DOCKERFILE_BACKEND_SOURCE 复制到 MAIN_PROJECT_DIR/backend/Dockerfile
    • LOCAL_DOCKERFILE_FRONTEND_SOURCE 复制到 MAIN_PROJECT_DIR/frontend/Dockerfile
    • LOCAL_NGINX_CONF_SOURCE 复制到 MAIN_PROJECT_DIR/frontend/nginx.conf
    • LOCAL_DOCKER_COMPOSE_YML_SOURCE (你的模板) 复制到 MAIN_PROJECT_DIR/docker-compose.yml
  5. 处理 db.sql: 与之前的脚本一样,尝试从克隆的后端项目中找到 db.sql 并复制到 db_init/init.sql
  6. 启动服务: 使用复制过来的 docker-compose.yml 文件执行 docker-compose up -d --build 来构建镜像并启动所有服务。

这样,你的部署脚本会更专注于流程的编排,而具体的 Docker 配置则由你维护在独立的本地文件中,方便阅读和修改。

好的,这个脚本将帮助你自动化以下操作:

  1. 创建一个主项目目录。
  2. 清空并克隆你的 Spring Boot 后端和 React 前端 GitHub 仓库到各自的子目录中。
  3. 在克隆下来的代码目录中生成对应的 Dockerfile 和前端的 nginx.conf
  4. 创建 db_init 目录,并尝试从后端项目中复制 db.sql(如果找到)。
  5. 生成 docker-compose.yml 文件。
  6. 最后,使用 docker-compose up -d --build 一键构建并启动所有服务。

重要前提:

  • 你需要在你的机器上安装好 DockerDocker Compose
  • 这个脚本使用 git 命令,所以也需要安装 Git
  • 脚本会删除已存在的 backendfrontend 目录(在主项目录下)以确保它们是空的,然后再克隆。请谨慎操作,确保这些目录中没有你需要保留的未提交更改。

脚本内容 (setup_and_deploy.sh)

请将以下内容保存为一个名为 setup_and_deploy.sh 的文件:

#!/bin/bash

# --- 配置项 ---
# !!! 请修改以下 GitHub 仓库 URL 为你自己的项目 URL !!!
BACKEND_REPO_URL="https://github.com/YOUR_USERNAME/YOUR_BACKEND_SPRINGBOOT_REPO.git"
FRONTEND_REPO_URL="https://github.com/YOUR_USERNAME/YOUR_FRONTEND_REACT_REPO.git"

# 项目目录名称
MAIN_PROJECT_DIR="my_fullstack_app_deployed"
BACKEND_DIR="backend"
FRONTEND_DIR="frontend"
DB_INIT_DIR="db_init"

# MySQL 配置 (可以根据需要修改 docker-compose.yml 中的环境变量)
MYSQL_DATABASE="mydatabase"
MYSQL_USER="myuser"
MYSQL_PASSWORD="mypassword" # !!! 生产环境请使用更强壮的密码,并考虑使用 .env 文件 !!!
MYSQL_ROOT_PASSWORD="rootpassword" # !!! 生产环境请使用更强壮的密码 !!!

# --- 脚本开始 ---
echo "🚀 开始部署全栈项目..."

# 1. 创建主项目目录
echo "创建主项目目录: ${MAIN_PROJECT_DIR}"
mkdir -p "${MAIN_PROJECT_DIR}"
cd "${MAIN_PROJECT_DIR}" || exit

# 2. 清理并克隆后端仓库
echo "🔄 清理并克隆后端仓库..."
if [ -d "${BACKEND_DIR}" ]; then
    echo "删除已存在的后端目录: ${BACKEND_DIR}"
    rm -rf "${BACKEND_DIR}"
fi
mkdir -p "${BACKEND_DIR}"
git clone "${BACKEND_REPO_URL}" "${BACKEND_DIR}"
if [ $? -ne 0 ]; then
    echo "❌ 克隆后端仓库失败!请检查 URL 或网络连接。"
    exit 1
fi
echo "✅ 后端仓库克隆完成到 ${BACKEND_DIR}/"

# 3. 清理并克隆前端仓库
echo "🔄 清理并克隆前端仓库..."
if [ -d "${FRONTEND_DIR}" ]; then
    echo "删除已存在的前端目录: ${FRONTEND_DIR}"
    rm -rf "${FRONTEND_DIR}"
fi
mkdir -p "${FRONTEND_DIR}"
git clone "${FRONTEND_REPO_URL}" "${FRONTEND_DIR}"
if [ $? -ne 0 ]; then
    echo "❌ 克隆前端仓库失败!请检查 URL 或网络连接。"
    exit 1
fi
echo "✅ 前端仓库克隆完成到 ${FRONTEND_DIR}/"

# 4. 生成后端 Dockerfile
# Dockerfile 将存放在克隆下来的后端代码目录的根目录下
echo "📝 生成后端 Dockerfile (${BACKEND_DIR}/Dockerfile)..."
cat << EOF > "${BACKEND_DIR}/Dockerfile"
# 使用一个包含 JDK 的基础镜像 (例如 OpenJDK 17)
FROM openjdk:17-jdk-slim

# 设置工作目录
WORKDIR /app

# 复制 Maven Wrapper 相关文件 (如果项目使用 Maven Wrapper)
COPY .mvn/ .mvn
COPY mvnw .
COPY pom.xml .

# 下载依赖 (利用 Docker 缓存机制)
# 如果 pom.xml 不在仓库根目录,或者 mvnw 不可用,需要调整
RUN ./mvnw dependency:go-offline -B || { echo "Maven go-offline failed. Check mvnw and pom.xml presence."; exit 1; }


# 复制源代码
COPY src ./src

# 打包应用
RUN ./mvnw package -DskipTests

# ---- 第二阶段:运行阶段 ----
# 使用一个更小的 JRE 镜像来运行应用
FROM openjdk:17-jre-slim

WORKDIR /app

# 从构建阶段复制 JAR 文件 (通常在 target/*.jar)
COPY --from=0 /app/target/*.jar app.jar

# 暴露 Spring Boot 应用的端口 (默认为 8080)
EXPOSE 8080

# 运行应用
ENTRYPOINT ["java", "-jar", "app.jar"]
EOF
echo "✅ 后端 Dockerfile 生成完毕。"

# 5. 生成前端 Dockerfile
# Dockerfile 将存放在克隆下来的前端代码目录的根目录下
echo "📝 生成前端 Dockerfile (${FRONTEND_DIR}/Dockerfile)..."
cat << EOF > "${FRONTEND_DIR}/Dockerfile"
# ---- 构建阶段 ----
# 使用 Node.js 镜像 (例如 Node 18 Alpine)
FROM node:18-alpine as builder

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json (或 yarn.lock)
COPY package*.json ./
# 如果使用 yarn:
# COPY yarn.lock ./

# 安装依赖
RUN npm install
# 如果使用 yarn:
# RUN yarn install

# 复制所有项目文件
COPY . .

# 构建应用 (通常是 npm run build)
RUN npm run build

# ---- 运行阶段 ----
FROM nginx:stable-alpine

# 复制 Nginx 配置文件 (nginx.conf 需要和 Dockerfile 在同一构建上下文)
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 从构建阶段复制构建好的静态文件到 Nginx 的 www 目录
# Vite 默认输出到 dist 目录
COPY --from=builder /app/dist /usr/share/nginx/html

# 暴露 Nginx 端口 (默认为 80)
EXPOSE 80

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
EOF
echo "✅ 前端 Dockerfile 生成完毕。"

# 6. 生成前端 Nginx 配置文件
# nginx.conf 将存放在克隆下来的前端代码目录的根目录下
echo "📝 生成前端 Nginx 配置文件 (${FRONTEND_DIR}/nginx.conf)..."
cat << EOF > "${FRONTEND_DIR}/nginx.conf"
server {
    listen 80;
    server_name localhost;

    root /usr/share/nginx/html;
    index index.html index.htm;

    # 处理 React Router 的路由 (重要)
    location / {
        try_files \$uri \$uri/ /index.html;
    }

    # 可选: 如果你想通过 Nginx 代理后端 API 请求
    # location /api/ {
    #     proxy_pass http://backend:8080/; # "backend" 是 docker-compose.yml 中的服务名
    #     proxy_set_header Host \$host;
    #     proxy_set_header X-Real-IP \$remote_addr;
    #     proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    #     proxy_set_header X-Forwarded-Proto \$scheme;
    # }
}
EOF
echo "✅ 前端 Nginx 配置文件生成完毕。"

# 7. 创建数据库初始化目录并尝试复制 db.sql
echo "📝 创建数据库初始化目录 (${DB_INIT_DIR})..."
mkdir -p "${DB_INIT_DIR}"
DB_SQL_SOURCE_PATH="${BACKEND_DIR}/src/main/resources/db.sql" # 假设的 db.sql 路径
DB_SQL_DEST_PATH="${DB_INIT_DIR}/init.sql"

if [ -f "${DB_SQL_SOURCE_PATH}" ]; then
    cp "${DB_SQL_SOURCE_PATH}" "${DB_SQL_DEST_PATH}"
    echo "✅ db.sql 已从 ${DB_SQL_SOURCE_PATH} 复制到 ${DB_SQL_DEST_PATH}"
else
    echo "⚠️ 未在 ${DB_SQL_SOURCE_PATH} 找到 db.sql。"
    echo "👉 请手动将你的数据库初始化脚本 (例如 db.sql) 命名为 init.sql 并放置在 ${MAIN_PROJECT_DIR}/${DB_INIT_DIR}/ 目录下。"
    echo "   MySQL 容器启动时会自动执行 /docker-entrypoint-initdb.d/init.sql"
fi

# 8. 生成 docker-compose.yml 文件
echo "📝 生成 docker-compose.yml 文件..."
cat << EOF > "docker-compose.yml"
version: '3.8'

services:
  backend:
    build:
      context: ./${BACKEND_DIR} # 构建上下文指向克隆的后端代码目录
      dockerfile: Dockerfile    # Dockerfile 在该目录的根下
    container_name: my-springboot-app
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/${MYSQL_DATABASE}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
      - SPRING_DATASOURCE_USERNAME=${MYSQL_USER}
      - SPRING_DATASource_PASSWORD=${MYSQL_PASSWORD}
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update # 或 validate, none (如果完全依赖 db.sql)
    depends_on:
      db:
        condition: service_healthy
    networks:
      - my-app-network

  frontend:
    build:
      context: ./${FRONTEND_DIR} # 构建上下文指向克隆的前端代码目录
      dockerfile: Dockerfile     # Dockerfile 在该目录的根下
    container_name: my-react-app
    ports:
      - "80:80"
    depends_on:
      - backend
    networks:
      - my-app-network

  db:
    image: mysql:8.0
    container_name: my-mysql-db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes:
      - mysql_data_volume:/var/lib/mysql
      - ./${DB_INIT_DIR}/init.sql:/docker-entrypoint-initdb.d/init.sql # 挂载初始化脚本
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u\${MYSQL_USER}", "-p\${MYSQL_PASSWORD}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - my-app-network

networks:
  my-app-network:
    driver: bridge

volumes:
  mysql_data_volume: # 数据卷名称
EOF
echo "✅ docker-compose.yml 生成完毕。"

# 9. (可选,如果需要 .env 文件管理敏感信息)
# echo "📝 (可选) 生成 .env 文件..."
# cat << ENV_EOF > ".env"
# MYSQL_DATABASE=${MYSQL_DATABASE}
# MYSQL_USER=${MYSQL_USER}
# MYSQL_PASSWORD=${MYSQL_PASSWORD}
# MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
# SPRING_DATASOURCE_USERNAME=${MYSQL_USER}
# SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
# ENV_EOF
# echo "✅ .env 文件已生成。你可以在 docker-compose.yml 中使用 \${VARIABLE_NAME} 引用这些变量。"
# echo "   例如: MYSQL_USER=\${MYSQL_USER_ENV} (并在 .env 中定义 MYSQL_USER_ENV)"
# echo "   注意:如果使用 .env 文件,请确保 .env 文件不被提交到 Git 仓库 (添加到 .gitignore)。"


# 10. 构建并启动 Docker Compose 服务
echo "🐳 构建并启动 Docker 服务 (docker-compose up -d --build)..."
docker-compose up -d --build

if [ $? -eq 0 ]; then
    echo "🎉 项目部署成功!"
    echo "前端应用应该可以通过 http://localhost 访问 (如果80端口未被占用)"
    echo "后端应用应该可以通过 http://localhost:8080 访问 (如果8080端口未被占用)"
    echo "MySQL 数据库正在运行,但通常不直接从外部访问。"
    echo "使用 'docker-compose logs -f' 查看日志。"
    echo "使用 'docker-compose down' 停止服务。"
else
    echo "❌ Docker Compose 启动失败。请查看上面的错误日志。"
fi

echo "🚀 部署脚本执行完毕。"

如何使用脚本

  1. 保存脚本: 将上面的代码复制并粘贴到一个新文件中,例如 setup_and_deploy.sh
  2. 修改配置:
    • 最重要: 打开 setup_and_deploy.sh 文件,将 BACKEND_REPO_URLFRONTEND_REPO_URL 的值修改为你自己后端和前端项目的实际 GitHub 仓库 URL。
    • (可选)你可以修改脚本顶部的 MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, MYSQL_ROOT_PASSWORD 等变量。强烈建议为生产环境或任何共享环境使用更安全的密码,并考虑使用 .env 文件来管理这些敏感信息,而不是直接写在脚本里。 (脚本中已注释掉生成 .env 的部分,你可以按需启用)。
  3. 授予执行权限: 在终端中,进入脚本所在的目录,然后运行: Bash

    chmod +x setup_and_deploy.sh
    
  4. 运行脚本: Bash

    ./setup_and_deploy.sh
    

脚本执行流程详解

  1. 创建主目录: 脚本首先创建一个名为 my_fullstack_app_deployed (或你自定义的 MAIN_PROJECT_DIR) 的主目录,并进入该目录。之后的所有操作都在这个主目录内进行。
  2. 克隆代码:
    • 它会检查是否存在 backendfrontend 子目录。如果存在,会先删除它们,以确保是从一个干净的状态开始克隆最新的代码。
    • 然后使用 git clone 从你提供的 URL 克隆后端和前端项目的代码到各自的 backendfrontend 目录中。
  3. 生成 Dockerfile:
    • 后端: 在 backend 目录(即克隆下来的后端代码根目录)下生成一个 Dockerfile。这个 Dockerfile 用于构建 Spring Boot 应用。
    • 前端: 在 frontend 目录(即克隆下来的前端代码根目录)下生成一个 Dockerfile。这个 Dockerfile 用于构建 React 应用并准备 Nginx。
  4. 生成 Nginx 配置: 在 frontend 目录下生成 nginx.conf 文件,供前端 Dockerfile 中的 Nginx 使用。
  5. 处理 db.sql:
    • 创建一个 db_init 目录。
    • 脚本会尝试从后端克隆下来的代码的 src/main/resources/db.sql 路径复制 db.sql 文件到 db_init/init.sql
    • 如果找不到 db.sql (例如路径不同或文件不存在),脚本会提示你手动将数据库初始化脚本命名为 init.sql 并放到 db_init 目录下。MySQL 容器启动时会自动执行这个目录下的 .sql 文件。
  6. 生成 docker-compose.yml: 在主项目录 (my_fullstack_app_deployed) 下生成 docker-compose.yml 文件。这个文件定义了 backend, frontend, 和 db 三个服务。
    • backendfrontend 服务的 build.context 分别指向 ./backend./frontend 目录,这样 Docker Compose 就会在这些目录中查找 Dockerfile 并构建镜像。
    • MySQL 服务会挂载 db_init/init.sql 来初始化数据库。
  7. 一键部署: 最后,脚本执行 docker-compose up -d --build
    • --build: 强制 Docker Compose 重新构建镜像(因为代码和 Dockerfile 都是新生成的)。
    • -d: 在后台分离模式下运行容器。
  8. 输出结果: 脚本会输出部署是否成功,以及如何访问应用和管理服务。

现在,你只需要配置好脚本顶部的仓库 URL,然后运行这个脚本,就可以实现从代码克隆到服务部署的全过程了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2386015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Devicenet主转Profinet网关助力改造焊接机器人系统智能升级

某汽车零部件焊接车间原有6台焊接机器人&#xff08;采用Devicenet协议&#xff09;需与新增的西门子S7-1200 PLC&#xff08;Profinet协议&#xff09;组网。若更换所有机器人控制器或上位机系统&#xff0c;成本过高且停产周期长。 《解决方案》 工程师选择稳联技术转换网关…

《STL--list的使用及其底层实现》

引言&#xff1a; 上次我们学习了容器vector的使用及其底层实现&#xff0c;今天我们再来学习一个容器list&#xff0c; 这里的list可以参考我们之前实现的单链表&#xff0c;但是这里的list是双向循环带头链表&#xff0c;下面我们就开始list的学习了。 一&#xff1a;list的…

python的pip怎么配置的国内镜像

以下是配置pip国内镜像源的详细方法&#xff1a; 常用国内镜像源列表 清华大学&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple阿里云&#xff1a;https://mirrors.aliyun.com/pypi/simple中科大&#xff1a;https://pypi.mirrors.ustc.edu.cn/simple华为云&#xff1…

PCB 通孔是电容性的,但不一定是电容器

哼&#xff1f;……这是什么意思&#xff1f;…… 多年来&#xff0c;流行的观点是 PCB 通孔本质上是电容性的&#xff0c;因此可以用集总电容器进行建模。虽然当信号的上升时间大于或等于过孔不连续性延迟的 3 倍时&#xff0c;这可能是正确的&#xff0c;但我将向您展示为什…

公有云AWS基础架构与核心服务:从概念到实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 &#xff08;初学者技术专栏&#xff09; 一、基础概念 定义&#xff1a;AWS&#xff08;Amazon Web Services&#xff09;是亚马逊提供的云计算服务&a…

Python60日基础学习打卡D35

import torch import torch.nn as nn import torch.optim as optim from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler import time import matplotlib.pyplot as plt# 设置GPU设…

目标检测 RT-DETR(2023)详细解读

文章目录 主干网络&#xff1a;Encoder&#xff1a;不确定性最小Query选择Decoder网络&#xff1a; 将DETR扩展到实时场景&#xff0c;提高了模型的检测速度。网络架构分为三部分组成&#xff1a;主干网络、混合编码器、带有辅助预测头的变换器编码器。具体来说&#xff0c;先利…

微信小程序 隐私协议弹窗授权

开发微信小程序的第一步往往是隐私协议授权&#xff0c;尤其是在涉及用户隐私数据时&#xff0c;必须确保用户明确知晓并同意相关隐私政策。我们才可以开发后续的小程序内容。友友们在按照文档开发时可能会遇到一些问题&#xff0c;我把所有的授权方法和可能遇到的问题都整理出…

金众诚业财一体化解决方案如何提升项目盈利能力?

在工程项目管理领域&#xff0c;复杂的全生命周期管理、成本控制的精准性以及业务与财务的高效协同&#xff0c;是决定项目盈利能力的核心要素。随着数字化转型的深入&#xff0c;传统的项目管理方式已难以满足企业对效率、透明度和盈利能力的需求。基于金蝶云星空平台打造的金…

LabVIEW中EtherCAT从站拓扑离线创建及信息查询

该 VI 主要用于演示如何离线创建 EtherCAT 从站拓扑结构&#xff0c;并查询从站相关信息。EtherCAT&#xff08;以太网控制自动化技术&#xff09;是基于以太网的实时工业通信协议&#xff0c;凭借其高速、高效的特性在自动化领域广泛应用。与其他常见工业通讯协议相比&#xf…

Flutter 3.32 新特性

2天前&#xff0c;Flutter发布了最新版本3.32&#xff0c;我们来一起看下29到32有哪些变化。 简介 欢迎来到Flutter 3.32&#xff01;此版本包含了旨在加速开发和增强应用程序的功能。准备好在网络上进行热加载&#xff0c;令人惊叹的原生保真Cupertino&#xff0c;以及与Fir…

windows和mac安装虚拟机-详细教程

简介 虚拟机&#xff1a;Virtual Machine&#xff0c;虚拟化技术的一种&#xff0c;通过软件模拟的、具有完整硬件功能的、运行在一个完全隔离的环境中的计算机。 在学习linux系统的时候&#xff0c;需要安装虚拟机&#xff0c;在虚拟机上来运行操作系统&#xff0c;因为我使…

【C++】vector容器实现

目录 一、vector的成员变量 二、vector手动实现 &#xff08;1&#xff09;构造 &#xff08;2&#xff09;析构 &#xff08;3&#xff09;尾插 &#xff08;4&#xff09;扩容 &#xff08;5&#xff09;[ ]运算符重载 5.1 迭代器的实现&#xff1a; &#xff08;6&…

使用Docker Compose部署Dify

目录 1. 克隆项目代码2. 准备配置文件3. 配置环境变量4. 启动服务5. 验证部署6. 访问服务注意事项 1. 克隆项目代码 首先&#xff0c;克隆Dify项目的1.4.0版本&#xff1a; git clone https://github.com/langgenius/dify.git --branch 1.4.02. 准备配置文件 进入docker目录…

杰发科技AC7840——CSE硬件加密模块使用(1)

1. 简介 2. 功能概述 3. 简单的代码分析 测试第二个代码例程 初始化随机数 这里的CSE_CMD_RND在FuncID中体现了 CSE_SECRET_KEY在17个用户KEY中体现 最后的读取RNG值&#xff0c;可以看出计算结果在PRAM中。 总的来看 和示例说明一样&#xff0c;CSE 初次使用&#xff0c;添加…

前端地图数据格式标准及应用

前端地图数据格式标准及应用 坐标系EPSGgeojson标准格式基于OGC标准的地图服务shapefile文件3D模型数据常见地图框架 坐标系EPSG EPSG&#xff08;European Petroleum Survey Group&#xff09;是一个国际组织&#xff0c;负责维护和管理地理坐标系统和投影系统的标准化编码 E…

threejs几何体BufferGeometry顶点

1. 几何体顶点位置数据和点模型 本章节主要目的是给大家讲解几何体geometry的顶点概念,相对偏底层一些&#xff0c;不过掌握以后&#xff0c;你更容易深入理解Threejs的几何体和模型对象。 缓冲类型几何体BufferGeometry threejs的长方体BoxGeometry、球体SphereGeometry等几…

向量数据库选型实战指南:Milvus架构深度解析与技术对比

导读&#xff1a;随着大语言模型和AI应用的快速普及&#xff0c;传统数据库在处理高维向量数据时面临的性能瓶颈日益凸显。当文档经过嵌入模型处理生成768到1536维的向量后&#xff0c;传统B-Tree索引的检索效率会出现显著下降&#xff0c;而现代应用对毫秒级响应的严苛要求使得…

java方法重写学习笔记

方法重写介绍 子类和父类有两个返回值&#xff0c;参数&#xff0c;名称都一样的方法&#xff0c; 子类的方法会覆盖父类的方法。 调用 public class Overide01 {public static void main(String[] args) {Dog dog new Dog();dog.cry();} }Animal类 public class Animal {…

TensorBoard安装与基本操作指南(PyTorch)

文章目录 什么是TensorBoard&#xff1f;TensorBoardX与TensorBoard的依赖关系易混关系辨析Pytorch安装TensorBoard并验证1. TensorBoard安装和访问2. TensorBoard主要界面介绍实用技巧 什么是TensorBoard&#xff1f; TensorBoard是TensorFlow生态系统中的一款强大的可视化工…