好的,我明白了。你希望脚本变得更简洁,主要负责:
- 代码克隆:从 GitHub 克隆你的后端和前端项目,并在克隆前确保目标目录为空。
- 文件复制:将你预先准备好的
Dockerfile
(后端和前端各一个)、前端的nginx.conf
以及docker-compose.yml
文件从你本地的指定位置复制到新创建的项目目录结构中。 - 数据库脚本处理:尝试从克隆的后端项目中复制
db.sql
。 - 一键部署:使用复制过来的
docker-compose.yml
文件启动服务。
这样,Dockerfile
和 docker-compose.yml
的具体内容就由你维护在本地文件中,脚本只负责“组装”和执行。
步骤 1: 准备你的本地配置文件
在运行脚本之前,你需要在你的电脑上准备好以下文件。假设你将这些文件统一存放在一个地方,例如 ~/my_docker_configs/
目录下 (你可以选择任何你方便的路径,并在脚本中配置)。
-
后端 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"]
- 这个
-
前端 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;"]
- 这个
-
前端 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; } }
-
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 创建并保存了
Dockerfile.backend
,Dockerfile.frontend
,nginx.conf
, 和docker-compose.yml.template
在你本地的某个目录下 (例如~/my_docker_configs/
)。 - 保存脚本: 将 步骤 2 中的脚本代码复制并粘贴到一个新文件中,例如
setup_and_deploy_local_files.sh
。 - 修改脚本配置:
- 打开
setup_and_deploy_local_files.sh
文件。 - 必须修改:
BACKEND_REPO_URL
和FRONTEND_REPO_URL
为你的 GitHub 仓库地址。LOCAL_CONFIG_BASE_PATH
为你在步骤 1 中存放配置文件的实际路径。
- (可选)你可以修改
MAIN_PROJECT_DIR
来更改最终生成的项目目录名称。
- 打开
- 授予执行权限: 在终端中,进入脚本所在的目录,然后运行: Bash
chmod +x setup_and_deploy_local_files.sh
- 运行脚本: Bash
./setup_and_deploy_local_files.sh
脚本执行流程
- 检查本地文件: 脚本会先检查你在
LOCAL_CONFIG_BASE_PATH
中指定的 Dockerfile、nginx.conf 和 docker-compose.yml 模板文件是否存在,如果不存在则会报错退出。 - 创建主目录: 创建
MAIN_PROJECT_DIR
并进入该目录。 - 克隆代码: 清理可能已存在的
backend
和frontend
子目录,然后从 GitHub 克隆你的项目代码到这两个目录中。 - 复制配置文件:
- 将
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
。
- 将
- 处理
db.sql
: 与之前的脚本一样,尝试从克隆的后端项目中找到db.sql
并复制到db_init/init.sql
。 - 启动服务: 使用复制过来的
docker-compose.yml
文件执行docker-compose up -d --build
来构建镜像并启动所有服务。
这样,你的部署脚本会更专注于流程的编排,而具体的 Docker 配置则由你维护在独立的本地文件中,方便阅读和修改。
好的,这个脚本将帮助你自动化以下操作:
- 创建一个主项目目录。
- 清空并克隆你的 Spring Boot 后端和 React 前端 GitHub 仓库到各自的子目录中。
- 在克隆下来的代码目录中生成对应的
Dockerfile
和前端的nginx.conf
。 - 创建
db_init
目录,并尝试从后端项目中复制db.sql
(如果找到)。 - 生成
docker-compose.yml
文件。 - 最后,使用
docker-compose up -d --build
一键构建并启动所有服务。
重要前提:
- 你需要在你的机器上安装好 Docker 和 Docker Compose。
- 这个脚本使用
git
命令,所以也需要安装 Git。 - 脚本会删除已存在的
backend
和frontend
目录(在主项目录下)以确保它们是空的,然后再克隆。请谨慎操作,确保这些目录中没有你需要保留的未提交更改。
脚本内容 (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 "🚀 部署脚本执行完毕。"
如何使用脚本
- 保存脚本: 将上面的代码复制并粘贴到一个新文件中,例如
setup_and_deploy.sh
。 - 修改配置:
- 最重要: 打开
setup_and_deploy.sh
文件,将BACKEND_REPO_URL
和FRONTEND_REPO_URL
的值修改为你自己后端和前端项目的实际 GitHub 仓库 URL。 - (可选)你可以修改脚本顶部的
MYSQL_DATABASE
,MYSQL_USER
,MYSQL_PASSWORD
,MYSQL_ROOT_PASSWORD
等变量。强烈建议为生产环境或任何共享环境使用更安全的密码,并考虑使用.env
文件来管理这些敏感信息,而不是直接写在脚本里。 (脚本中已注释掉生成.env
的部分,你可以按需启用)。
- 最重要: 打开
- 授予执行权限: 在终端中,进入脚本所在的目录,然后运行: Bash
chmod +x setup_and_deploy.sh
- 运行脚本: Bash
./setup_and_deploy.sh
脚本执行流程详解
- 创建主目录: 脚本首先创建一个名为
my_fullstack_app_deployed
(或你自定义的MAIN_PROJECT_DIR
) 的主目录,并进入该目录。之后的所有操作都在这个主目录内进行。 - 克隆代码:
- 它会检查是否存在
backend
和frontend
子目录。如果存在,会先删除它们,以确保是从一个干净的状态开始克隆最新的代码。 - 然后使用
git clone
从你提供的 URL 克隆后端和前端项目的代码到各自的backend
和frontend
目录中。
- 它会检查是否存在
- 生成 Dockerfile:
- 后端: 在
backend
目录(即克隆下来的后端代码根目录)下生成一个Dockerfile
。这个Dockerfile
用于构建 Spring Boot 应用。 - 前端: 在
frontend
目录(即克隆下来的前端代码根目录)下生成一个Dockerfile
。这个Dockerfile
用于构建 React 应用并准备 Nginx。
- 后端: 在
- 生成 Nginx 配置: 在
frontend
目录下生成nginx.conf
文件,供前端 Dockerfile 中的 Nginx 使用。 - 处理
db.sql
:- 创建一个
db_init
目录。 - 脚本会尝试从后端克隆下来的代码的
src/main/resources/db.sql
路径复制db.sql
文件到db_init/init.sql
。 - 如果找不到
db.sql
(例如路径不同或文件不存在),脚本会提示你手动将数据库初始化脚本命名为init.sql
并放到db_init
目录下。MySQL 容器启动时会自动执行这个目录下的.sql
文件。
- 创建一个
- 生成
docker-compose.yml
: 在主项目录 (my_fullstack_app_deployed
) 下生成docker-compose.yml
文件。这个文件定义了backend
,frontend
, 和db
三个服务。backend
和frontend
服务的build.context
分别指向./backend
和./frontend
目录,这样 Docker Compose 就会在这些目录中查找Dockerfile
并构建镜像。- MySQL 服务会挂载
db_init/init.sql
来初始化数据库。
- 一键部署: 最后,脚本执行
docker-compose up -d --build
。--build
: 强制 Docker Compose 重新构建镜像(因为代码和 Dockerfile 都是新生成的)。-d
: 在后台分离模式下运行容器。
- 输出结果: 脚本会输出部署是否成功,以及如何访问应用和管理服务。
现在,你只需要配置好脚本顶部的仓库 URL,然后运行这个脚本,就可以实现从代码克隆到服务部署的全过程了!