在树莓派5中使用Docker部署ruoyi前后端分离项目

前言

Docker镜像选取

  • 因为是树莓派arm64,所以拉取镜像的时候要格外注意。以下是我踩了很多不能用的镜像坑之后摸索出来的,现在你仍可在dockerhub机子可科学网上冲浪条件下)上直接拉取的镜像。
REPOSITORY                     TAG         IMAGE ID       CREATED         SIZE      SHARED SIZE   UNIQUE SIZE   CONTAINERS
ruoyi-admin                    latest      268e2764950f   25 hours ago    602MB     520.2MB       82.17MB       1
nginx                          latest      443d199e8bfc   3 weeks ago     193MB     97.11MB       95.89MB       1
redis                          latest      db35fcf47f4b   7 weeks ago     139MB     97.11MB       41.99MB       1
openjdk                        8           6fbf41d7a679   23 months ago   520MB     520.2MB       0B            1
ibex/debian-mysql-server-5.7   latest      a53b3adb3cdc   5 years ago     230MB     0B            229.9MB       1
arm64v8/maven                  3.5-jdk-8   bad818985d47   5 years ago     590MB     0B            590.4MB       1
  • 如你所见,我们用到的镜像主要包括以上几个,其中第一个ruoyi-admin是使用docker build基于Dockerfile构建的,它被用来构部署ruoyi后端服务器。(具体操作将在后端搭章节详细讲解
    • 至于nginx、redis、openjdk、debian-mysql-server-5.7、arm64/maven则可直接从dockerhub上pull下来,使用如下命令:
    docker pull nginx
    docker pull redis
    docker pull openjdk:8
    docker pull ibex/debian-mysql-server-5.7
    docker pull arm64v8/maven:3.5-jdk-8
    

后端部署

  • 在进行后端部署时,涉及到了mysql、redis、后端(ruoyi-admin)服务器的构建。他们分属于不同的docker容器,所以为了达到部署的目的,容器运行时肯定是要在同一网络下,参考开头提到的链接1的自建网络 --network net-ry。在对容器们进行docker run指令时注意添加这么一条--network net-ry就可以保证他们在同一网络下。
  • 整体介绍:首先讲后端部署。这一篇章主要介绍redis,mysql的分别部署,将ruoyi后端的application.ym文件的环境从原先的local改为prod,因为我们现在要部署而不是开发了。(这个主要看自己使用的ruoyi项目的具体情况,我的文件路径是这样的:~/EdgeCloudBackend/src/main/resources/application.ym
  • 使用Docker查看运行状态下的容器的ip地址和端口的命令:
    docker ps或者使用docker ps -a查看全部容器
  • 使用Docker查看运行状态下的容器的ip地址和端口的命令:
    docker inspect 容器ID
# application.ym的部分代码
# Spring配置
spring:
  #切换环境
  profiles:
    active: prod #就是这里从local改为prod
  • 之后,继续更改同级的application-prod.yml文件,它用来指定你所部署的mysql、redis服务器的具体地址。只用更改redis的host、mysql后的主数据库源的url即可,我更改完了之后完整文件如下:(也可以先看后面章节,等mysql、redis容器部署完了确定了ip再回来改)
# 项目相关配置
ruoyi:
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: /home/ruoyi/laboratory/uploadPath

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8080
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # tomcat最大线程数,默认为200
    max-threads: 800
    # Tomcat启动初始化的线程数,默认值25
    min-spare-threads: 30

# Spring配置
spring:
  redis:
    # 地址
    host: 172.68.0.2 #更改这里,这里就是在docker自建网络下运行你自己的redis的容器的ip地址
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password:
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://172.68.0.3:3306/laboratory?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 
        #更改这里,改为你自己的在docker自建网络下运行的mysql容器的ip地址。
        username: root
        password: 114514 #设置为你自己使用的数据库密码
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:
        username:
        password:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username:
        login-password:
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true
#授权相关地址
secret:
    ip: 127.0.0.1
    port: 7789

用Docker部署redis服务器

  • 部署redis服务器时最简单的,参考链接1步骤即可。仅需在宿主机先创建好redis.conf,然后在docker run的时候将宿主机的conf文件挂载到容器里即可。另外记得启动的时候要--network net-ry

用Docker部署mysql服务器

  • 这一步非常重要,直接关系到后续ruoyi后端服务器运行jar包时能否成功启动的问题。同样可以参考链接1。由于之前已经说明过docker拉取mysql了,下面直接运行。
    • 首先介绍我的文件夹布局:
    kochiya@raspberrypi:~/Devbuild/ruoyiDocker/mysql $ tree
    .
    ├── conf
    │   └── my.cnf
    └── data
        └── xxx.sql
    
    • 其中my.cnf文件中的内容如下:注意lower_case_table_names=1一定要加!如果你是使用的是树莓派或者同是arm64架构就一定要加!不然如果你数据库中表格名有大写字母的话会报错!本人踩坑亲测,,

    •   [client]
        default-character-set=utf8
         
        [mysql]
        default-character-set=utf8
        
        [mysqld]
        ##官方的配置
        #
        # Remove leading # and set to the amount of RAM for the most important data
        # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
        # innodb_buffer_pool_size = 128M
        #
        # Remove leading # to turn on a very important data integrity option: logging
        # changes to the binary log between backups.
        # log_bin
        #
        # Remove leading # to set options mainly useful for reporting servers.
        # The server defaults are faster for transactions and fast SELECTs.
        # Adjust sizes as needed, experiment to find the optimal values.
        # join_buffer_size = 128M
        # sort_buffer_size = 2M
        # read_rnd_buffer_size = 2M
        skip-host-cache
        skip-name-resolve
        datadir=/mysql
        
        lower_case_table_names=1 #记得一定要添加这一条!!忽略大小写
         
        character-set-server=utf8
        collation-server=utf8_unicode_ci
        explicit_defaults_for_timestamp=true
      
    • 将mysql容器运行起来:docker run -d --name mysql01 --network net-ry -v /home/kochiya/Devbuild/ruoyiDocker/mysql/conf/my.cnf:/etc/my.cnf -v /home/kochiya/Devbuild/ruoyiDocker/mysql/data:/var/lib/mysql --privileged=true --restart=always -e MYSQL_ROOT_PASSWORD=114514 -p 3306:3306 ibex/debian-mysql-server-5.7

      • 指令简介:-d后台运行;-v将宿主机文件目录或文件挂载到“:”后的容器内部目录或文件,–p指定容器运行的端口;ibex/debian-mysql-server-5.7之前下载的容器镜像。
    • 可以进入容器查看是否挂载成功:docker exec -it mysql01 /bin/bash执行后可以到处看看,看看指定的目录是否有挂载上宿主机的文件(conf文件和sql文件)。运行mysql -uroot -p进入mysql命令。使用show databases;查看当前容器中的数据库。

    •   	 mysql> show databases;
        	+--------------------+
        	| Database           |
        	+--------------------+
        	| information_schema |
        	| mysql              |
        	| performance_schema |
        	| sys                |
        	+--------------------+
        	5 rows in set (0.01 sec)
      
    • 现在我们可以建立一个专门的数据库来存放我们的xxx.sql。指令如下:(比如我这里建立的数据库叫‘laboraroty’)带数据库插入完即可。同时这个数据库名也要与上面提到过的application-prod.yml里的主数据库url的ip地址后的数据库名相对应。这样就搭建好了。

    •     mysql> create database laboratory;
          mysql> use laboratory;
          mysql> source /var/lib/mysql/xxx.sql;
      

构建并部署ruoyi后端服务器容器

  • 这里涉及到使用maven容器作为工具将后端项目打包。也是在选取和使用镜像方面踩了很多坑,都是关于jdk版本和maven版本以及ruoyi项目的xml文件中版本对应的问题,我使用的项目比较老,所以采用了maven3.5以及jdk1.8。如果你的项目也是要部署于arm64,强烈建议拉取我上面使用的arm64v8/maven:3.5-jdk-8也是废了些功夫试了很多错,终于找到了这个镜像。下面将其运行,将后端的目录挂载到容器中,我这里容器里是/mymaven,我的宿主机后端目录结构如下:
kochiya@raspberrypi:~/Devbuild/EdgeCloudBackend $ ls
bin  doc  LICENSE  pom.xml  README.md  ruoyi.iml  ry.sh  sql  src  target

其中这个target是在执行了mvn package之后产生的。运行启动容器的指令:
docker run -v /home/kochiya/Devbuild/EdgeCloudBackend:/mymaven -w /mymaven arm64v8/maven:3.5-jdk-8 mvn package运行完之后就可以看到你自己宿主机的项目目录多出来了target文件。

  • 将target文件里的jar包复制到ruoyi-admin文件夹中,这个文件夹主要被建立来用于我们构建后端服务器容器的镜像。所以说这个文件夹里需要有项目后端的jar包和一个Dockerfile文件,文件如下:这里我们将openjdk:8的镜像加入了我们的后端镜像镜像套镜像的方法也是查找了好多文档,踩了很多坑试来的,之前尝试各种方法,比如直接在Dockerfile里下载jdk,但是疯狂报错
FROM openjdk:8
ENV APP_PATH=/root/app
WORKDIR $APP_PATH
ADD ./ruoyi.jar /$APP_PATH/apps.jar #添加你当前的ruoyi-admin文件夹中的jar文件进入虚拟容器
EXPOSE 8080 #露出8080端口,方便后续被前端部署nginx容器访问
ENTRYPOINT ["java","-jar"]
CMD ["apps.jar"] #执行jar文件,将后端运行起来
  • 之后在ruoyi-admin文件夹下把docker build起来:命令:docker build -t ruoyi-admin .这里我们把构建的镜像也命名为ruoyi-admin然后可以运行docker images查看到底有没有被成功build出来。
  • 之后我们运行这个镜像:docker run -itd --name ruoyi-admin --network net-ry -p 8080:8080 ruoyi-admin
  • 注意我们更改使用了-itd来运行,由于有-d的存在,容器是在后台执行的,我们在命令行运行完之后是不知道它内部究竟是运行好了还是报错了,这时候我们使用指令docker logs ruoyi-admin来查看内部到底运行打印出的内容是什么样的。如果顺利的话打印情况如下:我们顺利启动了ruoyi后端,且成功连接了mysql和redis
09:36:33.532 [main] INFO  o.q.i.StdSchedulerFactory - [instantiate,1374] - Quartz scheduler 'RuoyiScheduler' initialized from an externally provided properties instance.
09:36:33.533 [main] INFO  o.q.i.StdSchedulerFactory - [instantiate,1378] - Quartz scheduler version: 2.3.2
09:36:33.536 [main] INFO  o.q.c.QuartzScheduler - [setJobFactory,2293] - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@2f7a7219
09:36:33.658 [main] DEBUG c.r.p.m.m.S.selectJobAll - [debug,137] - ==>  Preparing: select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark from sys_job
09:36:33.661 [main] DEBUG c.r.p.m.m.S.selectJobAll - [debug,137] - ==> Parameters: 
09:36:33.666 [main] DEBUG c.r.p.m.m.S.selectJobAll - [debug,137] - <==      Total: 3
09:36:35.231 [main] INFO  s.d.s.w.PropertySourcedRequestMappingHandlerMapping - [initHandlerMethods,69] - Mapped URL path [/v2/api-docs] onto method [springfox.documentation.swagger2.web.Swagger2Controller#getDocumentation(String, HttpServletRequest)]
09:36:37.105 [main] INFO  s.d.s.w.p.DocumentationPluginsBootstrapper - [start,160] - Context refreshed
09:36:37.158 [main] INFO  s.d.s.w.p.DocumentationPluginsBootstrapper - [start,163] - Found 1 custom documentation plugin(s)
09:36:37.285 [main] INFO  s.d.s.w.s.ApiListingReferenceScanner - [scan,41] - Scanning for api listing references
09:36:37.652 [main] INFO  o.a.c.h.Http11NioProtocol - [log,173] - Starting ProtocolHandler ["http-nio-8080"]
09:36:37.696 [main] INFO  c.r.RuoYiApplication - [logStarted,61] - Started RuoYiApplication in 15.989 seconds (JVM running for 16.605)
(♥◠‿◠)ノ゙  若依启动成功   ლ(´ڡ`ლ)゙  
.-------.       ____     __        
|  _ _   \      \   \   /  /    
| ( ' )  |       \  _. /  '       
|(_ o _) /        _( )_ .'         
| (_,_).' __  ___(_ o _)'          
|  |\ \  |  ||   |(_,_)'         
|  | \ `'   /|   `-'  /           
|  |  \    /  \      /           
''-'   `'-'    `-..-'       

前端部署

  • 本以为后端搞好了,前端就简简单单用nginx容器部署了,但也是过程一波三折,因为疯狂出现403 forbidden报错,后面细说。
  • 在前端工程中运行npm run build,会在前端文件夹目录中生成dist文件。为了便于讲解我们将dist文件夹复制到ruoyi-front文件夹中的html下,我的文件夹布局如下:
kochiya@raspberrypi:~/Devbuild/ruoyiDocker/ruoyi-front $ tree
.
├── conf
│   └── nginx.conf
├── html
│   └── dist
│       ├── favicon.ico
│       ├── index.html
│       ├── robots.txt
│       └── static
  • 可以看到在这个文件夹中除了dist文件夹还有conf,这主要是用来配置nginx的配置文件,内容如下:


   user nginx;

   worker_processes auto;

   error_log /var/log/nginx/error.log;

   pid /run/nginx.pid;

   include /usr/share/nginx/modules/*.conf;

   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 4096;

   include /etc/nginx/mime.types;

   default_type application/octet-stream;

   server {

   listen 80;#80端口

   server_name localhost;

   location / {

   root /usr/share/nginx/html;#虚拟容器中的位置,dist下的内容要挂载到这里

   index index.html;

   }

   location /prod-api/ {

   proxy_pass http://172.68.0.5:8080/; #之前运行的ruoyi后端服务器容器的地址+对应端口,一定要设置
   }
   }
   }
  • 使用命令运行nginx容器:docker run -itd --name nginx01 --network net-ry -p 80:80 -v /home/kochiya/Devbuild/ruoyiDocker/ruoyi-front/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/kochiya/Devbuild/ruoyiDocker/ruoyi-front/html/dist:/usr/share/nginx/html --privileged=true --restart=always nginx注意我这里是将dist文件夹的内容挂载到了容器中,而非把dist文件夹挂载过去。我查到的很多教程有些是把dist整个挂载过去,如:-v ~/ruoyi-front/html/:/usr/share/nginx/html但是我这要操作之后浏览器访问树莓派本机的80端口会产生如下403报错:(该报错使用docker logs nginx01查看内部报错)
2024/07/12 12:03:25 [error] 29#29: *1 directory index of "/nginx/html/" is forbidden, client: 192.168.1.xxx server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.xxx"
192.168.1.xxx - - [12/Jul/2024:12:03:25 +0000] "GET / HTTP/1.1" 403 153 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0"
  • 被这个问题困扰了半天。后面发现挂载dist内的内容到容器中就行了,这时候用你的宿主机(树莓派)的浏览器再访问localhost:80你的树莓派ip:80就能成功进入了,附成功的截图。
    在这里插入图片描述

存在的问题

  • 每次重启机器或者重启docker之后都可能会变docker运行的ip。即每个docker容器运行的ip不固定,一旦重启可能就要内部文件要要重新执行。
  • 后续考虑使用dockercompose整合这些docker。不然感觉太麻烦了。
  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值