📋 项目概述

本文将详细介绍如何在 CentOS 7 环境下使用 Docker Compose 一键部署包含 Spring Boot 2 后端、Vue 3 前端、MySQL 数据库和 Redis 缓存的全栈项目。

环境要求

  • 服务器环境:CentOS 7(云服务器或本地虚拟机)

  • 容器环境:Docker 及 Docker Compose

  • 开发环境:JDK 8、Maven 3、IDEA、Node.js(用于项目构建)

🚀 部署步骤

1. 环境准备

1. Docker 安装与配置

  1.若您安装过docker,需要先删掉,之后再安装依赖:

sudo yum remove docker docker-common docker-selinux docker-engine
sudo yum install -y yum-utils device-mapper-persistent-data lvm2

2.下载repo文件

wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo

软件仓库地址替换为:

sudo sed -i 's+download.docker.com+mirrors.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo

3、更新索引文件并安装

sudo yum makecache fast
sudo yum install docker-ce

2.前端、后端项目打包

        前端后端打包之前,需要将项目配置信息进行调整,redis:host: redis等,后续创建容器的会创建一个自定义网络,并把所有容器都连接到自定义网络中。这样它们之间通信,就能通过容器名代替ip地址通信

        

如果前端代码中硬编码了 localhost:8080,其他用户访问时会请求他们自己电脑的8080端口,而不是你的服务器。前端也要对应修改,比较重要的是这里

后端打包:打开maven面板,先执行clean,再执行package,这样就会出现一个target目录,target目录会有一个jar包

前端打包:打开终端,输入npm run build,这样左边会有一个dist目录,dist就是由前端打包出来的

后端jar前端dist文件夹中的内容上传到虚拟机,虚拟机目录

/opt/project/
├── docker-compose.yml
├── nginx/
│   ├── nginx.conf
│   └── Dockerfile
│   └──── dist/          # 前端构建产物
├── backend/
│   ├── Dockerfile
│   └── app.jar           # 后端JAR包

实际上这样就已经做完很多了,因为困难的是那些跨域问题什么的,还要继续修改前后端代码,但是我已经改好了

3、配置 Nginx.conf,Dockerfile(nginx目录下的)

[root@localhost nginx]# cat nginx.conf
server {
    listen 80;
    server_name 192.168.92.11;


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


    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://springboot:8080/;
        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;
        proxy_set_header Authorization $http_authorization;


        add_header Access-Control-Allow-Origin 'http://192.168.92.11' always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With' always;
        add_header Access-Control-Allow-Credentials 'true' always;


        if ($request_method = 'OPTIONS') {
            add_header Access-Control-Allow-Origin 'http://192.168.92.11';
            add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
            add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With';
            add_header Access-Control-Max-Age 86400;
            return 204;
        }
    }


    location /category/ {
        proxy_pass http://springboot:8080/;
        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;
        proxy_set_header Authorization $http_authorization;


        add_header Access-Control-Allow-Origin 'http://192.168.92.11' always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With' always;
        add_header Access-Control-Allow-Credentials 'true' always;

        if ($request_method = 'OPTIONS') {
            return 204;
        }
    }


    location /poets/ {
        proxy_pass http://springboot:8080/;
        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;
        proxy_set_header Authorization $http_authorization;


        add_header Access-Control-Allow-Origin 'http://192.168.92.11' always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With' always;
        add_header Access-Control-Allow-Credentials 'true' always;

        if ($request_method = 'OPTIONS') {
            return 204;
        }
    }

    location /article/ {
        proxy_pass http://springboot:8080/;
        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;
        proxy_set_header Authorization $http_authorization;


        add_header Access-Control-Allow-Origin 'http://192.168.92.11' always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With' always;
        add_header Access-Control-Allow-Credentials 'true' always;

        if ($request_method = 'OPTIONS') {
            return 204;
        }
    }

    location /user/ {
        proxy_pass http://springboot:8080/;
        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;
        proxy_set_header Authorization $http_authorization;


        add_header Access-Control-Allow-Origin 'http://192.168.92.11' always;
        add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header Access-Control-Allow-Headers 'Content-Type, Authorization, X-Requested-With' always;
        add_header Access-Control-Allow-Credentials 'true' always;

        if ($request_method = 'OPTIONS') {
            return 204;
        }
    }


    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}
[root@localhost nginx]# cat Dockerfile
FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80


4、配置 Dockerfile(backend目录下的)

[root@localhost backend]# cat Dockerfile
FROM openjdk:17
LABEL author=liuyunjie
COPY Springbootdemo-0.0.1-SNAPSHOT.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]


5、运行项目

docker network create app-network

docker run -d --name mysql --network app-network -p 3306:3306 \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -e MYSQL_DATABASE=big_event \
  mysql:8.0.35

docker run -d --name redis --network app-network -p 6379:6379 redis:5.0-alpine

docker run -d --name springboot --network app-network -p 8080:8080 springboot2.7
docker run -d --name vue --network app-network -p 80:80 vue3

这里的数据库还没有数据,你还要自己导入,用navicat连接虚拟机上的数据库,连接成功后进行数据库的操作,运行我提供的sql脚本,简言来说你可以用windows上的数据库管理工具来操作虚拟机上的数据库,不然虚拟机上的数据库没有数据,你也就不能登录啥的,(可以创建好数据库容器就直接做这一步)

然后就成功了,可以访问自己的虚拟机ip进行访问了

想要一键启动就要用到docker-compose编排工具,此时虚拟机目录:

project/
├── backend/
│      ├── app.jar
│      └── Dockerfile
├── docker-compose.yml
├── frontend/
├── mysql/
│   ├── conf/
│   └── init/          # 在这里创建 init 目录
│       └── big_event.sql  # 把你的 SQL 文件放在这里
└── nginx/
    ├── dist/
    └── nginx.conf
    └── Dockerfile
[root@localhost project]# cat docker-compose.yml
version: '3.8'

services:
  # MySQL 数据库服务
  mysql:
    image: mysql:8.0.35
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: big_event
      MYSQL_TCP_PORT: 3306
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d
      - ./mysql/init:/docker-entrypoint-initdb.d
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10

  # Redis 缓存服务
  redis:
    image: redis:5.0-alpine
    container_name: redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      timeout: 10s
      retries: 5

  # SpringBoot 后端服务
  springboot:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: springboot
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/big_event?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=123456
      - SPRING_REDIS_HOST=redis
      - SPRING_REDIS_PORT=6379
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Nginx + Vue 前端服务
  nginx:
    image: nginx:alpine
    container_name: vue
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./nginx/dist:/usr/share/nginx/html  # Vue 构建后的静态文件
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - springboot
    networks:
      - app-network

# 数据卷定义
volumes:
  mysql_data:
    driver: local
  redis_data:
    driver: local

# 网络定义
networks:
  app-network:
    driver: bridge
-------------------------------------------------------------------------------------------------------------------

[root@localhost project]# cd /opt/project/mysql/init
[root@localhost init]# ls
big_event.sql
把sql文件保存在这里,docker-compose启动时会自己构建数据,不然还是要自己导入,再执行这条命令就可以一键启动了,和自己手动起四个容器效果一致:docker compose up -d

6.加几个注意事项

生产环境端口
生产环境没有固定的端口号(前端)

宿主机路径: /opt/project/backend/Springbootdemo-0.0.1-SNAPSHOT.jar
    ↓ Docker COPY 命令
容器内路径: /app.jar

Dockerfile 就是用来定义和构建 Docker 镜像的蓝图文件。

你想让别的电脑也可以通过你的虚拟机ip来访问你的服务,你可以设置成桥接网络或使用云服务器

🌐 虚拟机桥接模式 vs 云服务器

虚拟机桥接模式 🏠

text

✅ 同一局域网内可访问
✅ 同一网段设备可访问  
❌ 互联网无法访问
❌ 外网用户无法访问

特点:

  • 虚拟机获得一个局域网IP(如:192.168.1.xxx

  • 只有连接到同一个路由器/交换机的设备能访问

  • 属于内网环境

  • 免费,但访问范围有限

云服务器 ☁️

text

✅ 同一局域网可访问
✅ 同一网段可访问
✅ 互联网可访问  
✅ 全球用户可访问

特点:

  • 云服务器获得一个公网IP(如:47.xxx.xxx.xxx

  • 任何有互联网连接的设备都能访问

  • 属于公网环境

  • 需要付费,但访问无限制

通过网盘分享的文件:poems 链接: https://pan.baidu.com/s/1ZFr7fCxUIh5bbsMH7Nsb9A 提取码: yunh --来自百度网盘超级会员v1的分享

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐