代码上传Docker化部署

1. 准备Docker相关配置文件

后端

项目目录如下

image

  • Dockerfile

    # 使用官方 Maven 镜像进行打包
    FROM maven:3.8.4-openjdk-8 AS builder
    
    # 设置工作目录
    WORKDIR /app
    
    # 复制整个项目到容器中
    COPY . .
    
    # 使用 Maven 打包项目
    RUN mvn clean package -DskipTests
    
    # ========== 分阶段构建 ==========
    # 使用轻量级运行时镜像
    FROM openjdk:8-jdk-alpine
    
    # 设置维护者信息
    LABEL maintainer="quanht"
    
    # 设置时区
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    
    # 安装必要工具
    RUN apk add --no-cache bash curl
    
    # 设置工作目录
    WORKDIR /app
    
    # 从 builder 阶段复制打包好的 jar 文件
    COPY --from=builder /app/runyue-service/target/runyue-service.jar app.jar
    
    # 暴露端口
    EXPOSE 9500
    
    # 启动命令
    ENTRYPOINT ["java", "-jar", "app.jar", "--spring.profiles.active=prod"]
    
  • Docker Compose

    项目使用了MySQL和Redis,将文件分为docker-compose-env.yml(环境依赖)、docker-compose-server.yml(业务服务)来控制启动顺序,当然也可以使用depends_on + condition来控制(Docker Compose v2.1+开始支持)

    • docker-compose-env.yml

      version: '3'
      services:
        mysql:
          image: mysql:8
          container_name: runyue-mysql
          environment:
            - MYSQL_ROOT_PASSWORD=mysql_CNEkRf
          ports:
            - 3306:3306
          volumes:
            - ./.mysql-data:/var/lib/mysql
            - ./mysql-init:/docker-entrypoint-initdb.d # 容器首次启动时自动执行,mysql中有数据则不会执行
          restart: always
          networks:
            - runyue-net
        redis:
          image: redis:6
          container_name: runyue-redis
          ports:
            - 6379:6379
          volumes:
            - ./.redis-data:/data # 容器数据持久化
          command: redis-server --requirepass redis_epChT3
          networks:
            - runyue-net
      networks:
        runyue-net:
      
    • docker-compose-server.yml

      version: '3'
      services:
        runyue-service:
          build:
            context: .
            dockerfile: Dockerfile
          container_name: runyue-service
          ports:
            - "9500:9500"
          volumes:
            - ./logs:/app/logs # 日志目录
            - ./uploadPath:/app/uploadPath # 文件上传目录
          networks:
            - runyue-net
      networks:
        runyue-net:
      
      

前端

项目目录如下

image

  • Dockerfile

    # 构建阶段
    FROM node:16-alpine AS builder
    
    # 设置工作目录
    WORKDIR /app
    
    # 复制 package.json 和 package-lock.json
    COPY package*.json ./
    
    # 安装依赖
    RUN npm install
    
    # 复制项目源代码
    COPY . .
    
    # 确保所有文件具有正确的权限
    RUN chmod -R 755 /app
    
    # 构建项目
    RUN npm run build:prod
    
    # 生产阶段
    FROM nginx:alpine
    
    # 将构建好的文件复制到 nginx 目录
    COPY --from=builder /app/dist /usr/share/nginx/html
    
    # 复制 nginx 配置文件(如果需要自定义配置)
    COPY nginx.conf /etc/nginx/nginx.conf
    
    # 暴露端口
    EXPOSE 80
    
    # 启动 nginx
    CMD ["nginx", "-g", "daemon off;"]
    
    
  • Docker Compose

    version: '3.8'
    
    services:
      runyue-ui:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: runyue-ui
        ports:
          - "80:80"
        environment:
          - NODE_ENV=production
        restart: always
        networks:
          - runyue-net
    
    networks:
      runyue-net:
    
    

前端是通过Nginx的转发来访问后端的,还需要准备nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # 定义上游服务器
    upstream runyue-service {
        server runyue-service:9500;  # 根据实际情况修改后端服务地址
    }

    server {
        listen       80;
        listen       [::]:80;
        server_name  localhost;

        # 静态文件服务
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }

        # API 请求转发到后端服务
        location /prod-api/ {
            proxy_pass http://runyue-service/;
            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_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }

        # 错误页面
        error_page 404 /404.html;
        location = /404.html {
            root /usr/share/nginx/html;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
}

前端通过 Nginx 的反向代理访问后端服务。为确保容器间通信正常,需保证前后端使用同一网络。

由于 Docker Compose 会自动将当前目录名作为项目名称加入网络名称中,而前后端部署目录不同,因此建议在前后端项目的同级目录下添加 .env 文件来统一项目名称。

当然也可以直接填写实际的IP(注意:linux貌似默认不支持host.docker.internal

# 指定docker的项目名称
COMPOSE_PROJECT_NAME=runyue

image

2. 代码上传到服务

可选择以下两种方式上传代码:

  1. SFTP 上传

    • 后端:上传前先执行 mvn clean 清理构建产物
    • 前端:删除 node_modules 目录以减少上传体积
  2. Git 上传

    • 将代码推送到远程仓库,在服务器上拉取最新代码

3. 项目启动

后端

先执行docker-compose-env.yml

sudo docker compose -f docker-compose-env.yml up -d

验证环境依赖的服务都启动完成后,再执行docker-compose-server.yml

sudo docker compose -f docker-compose-server.yml up -d

前端

sudo docker compose up -d

posted @ 2025-08-17 21:00  quanht  阅读(17)  评论(0)    收藏  举报