基于上次项目的全流程部署方案,各位少侠想必也觉得操作繁琐吧?那么如何简化部署流程,最好能一步完成整体部署工作。那么各位少侠必不能错过今天的这份指南。

首先我们在上次部署全流程中已经使用过Docker来容器化部署MySQL,Redis等中间件了,那么这次考虑将项目所有相关的东西全部容器化。再根据这段时间部署项目的经验,我们在安全的考虑下使用docker网络来连接系统与中间件,整个项目对外只暴露代理前端的Nginx9092端口。一个一个的启动容器也太不智能了,所以咱们考虑引入Docker Compose 这个工具来做部署编排。

Docker Compose 就是一个用来定义和运行多容器 Docker 应用程序的工具。

你可以使用一个 YAML 文件(通常是 docker-compose.yml)来配置你的应用所需的所有服务。然后,使用一个简单的命令(docker-compose up),Compose 就会根据你的配置,创建并启动所有服务,处理好它们之间的网络和依赖关系。

那么首先在安装完Docker后记得安装Docker Compose

sudo curl -L "https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

验证

docker-compose -version

安装完工具那么就开始部署,这次咱们的部署目录结构如下,文件按目录放好

/app
├── back

│   ├── Dockerfile
│   └── your-project-name.jar

├── front

│    ├── Dockerfile

│    ├── nginx.conf    Nginx配置
│    └── dist

├── data

│    ├── mysql

│        ├── data

│        └── init

│            └── init.sql    数据库初始化用

│    ├── redis

│         ├── data

│         └── conf

│             └──redis.conf

│    ├── rabbitMq

│        └── data

└── docker-compose.yml

接着挨个配置,首先是后端的dockerfile

# 使用JDK21基础镜像
FROM openjdk:21-jdk-slim

#安装缺失字体(这个按需)
RUN apt-get update && apt-get install -y fontconfig fonts-dejavu libfreetype6 && rm -rf /var/lib/apt/lists/*

# 设置作者信息
LABEL maintainer="xxx <xxxxxxx@qq.com>"

# 设置环境变量
ENV TZ=Asia/Shanghai \
    SERVER_DIR=/smallnovel \
    CSP_LOG_DIR=logs/csp

# 创建容器内应用目录
RUN mkdir -p $SERVER_DIR \
    && mkdir -p $CSP_LOG_DIR \
    && chmod -R 755 $SERVER_DIR \
    && chmod -R 755 $CSP_LOG_DIR

# 设置容器内工作目录
WORKDIR $SERVER_DIR

# 复制宿主机应用JAR文件到容器内工作目录
COPY *.jar app.jar

# 暴露端口
EXPOSE 9091

# 声明日志卷(新增)
VOLUME /smallnovel/logs

# 启动应用
ENTRYPOINT ["java", "-Dcsp.sentinel.log.dir=$CSP_LOG_DIR", "-jar", "app.jar", "--spring.profiles.active=prod"]

后端数据库,Redis等连接由于在生产环境时使用docker网络,所以需要做相应修改。即使用组件容器名来连接。示例如下:

spring:
  config:
    activate:
      on-profile: dev
  #mysql数据库配置
  datasource:
    url: jdbc:mysql://localhost:3306/novel_test?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 1234
spring:
  config:
    activate:
      on-profile: prod
  #mysql数据库配置
  datasource:
    url: jdbc:mysql://mysql:3306/smallnovel?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 1234

然后是前端dockerfile,

# 使用Nginx官方镜像
FROM nginx:alpine

# 设置作者信息
LABEL maintainer="xxx <xxxxxxx@qq.com>"

# 创建日志目录并设置权限
RUN mkdir -p /var/log/nginx \
    && touch /var/log/nginx/nginx_access.log \
    && touch /var/log/nginx/nginx_error.log \
    && chown -R nginx:nginx /var/log/nginx \
    && chmod 755 /var/log/nginx \
    && chmod 644 /var/log/nginx/nginx_access.log \
    && chmod 644 /var/log/nginx/nginx_error.log

# 复制前端构建文件
COPY ./dist /usr/share/nginx/html

# 复制Nginx配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 9092

# 启动Nginx
CMD ["nginx", "-g", "daemon off;"]

前后端连接也要做相应的修改

ENV = 'development'

VUE_APP_BASE_API_URL = 'http://127.0.0.1:9091/api'

ENV = 'production'

VUE_APP_BASE_API_URL = '/api'

由Nginx直接做代理转发,nginx.conf配置如下:

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       9092;
        server_name  xx.xx.xx.xx;

        # 前端静态资源
        location / {
            root /usr/share/nginx/html; # 使用挂载目录
            index index.html;
            try_files $uri $uri/ /index.html; # SPA路由支持
        }

        # 后端API代理
        location /api/ {
            proxy_pass http://back:9091/api/;
            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;
        }
        # 静态资源代理(如图片)
        location /uploads/ {
            proxy_pass http://back:9091/uploads/;
            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;
        }
    }

    server {
        listen       9092;
        server_name  localhost;

        # 前端静态资源
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        # 后端API代理
        location /api/ {
            proxy_pass http://back:9091/api/;
            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;
        }
        # 静态资源代理(如图片)
        location /uploads/ {
            proxy_pass http://back:9091/uploads/;
            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;
        }
    }
}

接着就是最重要的dockerr compose编排文件

docker-compose.yml
# 定义网络
networks:
#docker网络的名称,可随意,全文保持一致
  app-network:
    driver: bridge

# 定义所有服务
services:
  # 前端服务
  front:
    build: ./front
    container_name: front
    ports:
      - "9092:9092"
    networks:
      - app-network
    depends_on:
      - back
    restart: unless-stopped

  # 后端服务
  back:
    build: ./back
    container_name: back
    ports:
      - "9091:9091"
    volumes:
      - /app/data/logs:/smallnovel/logs
    networks:
      - app-network
    environment:
      - TZ=Asia/Shanghai
    depends_on:
      - mysql
      - redis
      - rabbitmq
    restart: unless-stopped

  # MySQL服务
  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      - "3306:3306"
    networks:
      - app-network
    environment:
      MYSQL_ROOT_PASSWORD: 1234
      MYSQL_DATABASE: smallnovel
      TZ: Asia/Shanghai
    volumes:
      - mysql_data:/var/lib/mysql
      - /app/data/mysql/init:/docker-entrypoint-initdb.d  # 初始化SQL脚本,后半句固定写法不要改
    command: ['--default-authentication-plugin=mysql_native_password']
    restart: unless-stopped

  # Redis服务
  redis:
    image: redis:8-alpine
    container_name: redis
    ports:
      - "6379:6379"
    networks:
      - app-network
    environment:
      TZ: Asia/Shanghai
    volumes:
      - redis_data:/data
      - /app/data/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf
    command: redis-server /usr/local/etc/redis/redis.conf
    restart: unless-stopped

  # RabbitMQ服务
  rabbitmq:
    image: rabbitmq:3.10-management
    container_name: rabbitmq
    networks:
      - app-network
    ports:
      - "5672:5672"
      - "15672:15672"  # 暴露rabbit管理端口
    environment:
      RABBITMQ_DEFAULT_USER: guest
      RABBITMQ_DEFAULT_PASS: guest
      RABBITMQ_DEFAULT_VHOST: smallnovel
      TZ: Asia/Shanghai
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq
    restart: unless-stopped

# 数据卷定义
volumes:
  mysql_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /app/data/mysql/data
  redis_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /app/data/redis/data
  rabbitmq_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /app/data/rabbitmq/data

最后,按照目录结构将文件放入服务器,进入/app文件夹

启动所有服务:docker-compose up -d

启动某个服务:docker-compose up -d 服务名

下线全部服务:docker-compose down

下线某个服务:docker-compose down 服务名

重启特定服务: docker-compose restart 服务名

修改dockerfile文件后重启需要重构镜像,以保证配置生效

docker-compose up -d --build 服务名

查看所有服务状态:docker-compose ps
查看实时日志:docker-compose logs -f
查看特定服务日志:docker-compose logs -f back

至此各位少侠想必已经能完全容器化部署一整个项目了,祝诸位一次成功。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐