docker-compose一键部署Springboot+Vue前后端分离项目

发布于:2025-08-05 ⋅ 阅读:(15) ⋅ 点赞:(0)

1. 背景说明

  • 后端使用JDK8,前端为普通Vue项目
  • 前端访问后端接口,统一带了前缀/api

2. 项目配置

2.1 后端

yml文件里配置统一访问前缀/api
在这里插入图片描述

2.2 前端

API路径配置为相对路径:

在这里插入图片描述
说明:我这边前后端应用都是部署在同一台服务器上,所以用相对路径更灵活省事,因为在相对路径配置下,接口请求会基于当前前端页面的域名和端口拼接基础地址。

如果前后端应用需要分开部署在不同的服务器上,配置绝对路径就好了,如下:
在这里插入图片描述

3. 打包

前后端分别打包好,将后端的jar包前端的dist目录上传到服务器,我这边的目录结构如下,一个项目的前后端都放在一个文件夹下,用apiweb目录区分

└── sa-admin
    ├── api
    │   ├── Dockerfile
    │   └── sa-admin-prod-3.0.0.jar
    └── web
    │   ├── dist
    │   ├── Dockerfile
    │   ├── nginx.conf
    ├── deploy.sh
    ├── docker-compose.yml

4 编写 Dockerfile 与 docker-compose.yml

后端jar包前端dist的目录下分别创建一个Dockerfile文件

4.1 后端的Dockerfile

# 使用 OpenJDK 8 作为基础镜像
FROM openjdk:8-jdk

# VOLUME 指定了临时文件目录为/tmp。
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
VOLUME /tmp

#设置时区
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone

# 复制jar包到容器内(注意jar包名称与实际一致)
COPY sa-admin-prod-3.0.0.jar app.jar

# 暴露后端服务端口(根据实际项目端口修改)
EXPOSE 9090

# 容器启动时执行的命令
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-jar","/app.jar"]

4.2 前端的Dockerfile

FROM nginx

# 删除nginx默认配置、默认静态文件
RUN rm -rf /usr/share/nginx/html/*
# 删除禁用nginx默认配置(为避免冲突,使自定义的sa-admin-web-nginx.conf生效)
RUN mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak

# 复制自定义的配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 复制前端dist目录到nginx静态文件目录
COPY dist/ /usr/share/nginx/html/

# 暴露80端口(nginx默认端口)
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

4.3 前端的nginx配置文件

server {
        listen 80;
        server_name localhost;  # 可替换为实际域名

        # 前端静态文件目录(对应Dockerfile中复制的dist目录)
        root /usr/share/nginx/html;
        index index.html index.htm;

        # 支持前端路由(history模式),刷新页面不404
        location / {
        		try_files $uri $uri/ /index.html;
        }

        # 反向代理到后端服务(核心配置)
        # 假设前端请求后端的API路径以 /api 开头(需与前端代码一致)
        location /api/ {
            # 后端容器名+端口(docker内部可直接用服务名访问,无需映射到宿主机)
            proxy_pass http://sa-admin-api:9090/api/;  # 注意结尾的斜杠与后端一致
            
            # 代理相关的头信息(解决跨域和后端获取真实IP等问题)
            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;
        }

        # 跨域配置(如果需要更宽松的跨域规则)
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
        add_header Access-Control-Allow-Headers 'Origin, Content-Type, Authorization';
    }
    

这一行配置:proxy_pass http://sa-admin-api:9090/api/;
为什么地址写的是sa-admin-api,看下面的配置说明 (关键)

4.4 docker-compose.yml

回到apiweb的根目录下(项目目录/sa-admin),创建docker-compose.yml文件:

version: '3.8'  # 兼容主流Docker版本

services:
  # 后端服务
  sa-admin-api:
    build:
      context: ./api  # 后端Dockerfile所在目录
    image: sa-admin-api  # 镜像名
    container_name: sa-admin-api  # 容器名
    ports:
      - "9090:9090"  # 宿主机端口:容器端口(根据后端实际端口调整)
    restart: unless-stopped  # 异常退出时自动重启
    environment:
      - SPRING_PROFILES_ACTIVE=prod  # 指定环境配置
    networks:
      - sa-admin-network  # 加入自定义网络(前后端可通过服务名通信)
    volumes:
      - /docker/sa-admin/log:/home/smart-admin  # 使用命名卷

  # 前端服务
  sa-admin-web:
    build:
      context: ./web  # 前端Dockerfile所在目录
    image: sa-admin-web  # 镜像名
    container_name: sa-admin-web  # 容器名
    ports:
      - "9091:80"  # 宿主机80端口映射到容器80(可自定义宿主机端口)
    restart: unless-stopped
    networks:
      - sa-admin-network
    depends_on:
      - sa-admin-api  # 确保后端先启动
    volumes:
      - ./web/dist/:/usr/share/nginx/html/

# 自定义网络(避免端口冲突,支持服务名访问)
networks:
  sa-admin-network:
    driver: bridge

4.4.1 配置说明:

networks: 创建docker网络
网络连接不通的问题

在docker中,容器的网络不等于宿主机的网络。

比如:按正常思维,前后端部署在一台机器上,前端访问后端地址配置为http://localhost:9090是肯定可以访问到的,但在docker中不行。

因为docker容器内的localhost不等于宿主机的localhost,Docker 容器有独立的网络命名空间,容器内部的localhost(127.0.0.1)仅指向容器自身,而非宿主机或其他容器。

若前端 Nginx 配置中用localhost:后端端口代理后端服务(例如proxy_pass http://localhost:9090),Nginx 会尝试访问当前前端容器内部的 9090端口,但后端服务通常运行在另一个容器或宿主机上,因此会出现 “连接拒绝”。

解决方案

要解决这个问题,就需要将前后端容器处于同一网络下。分为两步:

  1. 创建自定义网络(上面前端nginx配置文件中的sa-admin-api),将前端、后端容器加入同一网络
  2. 修正 Nginx 代理配置,用后端容器名作为代理目标(同一网络内可直接访问):http://sa-admin-api:9090/api/,http后面直接接上后端的容器名

4.5 一键部署脚本

docker-compose.yml同目录下创建deploy.sh文件:

#!/bin/bash

# 定义颜色变量,用于美化输出
GREEN="\033[0;32m"
RED="\033[0;31m"
NC="\033[0m" # 无颜色

echo -e "${GREEN}开始部署sa-admin项目...${NC}"

# 停止并删除所有相关容器、网络,同时删除关联镜像
echo -e "${GREEN}正在停止并清理旧容器和镜像...${NC}"
docker-compose down --rmi all

# 检查上一条命令是否执行成功
if [ $? -ne 0 ]; then
    echo -e "${RED}清理旧容器和镜像失败!${NC}"
    exit 1
fi

# 重新构建镜像并启动容器
echo -e "${GREEN}正在构建新镜像并启动容器...${NC}"
docker-compose up --build -d

# 检查部署是否成功
if [ $? -eq 0 ]; then
    echo -e "${GREEN}部署成功!${NC}"
    echo -e "${GREEN}正在运行的容器:${NC}"
    docker ps --filter "name=sa-admin"
else
    echo -e "${RED}部署失败!${NC}"
    exit 1
fi
    

脚本执行顺序说明:

  1. 删除旧的镜像、容器
  2. 构建新镜像
  3. 创建新容器并启动

给脚本添加可执行权限:chmod +x deploy.sh

5. 一键部署

进入deploy.sh文件目录下,执行命令:./deploy.sh

6. 执行效果

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到