微服务架构使用和docker部署方法(若依)

这里以若依官方网站开源的微服务框架为例子记录使用方法过程。

开源地址:RuoYi-Cloud: 🎉 基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统,同时提供了 Vue3 的版本

下载后,用IDEA社区版开发工具打开,Maven下pom.xml项目,下载相关依赖。

由于这里使用的注册中心是nacos,以window为例,下载nacos-server.zip工具包。我这里下载的是2.0.3版本的,可自行选择当前最新版本。若速度较慢,可下载迅雷软件客户端下载加速。

Releases · alibaba/nacos · GitHub

nacos下载完之后,在本地mysql客户端创建一个ry-config数据库,再将conf目录下的nacos-mysql.sql的表结构执行到里面。然后修改application.properties里的mysql数据库连接配置如下:

#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:spring.datasource.platform=mysql### Count of DB:db.num=1### Connect URL of DB:db.url.0=jdbc:mysql://127.0.0.1:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTCdb.user.0=rootdb.password.0=root### Connection pool configuration: hikariCP
db.pool.config.connectionTimeout=30000
db.pool.config.validationTimeout=10000
db.pool.config.maximumPoolSize=20
db.pool.config.minimumIdle=2

然后启动nacos,这里我使用的是单例模式启动nacos。打开命令行提示符工具,进入nacos的bin目录下。执行命令如下:

startup.cmd -m standalone

 执行完之后,会显示成功如下:

成功之后,就可以访问nacos本地地址了。在浏览器输入 http://localhost:8848/nacos  可打开。账号密码默认:nacos  nacos

项目的所有模块的配置信息都可以在这里配置。若依dev默认是配置好的,如果要添加新的环境,比如test,可在命名空间里现在设置,然后在配置管理-配置列表里选择对应的命名空间。手动添加配置文件记录:

这里先讲到这里。下面讲如何使用若依微服务框架:

模块解释:

ruoyi-api是服务调用接口写在此处

ruoyi-auth是认证中心,用来添加登录的

ruoyi-common是项目需要的一些内容,包括核心部分、数据源配置、数据域、日志配置、Redis配置、认证安全配置、swagger接口文档配置

ruoyi-gateway是网关,用来控制各模块的。网关的端口提供给前端连接各模块的统一的端口

ruoyi-modules包括了一些业务模块,现有的包括文件上传、代码生成、定时任务、系统配置模块,可在ruoyi-modules模块下添加自己需要的子模块。按照模块结构进行开发。包结构包括如下:

ruoyi-ui是后台管理系统。在根目录下,执行以下命令就可使用:

npm inpm run dev

ruo-visual是spring boot admin监控中心,运行后,访问http://localhost:9100即可。

上述模块大意讲完后,讲他们的使用。

项目的sql数据库在项目的根目录sql文件夹下。自行在自己的本地数据库创建。如若修改数据库名称,可在nacos启动之后的配置管理-配置列表里修改

api模块的使用说明:

模块之间不能直接相互调用,这里就使用FeignClient注解接口,调用modules下的方法,例如,要调用system模块下根据用户名称查询用户信息的接口,使用步骤如下。

1.在api模块下定义接口:

package com.ruoyi.system.api;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
import com.ruoyi.system.api.model.LoginUser;/*** 用户服务** @author ruoyi*/
@FeignClient(contextId = "remoteUserService", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = RemoteUserFallbackFactory.class)
public interface RemoteUserService
{/*** 通过用户名查询用户信息** @param username 用户名* @param source 请求来源* @return 结果*/@GetMapping("/user/info/{username}")public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);}

2、接口的服务降级:

package com.ruoyi.system.api.factory;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;/*** 用户服务降级处理* * @author ruoyi*/
@Component
public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserService>
{private static final Logger log = LoggerFactory.getLogger(RemoteUserFallbackFactory.class);@Overridepublic RemoteUserService create(Throwable throwable){log.error("用户服务调用失败:{}", throwable.getMessage());return new RemoteUserService(){@Overridepublic R<LoginUser> getUserInfo(String username, String source){return R.fail("获取用户失败:" + throwable.getMessage());}};}
}

3、model类和domain类创建:

package com.ruoyi.system.api.model;import java.io.Serializable;
import java.util.Set;
import com.ruoyi.system.api.domain.SysUser;/*** 用户信息** @author ruoyi*/
public class LoginUser implements Serializable
{private static final long serialVersionUID = 1L;/*** 用户唯一标识*/private String token;/*** 用户名id*/private Long userid;/*** 用户名*/private String username;/*** 登录时间*/private Long loginTime;/*** 过期时间*/private Long expireTime;/*** 登录IP地址*/private String ipaddr;/*** 权限列表*/private Set<String> permissions;/*** 角色列表*/private Set<String> roles;/*** 用户信息*/private SysUser sysUser;public String getToken(){return token;}public void setToken(String token){this.token = token;}public Long getUserid(){return userid;}public void setUserid(Long userid){this.userid = userid;}public String getUsername(){return username;}public void setUsername(String username){this.username = username;}public Long getLoginTime(){return loginTime;}public void setLoginTime(Long loginTime){this.loginTime = loginTime;}public Long getExpireTime(){return expireTime;}public void setExpireTime(Long expireTime){this.expireTime = expireTime;}public String getIpaddr(){return ipaddr;}public void setIpaddr(String ipaddr){this.ipaddr = ipaddr;}public Set<String> getPermissions(){return permissions;}public void setPermissions(Set<String> permissions){this.permissions = permissions;}public Set<String> getRoles(){return roles;}public void setRoles(Set<String> roles){this.roles = roles;}public SysUser getSysUser(){return sysUser;}public void setSysUser(SysUser sysUser){this.sysUser = sysUser;}
}
package com.ruoyi.system.api.domain;import java.util.Date;
import java.util.List;
import javax.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.annotation.Excel.ColumnType;
import com.ruoyi.common.core.annotation.Excel.Type;
import com.ruoyi.common.core.annotation.Excels;
import com.ruoyi.common.core.web.domain.BaseEntity;
import com.ruoyi.common.core.xss.Xss;/*** 用户对象 sys_user* * @author ruoyi*/
public class SysUser extends BaseEntity
{private static final long serialVersionUID = 1L;/** 用户ID */@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")private Long userId;/** 部门ID */@Excel(name = "部门编号", type = Type.IMPORT)private Long deptId;/** 用户账号 */@Excel(name = "登录名称")private String userName;/** 用户昵称 */@Excel(name = "用户名称")private String nickName;/** 用户邮箱 */@Excel(name = "用户邮箱")private String email;/** 手机号码 */@Excel(name = "手机号码")private String phonenumber;/** 用户性别 */@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")private String sex;/** 用户头像 */private String avatar;/** 密码 */private String password;/** 帐号状态(0正常 1停用) */@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")private String status;/** 删除标志(0代表存在 2代表删除) */private String delFlag;/** 最后登录IP */@Excel(name = "最后登录IP", type = Type.EXPORT)private String loginIp;/** 最后登录时间 */@Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)private Date loginDate;/** 部门对象 */@Excels({@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)})private SysDept dept;/** 角色对象 */private List<SysRole> roles;/** 角色组 */private Long[] roleIds;/** 岗位组 */private Long[] postIds;/** 角色ID */private Long roleId;public SysUser(){}public SysUser(Long userId){this.userId = userId;}public Long getUserId(){return userId;}public void setUserId(Long userId){this.userId = userId;}public boolean isAdmin(){return isAdmin(this.userId);}public static boolean isAdmin(Long userId){return userId != null && 1L == userId;}public Long getDeptId(){return deptId;}public void setDeptId(Long deptId){this.deptId = deptId;}@Xss(message = "用户昵称不能包含脚本字符")@Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")public String getNickName(){return nickName;}public void setNickName(String nickName){this.nickName = nickName;}@Xss(message = "用户账号不能包含脚本字符")@NotBlank(message = "用户账号不能为空")@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")public String getUserName(){return userName;}public void setUserName(String userName){this.userName = userName;}@Email(message = "邮箱格式不正确")@Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")public String getEmail(){return email;}public void setEmail(String email){this.email = email;}@Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")public String getPhonenumber(){return phonenumber;}public void setPhonenumber(String phonenumber){this.phonenumber = phonenumber;}public String getSex(){return sex;}public void setSex(String sex){this.sex = sex;}public String getAvatar(){return avatar;}public void setAvatar(String avatar){this.avatar = avatar;}@JsonPropertypublic String getPassword(){return password;}public void setPassword(String password){this.password = password;}public String getStatus(){return status;}public void setStatus(String status){this.status = status;}public String getDelFlag(){return delFlag;}public void setDelFlag(String delFlag){this.delFlag = delFlag;}public String getLoginIp(){return loginIp;}public void setLoginIp(String loginIp){this.loginIp = loginIp;}public Date getLoginDate(){return loginDate;}public void setLoginDate(Date loginDate){this.loginDate = loginDate;}public SysDept getDept(){return dept;}public void setDept(SysDept dept){this.dept = dept;}public List<SysRole> getRoles(){return roles;}public void setRoles(List<SysRole> roles){this.roles = roles;}public Long[] getRoleIds(){return roleIds;}public void setRoleIds(Long[] roleIds){this.roleIds = roleIds;}public Long[] getPostIds(){return postIds;}public void setPostIds(Long[] postIds){this.postIds = postIds;}public Long getRoleId(){return roleId;}public void setRoleId(Long roleId){this.roleId = roleId;}@Overridepublic String toString() {return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE).append("userId", getUserId()).append("deptId", getDeptId()).append("userName", getUserName()).append("nickName", getNickName()).append("email", getEmail()).append("phonenumber", getPhonenumber()).append("sex", getSex()).append("avatar", getAvatar()).append("password", getPassword()).append("status", getStatus()).append("delFlag", getDelFlag()).append("loginIp", getLoginIp()).append("loginDate", getLoginDate()).append("createBy", getCreateBy()).append("createTime", getCreateTime()).append("updateBy", getUpdateBy()).append("updateTime", getUpdateTime()).append("remark", getRemark()).append("dept", getDept()).toString();}
}

4、服务降级工厂类的配置,在resources目录下的META-INF目录下的文件spring.factories配置:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.ruoyi.system.api.factory.RemoteUserFallbackFactory

api远程调用接口的实现,在system模块下实现,接口名称就是接口上方定义的

/user/info/{username}

system模块实现如下,注意注解InnerAuth的使用及返回的类型要与api接口定义返回的类型一致是R<?>:

package com.ruoyi.system.controller;import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysRole;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysPermissionService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;/*** 用户信息* * @author ruoyi*/
@RestController
@RequestMapping("/user")
public class SysUserController extends BaseController
{@Autowiredprivate ISysUserService userService;@Autowiredprivate ISysRoleService roleService;@Autowiredprivate ISysPostService postService;@Autowiredprivate ISysPermissionService permissionService;@Autowiredprivate ISysConfigService configService;/*** 获取当前用户信息*/@InnerAuth@GetMapping("/info/{username}")public R<LoginUser> info(@PathVariable("username") String username){SysUser sysUser = userService.selectUserByUserName(username);if (StringUtils.isNull(sysUser)){return R.fail("用户名或密码错误");}// 角色集合Set<String> roles = permissionService.getRolePermission(sysUser.getUserId());// 权限集合Set<String> permissions = permissionService.getMenuPermission(sysUser.getUserId());LoginUser sysUserVo = new LoginUser();sysUserVo.setSysUser(sysUser);sysUserVo.setRoles(roles);sysUserVo.setPermissions(permissions);return R.ok(sysUserVo);}
}

上面完成之后,就可以在其他模块通过api接口名称使用该接口,如下:

在其他模块controller层可以通过autowired注解调用该方法获取相关用户信息@Autowiredprivate RemoteUserService remoteUserService;// 查询用户信息R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);if (R.FAIL == userResult.getCode()){throw new ServiceException(userResult.getMsg());}

多环境切换的使用:

在resources下分别定义不同环境配置如下,连接nacos的时候,可以在nacos配置不同的环境:

根目录pom.xm配置变量切换:

<!--统一配置测试开发生产环境--><profiles><profile><!--开发环境--><id>dev</id><properties><activatedProperties>dev</activatedProperties><nacosNamespace>36a6cffb-6ec5-4ed8-a357-f4170e2ab131</nacosNamespace><serverAddr>127.0.0.1:8848</serverAddr></properties></profile><profile><!--测试环境--><id>test</id><!-- 加了这个,默认选中 --><activation><activeByDefault>true</activeByDefault></activation><!-- 以下属性用于 bootstrap.yml 文件中 可通过 @activatedProperties@ 获取配置的变量--><properties><activatedProperties>test</activatedProperties><nacosNamespace>53177b7c-42f2-4e29-99d6-9e4e27654635</nacosNamespace><serverAddr>ruoyi-nacos:8848</serverAddr><ip>122.231.144.193</ip></properties></profile><!--生产环境--><profile><id>prod</id><properties><activatedProperties>prod</activatedProperties><nacosNamespace>099fa140-a9d1-42af-861b-85ae54471703</nacosNamespace><serverAddr>127.0.0.1:8848</serverAddr><ip>122.231.144.193</ip></properties></profile></profiles>

模块pom.xml下设置resources访问:

<build><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource></resources>
</build>

内容配置:

# boostrap.xml:# Tomcat
server:port: 9200# Spring
spring:boot:admin:client:url: http://localhost:9100instance:prefer-ip: trueapplication:# 应用名称name: ruoyi-authprofiles:# 环境配置active: @activatedProperties@main:allow-circular-references: trueallow-bean-definition-overriding: true
logging:file:name: logs/${spring.application.name}/info.log#bootstrap-dev.xml/bootstrap-test.xml/bootstrap-prod.xml# Spring
spring:cloud:nacos:discovery:# 服务注册地址server-addr:  @serverAddr@namespace:  @nacosNamespace@config:# 配置中心地址server-addr: @serverAddr@# 配置文件格式file-extension: yml# 共享配置shared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}namespace: @nacosNamespace@

logback.xml日志配置要对应相应的模块应用名称:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false"><!-- 日志存放路径 --><property name="log.path" value="logs/ruoyi-auth" /><!-- 日志输出格式 --><property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!-- 系统日志输出 --><appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/info.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>INFO</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/error.log</file><!-- 循环政策:基于时间创建日志文件 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 日志文件名格式 --><fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern><!-- 日志最大的历史 60天 --><maxHistory>60</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 过滤的级别 --><level>ERROR</level><!-- 匹配时的操作:接收(记录) --><onMatch>ACCEPT</onMatch><!-- 不匹配时的操作:拒绝(不记录) --><onMismatch>DENY</onMismatch></filter></appender><!-- 系统模块日志级别控制  --><logger name="com.ruoyi" level="info" /><!-- Spring日志级别控制  --><logger name="org.springframework" level="warn" /><root level="info"><appender-ref ref="console" /></root><!--系统操作日志--><root level="info"><appender-ref ref="file_info" /><appender-ref ref="file_error" /></root>
</configuration>

sql目录下是项目使用到的表结构,如果以后别别的表或者字段创建或者删除,则重新创建一个带有数据库名和日期的sql文件,将语法更新在里面,并通知给其他人,好更新自己的本地数据库,以保证项目运行没有问题。

以上是框架基本的使用,接下来讲解若依微服务框架在Linux centos环境的部署:

若依已经将打包工具和配置文件在项目根目录下设置好,稍作配置即可。

打包工具在bin目录下,如下,clean是清空target,package是打包,其他是运行打包后target下的jar包文件:

docker部署项目文件配置如下,deploy.sh是执行工具,docker-compose.yml是配置项目不同模块内容,copy.sh是复制打包后的jar包到不同模块下的jar目录下:

docker-compose.yml配置如下:

#由于上面有Redis,nacos,mysql的相关dockfile配置,所以这里注释掉,直接引用,否则就又要重新构建当执行命令的时候version : '3.8'
services:ruoyi-nacos:container_name: ruoyi-nacos
#    image: nacos/nacos-serverbuild:context: ./nacosdockerfile: dockerfileenvironment:- MODE=standalone- SPRING_DATASOURCE_PLATFORM=mysql- PREFER_HOST_mode=hostnamevolumes:- ./nacos/logs/:/home/nacos/logs- ./nacos/conf/application.properties:/home/nacos/conf/application.propertiesports:- "8848:8848"- "9848:9848"- "9849:9849"depends_on:- ruoyi-mysqlruoyi-mysql:container_name: ruoyi-mysql
#    image: mysql:5.7build:context: ./mysqldockerfile: dockerfileports:- "3306:3306"volumes:- ./mysql/conf:/etc/mysql/conf.d- ./mysql/logs:/logs- ./mysql/data:/var/lib/mysqlcommand: ['mysqld','--innodb-buffer-pool-size=80M','--character-set-server=utf8mb4','--collation-server=utf8mb4_unicode_ci','--default-time-zone=+8:00','--lower-case-table-names=1']environment:MYSQL_DATABASE: 'ry-cloud'MYSQL_ROOT_PASSWORD: shares2024.ruoyi-redis:container_name: ruoyi-redis
#    image: redisbuild:context: ./redisdockerfile: dockerfileports:- "6379:6379"volumes:- ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf- ./redis/data:/datacommand: redis-server /home/ruoyi/redis/redis.confruoyi-nginx:container_name: ruoyi-nginx
#    image: nginxbuild:context: ./nginxdockerfile: dockerfileports:- "80:80"volumes:- ./nginx/html/dist:/home/ruoyi/projects/ruoyi-ui- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf- ./nginx/logs:/var/log/nginx- ./nginx/conf.d:/etc/nginx/conf.ddepends_on:- ruoyi-gatewaylinks:- ruoyi-gatewayruoyi-gateway:container_name: ruoyi-gatewaybuild:context: ./ruoyi/gatewaydockerfile: dockerfileports:- "8080:8080"depends_on:- ruoyi-redislinks:- ruoyi-redisruoyi-auth:container_name: ruoyi-authbuild:context: ./ruoyi/authdockerfile: dockerfileports:- "9200:9200"depends_on:- ruoyi-redislinks:- ruoyi-redisruoyi-modules-system:container_name: ruoyi-modules-systembuild:context: ./ruoyi/modules/systemdockerfile: dockerfileports:- "9201:9201"depends_on:- ruoyi-redis- ruoyi-mysqllinks:- ruoyi-redis- ruoyi-mysqlruoyi-modules-gen:container_name: ruoyi-modules-genbuild:context: ./ruoyi/modules/gendockerfile: dockerfileports:- "9202:9202"depends_on:- ruoyi-mysqllinks:- ruoyi-mysqlruoyi-modules-job:container_name: ruoyi-modules-jobbuild:context: ./ruoyi/modules/jobdockerfile: dockerfileports:- "9203:9203"depends_on:- ruoyi-mysqllinks:- ruoyi-mysqlruoyi-modules-file:container_name: ruoyi-modules-filebuild:context: ./ruoyi/modules/filedockerfile: dockerfileports:- "9300:9300"volumes:- ./ruoyi/uploadPath:/home/ruoyi/uploadPathruoyi-visual-monitor:container_name: ruoyi-visual-monitorbuild:context: ./ruoyi/visual/monitordockerfile: dockerfileports:- "9100:9100"

配置好后,且打包完成移动之后,在Linux的home目录下上传以上内容。

在执行deploy.sh之前,先安装docker和docker-compose。

docker安装步骤可可参考若依微服务在线文档或者百度一下即可得到命令,安装时候使用的命令可根据不同系统来设置,这里以centos为例:

docker-compose也同样如此:

验证是否成功:docker-compose --version。上面是示例版本,如果想用最新版本,可更换版本号在地址中。

注意:安装好之后,安装若依微服务的执行步骤,需要使用./deploy.sh port先开通防火墙,才能开发端口,由于防火墙默认是关闭状态的,开通会拦截外网地址,包括docker的启动。因此建议在安装docker之前就先开通防火墙,将所需端口手动开放后,在刷新防火墙后关闭防火墙,再安装docker工具。

docker安装好之后还需要去拉取镜像安装系统环境,比如redis、nginx、mysql、nacos等。

当上面准备好之后,就可以执行./deploy.sh去部署项目了。

先执行./deloy.sh base,可执行mysql下的db下的sql文件等。注意建议项目本身的数据库初始化的时候不在这里面执行,而是手动添加在数据库里,包括ry-cloud.sql,ry-config.sql,ry-seate.sql。其他更新的数据结构sql可放这里执行.

成功之后,执行./deploy.sh modules其他其他模块jar包。

由于后台的dist已打包放在nginx/html/里面,且访问后端的端口是网关端口,因此,项目启动成功后,可以在浏览器直接访问,前台端口默认是80。

以上是第一次启动项目的时候的基本步骤,当出现多次部署更新新的jar包的时候,除了正常上传外,需要停止该jar包的命令,及先删除其对应的容器再删除对应的镜像,然后重新执行启动,方可部署成新的jar包内容,如果没有按照这个步骤去停止删除,容易出现多次启动都还是原来的内容没有变化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GNU Radio Radar Toolbox编译及安装

文章目录 前言一、GNU Radio Radar Toolbox 介绍二、gr-radar 安装三、具体使用四、OFDM 雷达仿真 前言 GNU Radio Radar Toolbox&#xff08;gr-radar&#xff09;是一个开放源码的工具箱&#xff0c;用于 GNU Radio 生态系统&#xff0c;主要目的是为雷达信号处理提供必要的…

vue源码解析——diff算法/双端比对/patchFlag/最长递增子序列

虚拟dom——virtual dom&#xff0c;提供一种简单js对象去代替复杂的 dom 对象&#xff0c;从而优化 dom 操作。virtual dom 是“解决过多的操作 dom 影响性能”的一种解决方案。virtual dom 很多时候都不是最优的操作&#xff0c;但它具有普适性&#xff0c;在效率、可维护性之…

木马免杀代码之python反序列化分离免杀

本篇文章主要用到python来对CobaltStrike生成的Shellcode进行分离免杀处理, 因此要求读者要有一定的python基础, 下面我会介绍pyhon反序列化免杀所需用到的相关函数和库 exec函数 exec函数是python的内置函数, 其功能与eval()函数相同, 但不同的是exec函数支持多行python代码…

我国新戊二醇产能逐渐增长 市场集中度有望进一步提升

我国新戊二醇产能逐渐增长 市场集中度有望进一步提升 新戊二醇&#xff08;NPG&#xff09;又称为2,2-二甲基-1,3-丙二醇&#xff0c;化学式为C5H12O2&#xff0c;熔点为124-130℃。新戊二醇多表现为一种无特殊气味的白色结晶固体&#xff0c;易溶于水及醇、醚等溶液。新戊二醇…

为什么看到这么多人不推荐C++?

前几天逛知乎的时候&#xff0c;看到一个问题&#xff1a; 看到这个问题我倒是想吐槽几句了。 C一直没找到自己的定位&#xff01; C语言&#xff1a;我是搞系统编程开发的&#xff0c;操作系统、数据库、编译器、网络协议栈全是我写的。 PHP&#xff1a;我是搞后端业务开发…

一年期SSL证书怎么申请?

申请SSL证书三步走 JoySSL_JoySSL SSL证书_JoySSL https证书-JoySSL 一、选证书类型 根据网站性质与安全需求&#xff0c;选定合适的SSL证书&#xff1a; - 域名验证证书&#xff08;DV&#xff09;&#xff1a;快速验证域名所有权&#xff0c;适用于个人网站、博客&#xff…

ReentrantLock源码阅读

1. 概述 lock锁, 基于队列同步器AQS, 实现公平锁、非公平锁 队列同步器AQS可以阅读我这篇文章&#xff1a; 点击传送 实现了Lock接口: public class ReentrantLock implements Lock// 加锁 获取不到锁一直等待 void lock(); // 加锁 获取不到锁一直等待 等待过程可以被中断…

【攻防世界】php_rce (ThinkPHP5)

进入题目环境&#xff0c;查看页面信息&#xff1a; 页面提示 ThinkPHP V5&#xff0c;猜测存在ThinkPHP5 版本框架的漏洞&#xff0c;于是查找 ThinkPHP5 的攻击POC。 构造 payload: http://61.147.171.105:50126/?sindex/think\app/invokefunction&functioncall_user_f…

【Go语言快速上手(一)】 初识Go语言

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Go语言专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; Go快速上手 1. 前言2. Go语言简介(为…

模拟Android系统Zygote启动流程

版权声明&#xff1a;本文为梦想全栈程序猿原创文章&#xff0c;转载请附上原文出处链接和本声明 前言&#xff1a; 转眼时间过去了10年了&#xff0c;回顾整个10年的工作历程&#xff0c;做了3年的手机&#xff0c;4年左右的Android指纹相关的工作&#xff0c;3年左右的跟传感…

亚马逊CloudFront使用体验

前言 首先在体验CloudFront之前&#xff0c;先介绍一下什么是CDN&#xff0c;以及CDN的基本原理。 CDN是Content Delivery Network&#xff08;内容分发网络&#xff09;的缩写&#xff0c;是一种利用分布式节点技术&#xff0c;在全球部署服务器&#xff0c;即时地将网站、应…

《由浅入深学习SAP财务》:第2章 总账模块 - 2.6 定期处理 - 2.6.6 年初操作:科目余额结转

2.6.6 年初操作&#xff1a;科目余额结转 在使用事务代码 FAGLB03 查询科目余额时&#xff0c;可以看到按期间的发生额清单。其中&#xff0c;第一行称为“余额结转”&#xff0c;该行的累计余额代表上年度遗留下来的余额&#xff0c;也就是年初余额。对于资产负债表科目而言&a…

七大设计原则

在软件开发的领域中&#xff0c;随着技术的不断进步和市场需求的不断变化&#xff0c;软件系统的设计和维护变得越来越重要。为了确保软件系统能够长期有效地运行&#xff0c;并且能够在未来的发展中适应新的需求和技术变化&#xff0c;提高软件系统的可维护性和可复用性成为了…

map与set

set使用 set在我们就是我们前面学习的k模型&#xff0c;它可以用来比对数据&#xff0c;增删查的时间复杂度都是O&#xff08;logn&#xff09;效率非常高&#xff0c;由于它底层的原因&#xff0c;它也可以实现排序&#xff0c;通过中序遍历可以输出我们的有序的数据&#xff…

安装gensim报错

安装gensim pip install --upgrade gensim装完以后注意一个 装了一堆库其实&#xff0c;看下对应的scipy版本是1.13.0 然后运行 import gensim报错&#xff1a; cannot import name ‘triu’ from ‘scipy.linalg’ https://www.soinside.com/question/brZ46N5EH7bk9xdVwXa…

华为OD机试 - 内存冷热标记(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

Springboot+Vue项目-基于Java+MySQL的高校心理教育辅导系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

【Linux网络编程】TCP协议

TCP协议 1.TCP协议段格式4位首位长度序号和确认序号16位窗口大小6个标志位 2.确认应答机制3.超时重传机制4.连接管理机制如何理解连接如何理解三次握手如何理解四次挥手 5.流量控制6.滑动窗口7.拥塞控制8.延迟应答9.捎带应答10.面向字节流11.粘包问题12.TCP异常情况13.TCP小结1…

亚马逊全球跨境市场地位稳固,武汉星起航深化服务助力合作伙伴

在全球跨境电商市场的激烈竞争中&#xff0c;亚马逊凭借其强大的市场地位和卓越的平台特点&#xff0c;持续引领着行业的发展潮流。作为行业的领军者&#xff0c;亚马逊不仅占据了全球市场的一大部分&#xff0c;还以其深厚的品牌影响力、广泛的覆盖范围和高效的物流运作&#…

雅虎、乐天、煤炉、国际站、newegg、wish等跨境卖家如何提升店铺销量?深度解析自养号测评的价值

一、如何提升销量&#xff1f; 优化产品描述和图片&#xff1a;确保您的产品描述准确、详细&#xff0c;图片清晰、美观。这将有助于提高产品的吸引力&#xff0c;增加潜在买家的购买意愿。 提供良好的客户服务&#xff1a;及时回复买家的咨询和问题&#xff0c;解决他们的疑…