撰于 阅读 22

springboot项目打包docker镜像并部署

1. 为什么要使用docker

首先我们不使用docker去启动,那么我想项目的部署需要通过maven将项目打包成jar包,丢到环境上去启动,如果服务发生异常springboot挂掉项目是需要手动重启的。

而且别人使用你的项目也需要下载源码,里面里面的一些配置改成自己的,然后再打包成jar,按照同样的步骤去部署,不是很友好。

而通过docker我们可以将一下自定义的内容比如对象存储服务、数据库等通过环境变量的形式,在启动容器的时候去设置,而镜像可以发布到镜像仓库,使用者拉取就可以直接使用非常的方便。

2. 打包步骤

2.1 配置修改

修改application.yaml将里面一下配置挪到prod文件中

server:
  # 端口号
  port: 8081

spring:
  profiles:
    active: dev
  jackson:
    # 设置后台返参,若字段值为 null, 是否返回
#    default-property-inclusion: non_null
    date-format: yyyy-MM-dd HH:mm:ss
  servlet:
    multipart:
      # 限制上传文件大小
      max-file-size: 10MB
      
jwt:
  # 签发人
  issuer: chengzi
  # 秘钥
  secret: gR6cytlUlgMfVh08nLKlksl898JGFUIBVlsCbKvRlWcLwNRU6+rIPcLx21x191kJgP8udtoZuHt5yUDWtgg==
  # token 过期时间(单位:分钟) 24*60
  tokenExpireTime: 1440
  # token Header 中的 key 值
  tokenHeaderKey: Authorization
  # token Header 中的 value 值前缀
  tokenPrefix: Bearer

#=================================================================
# IP归属地信息库文件路径 ip2region.xdb
#=================================================================
xdb:
  profile: xxx

application-prod.yaml:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: ${SPRING_DATASOURCE_URL}
    username: ${SPRING_DATASOURCE_USERNAME}
    password: ${SPRING_DATASOURCE_PASSWORD}
    hikari:
      minimum-idle: 5
      maximum-pool-size: 9
      auto-commit: true
      idle-timeout: 30000
      pool-name: Weblog-HikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  
#=================================================================
# log
#=================================================================
logging:
  config: classpath:logback-weblog.xml

#=================================================================
# minio (上传图片需要,需配置成自己的地址)
#=================================================================
minio:
  endpoint: ${MINIO_ENDPOINT}
  accessKey: ${MINIO_ACCESS_KEY}
  secretKey: ${MINIO_SECRET_KEY}
  bucketName: ${MINIO_BUCKET_NAME}

#=================================================================
# Lucene 全文检索
#=================================================================
lucene:
  indexDir: /app/weblog/lucene-index # lucene 索引存放的位置

2.2 Dockerfile

# FROM 指定使用哪个镜像作为基准
FROM openjdk:8-jdk-alpine

# 创建目录, 并设置该目录为工作目录
RUN mkdir -p /windblog
WORKDIR /windblog

# 复制文件到镜像中
COPY windblog-web-0.0.1-SNAPSHOT.jar app.jar
COPY application-prod.yaml application-prod.yaml
COPY application.yaml application.yaml

# 设置时区
ENV TZ=Asia/Shanghai

# 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV JAVA_OPTS="-Xms300m -Xmx300m -Djava.security.egd=file:/dev/./urandom"

# 应用参数,可通过 docker run -e "ARGS=" 来设置,如 -e "ARGS=--spring.profiles.active=prod"
ENV ARGS="--spring.profiles.active=prod"

# 暴露 8081 端口
EXPOSE 8081

# 启动后端服务
CMD java ${JAVA_OPTS} -jar app.jar $ARGS

2.3 打包镜像

将maven打包好的windblog-web-0.0.1-SNAPSHOT.jar、application-prod.yaml、application.yaml和dockerfile放到服务器的同一目录下

执行命令

docker build -t windblog:v1.0 -f Dockerfile .

-t后面是你自定义的镜像名字

执行完成后可以通过

docker images

查看已完成的镜像列表

3. 部署项目

在项目目录下新建docker-compose.yml文件

version: '3.8'
services:
  app:
    image: windblog:v1.0  # 替换为你的镜像名称
    container_name: windblog # 容器名称
    network_mode: "host"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://127.0.0.1:3306/windblog?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
      SPRING_DATASOURCE_USERNAME: windblog
      SPRING_DATASOURCE_PASSWORD: windblog
      MINIO_ENDPOINT: http://windblog:9000
      MINIO_ACCESS_KEY: jNcxxxxxJWDG7PX5
      MINIO_SECRET_KEY: CTkVKu4Sxxxxxxxxxxx9pV5D0aBDc8H2
      MINIO_BUCKET_NAME: winblog
    ports:
      - "8081:8081"
    volumes:
      - /mnt/data/docker/windblog/lucene:/app/weblog/lucene-index
      - /mnt/data/docker/windblog/logs:/app/weblog/logs

注意 volumes,因为我的项目中日志和全文索引都需要创建文件夹使用,所以需要指定我在容器中的相应路径应该指向哪里,这个路径是可以自定义的

3.1 后端服务

在docker-compose.yml下执行命令启动服务

docker-compose up --detach

可以去挂载的日志目录查看项目的启动日志

3.2 前端

在宝塔中新建一个纯静态的php网站,绑定域名,然后将前端打包的dist文件上传到网站的跟路径下解压,注意不保留dist文件夹,将dist文件夹里的内容剪切粘贴到网站的根目录下


点击网站设置nginx反向代理

location / {
        root /www/wwwroot/test.nasfly.top;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:8081/;
        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;
    }

/api/请根据你的前端项目的实际追加接口前缀设置,注意端口号最后的斜杆,很关键
proxy_pass http://127.0.0.1:8081/

当 proxy_pass 的 URL 末尾有斜杠 / 时,Nginx 会将匹配到的 location 路径从原始请求路径中移除,然后将剩余部分附加到 proxy_pass 的 URL 后面。

例如,如果请求路径是 /api/some/endpoint,Nginx 会将请求代理到 http://127.0.0.1:8081/some/endpoint

proxy_pass http://127.0.0.1:8081

当 proxy_pass 的 URL 末尾没有斜杠 / 时,Nginx 会将匹配到的 location 路径保留在原始请求路径中,然后将整个路径附加到 proxy_pass 的 URL 后面。

例如,如果请求路径是 /api/some/endpoint,Nginx 会将请求代理到 http://127.0.0.1:8081/api/some/endpoint

不设置对你的接口都会404

然后访问你的域名,就可以访问网站了

4. 镜像发布

为了别人也能使用我们的镜像,因为现在镜像是我们build在本地的,还没有发布到docker的仓库,我们需要再服务器上登录我们的dockerhub账号,然后更名镜像,push到公共仓库

去镜像查看已经有镜像啦

别人想使用直接新建一个docker-compose.yml文件将image: windblog:v1.0修改为image: chengzi1220/windblog:latest,然后执行

docker-compose up --detach

会自动拉取镜像并启动容器,记得前端单独部署哦

5. 总结

至于为什么没有将数据库也写入compose的文件中,是因为我们一般服务器都会安装宝塔和1panel,都是自带了mysql等数据库服务

如果再启动一个数据库容器会占用内存,所以在compose中将windblog的容器指定为host网络,可以直接使用宿主机创建的数据库,这样既节省内存也更加方便管理数据库