一、项目结构
我这里准备了一个微服务项目。
里面包含三个服务模块:
card-service
、use-rservice
以及网关gateway
。
一个公共模块:
fegin-api
。
其中fegin-api
被card-service
和user-service
引用。
二、基于项目构建部署目录结构
这个springcloud-app
目录中的全部内容,之后就是要上传到服务上进行部署的源文件。
springcloud-app
一级目录下包含了放gateway
、card-service
、user-service
三个微服务的文件夹。
一个放mysql
数据和配置文件的文件夹。
以及一个dockercompose
配置文件。
关于它们的详解如下。
2.1 gateway目录构建详解
在我提供的项目中,gateway
、card-service
、user-service
都属于微服务,构建方式是一样的。
这里就以gateway
为例,解析怎么构建文件目录。
1)进入gateway目录:
里面只有一个我提前写好的Dockerfile
文件。
要使用Docker
构建镜像肯定是需要编写Dockerfile
,在其中编写构建规则的。
2)打开Dockerfile文件:
里面只需要三句话即可。
# 指定java:8-alpine作为基础镜像,它包含了java程序部署的基本环境依赖
FROM java:8-alpine
# 把当前目录下的javaApp.jar移动到/soft目录下
COPY ./javaApp.jar /soft/javaApp.jar
# 程序运行入口,就是java项目的启动命令
# 这句话也是容器成功运行后,第一个执行的命令
ENTRYPOINT java -jar /soft/javaApp.jar
card-service
、use-rservice
两个文件夹下的内容和gateway
中的一致。
并且Dockerfile
文件的内容也一样。因为它们三种都是基于java
开发的微服务,构建镜像的方式都是一致的。
2.2 mysql 目录构建详解
由于所有微服务都是使用的mysql
数据库。
这样也就涉及到了Docker
中运行mysql
容器。
而为了mysql
数据和配置的可移植性和可维护性。一般都会进行数据卷挂载或者磁盘挂载。
把自定义的mysql
配置合并到容器中,以及把容器内被隔离的mysql
数据与宿主机进行关联。
1)conf目录
hmy.cnf
中存放着自定义mysql
配置。可以是字符集配置,主从复制中的配置等等等。
如果暂时没有自定义配置,最好也先挂载上。由于容器启动后无法再挂载新的数据卷或者磁盘。
如果第一次不挂载,今后再想给mysql
添加配置。
就只能删除容器再重新运行镜像生成新容器时再去挂载配置文件了。
2)data目录
里面包含着mysql
数据库服务器下存放的所有数据库的数据。这些数据都以二进制文件的形式存储在本地磁盘。
每个电脑存放mysql
本地二进制表格数据的位置不同,一般是安装的时候自己设定的。
只有找到那个文件夹,把需要的数据库二进制文件复制进来即可。
这个目录和容器磁盘进行挂载后,里面的数据会直接覆盖mysql
容器中的数据。
之后容器中mysql
的数据发生变化之后,也会同步更新到宿主机本地磁盘中的对应位置。
也就是说这里的data
目录里的对应文件,也会随之修改。这属于Docker
的基础知识了。
2.3 dcoker-compose.yml文件详解
# Compose 文件格式有3个版本,分别为1, 2.x 和 3.x
# 目前主流的为 3.x 其支持 docker 1.13.0 及其以上的版本
version: "3.0"
services: # 具体的服务定义
nacos: # nacos配置 nacos也是未来naocs服务的容器名称
image: nacos/nacos-server # nacos镜像名称
environment: # nacos环境变量
MODE: standalone # MODE相当于之前命令行的-m参数,指代运行模式。
# standalone单机运行(如果有nacos集群就不是这么写了)
ports: # 端口映射
- "8848:8848" # 把宿主机8848端口和nacos容器的8848端口相关联
mysql: # mysql配置 mysql也是未来mysql服务的容器名称
image: mysql:5.7.25 # mysql镜像名称
environment: # mysql环境变量
MYSQL_ROOT_PASSWORD: root # mysql密码为root
volumes: # 数据卷挂载配置
- "$PWD/mysql/data:/var/lib/mysql"
# 宿主/mysql/data目录挂载到器/var/lib/mysql目录
- "$PWD/mysql/conf:/etc/mysql/conf.d/"
# 宿主/mysql/conf目录挂载到器/etc/mysql/conf.d/目录
# $PWD 代表运行Linux的pwd命令,获取当前文件的路径
# 这样可以确保在Linux中任意位置都能找到/mysql/conf目录
ports: # 端口映射
- "3306:3306" # 把宿主机3306端口和mysql容器的3306端口相关联
userservice: # userservice微服务配置 userservice也是未来微服务的容器名称
build: ./user-service # 代表在当前目录下的user-service目录下构建userservice镜像
cardservice: # cardservice微服务配置 cardservice也是未来微服务的容器名称
build: ./card-service # 代表在当前目录下的card-service目录下构建cardservice镜像
gateway: # gateway微服务配置 gateway也是未来微服务的容器名称
build: ./gateway # 代表在当前目录下的gateway目录下构建gateway镜像
ports: # 端口映射
- "9999:9999" # 把宿主机9999端口和gateway容器的9999端口相关联
关于mysql端口映射的说明:
mysql
只在微服务集群内部进行访问,只需要在userservice
和cardservice
的application.yml
文件中。
把mysql
的注册中心的地址,由ip
格式改为dcoker-compose.yml
文件中配置的服务命名称即可。
compose-file
文件的官方文档:
https://docs.docker.com/compose/compose-file/
自定义的微服务配置可以在这里找配置怎么写。
像nacos
这种地三方镜像,就去它们对应的官网或者dockerHub
上看看。
三、准备各个微服务的jar包
这里主要涉及了三个微服务userservice
和cardservice
和gateway
。
在打jar
包前,需要先修改配置文件。
修改各个微服务的application.yml
文件或者bootstrap.yml
文件中的mysql
和nacos
的地址配置。
由ip
格式改为dcoker-compose.yml
文件中配置的服务命名称。
这是因为使用dcoker-compose
配置时。
所有的服务之间都可以直接使用dcoker-compose.yml
文件中配置的服务命名称来访问对方。
这里就以打包user-service这个模块为例。
3.1 修改mysql和nacos地址
1)修改bootstrap.yml文件
# 把红框处的localhost改为dcoker-compose.yml文件中配置的nacos
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: nacos:8848 # Nacos地址
config: # discovery 代表注册中心配置 config代表配置中心配置
file-extension: yaml # 文件后缀名
2)修改application.yml
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://mysql:3306/cloud_user?useSSL=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
card-service和gateway模块中的配置也按上面的方式修改即可。
3.2 在pom.xml文件中添加打包插件
<!-- finalName中的配置就能确定打出来的jar包是什么名称 -->
<!-- plugins中配置的就是常规的maven打包插件 -->
<build>
<finalName>javaApp</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.3 使用Idea的Maven打包工具打包微服务
点击右侧Maven
工具栏的package
即可。
打包完成后到对应模块的target
目录下获取jar
包。
card-service和gateway模块的jar包也按上面的方式打出来即可,jar包名字都叫javaApp。
四、把jar包复制到springdata-app下的对应子目录中
以user-service
为例。
在idea
中的user-service
模块下,找到target
目录。
把打好的jar
包复制到springdata-app
目录下的userservice
目录里。
card-service和gateway模块的jar包也按上面的方式制到springdata-app下的对应子目录中。
五、使用finallshell上传文件夹到服务器
可以选择任意自己想放的位置。只要便于查找即可。
六、compose相关命令
1)部署命令
# 对命令不熟悉可以查看命令文档
docker-compose --help
# docker-compose 是有非常多命令选项参数的,这里涉及到的两个
# up 创建并启动一个容器
# -d 后台运行
docker-compose up -d
2)停止命令
docker-compose stop
3)停止并删除
docker-compose down
4)重启
docker-compose restart
# 重启某些具体服务的写法
docker-compose restart gateway userservice
5)查看日志
docker-compose logs
# 查看具体的服务日志
# -f 持续更新日志变化,按ctrl+c可以结束
docker-compose logs -f userservice
上述都是常用命令,还有更多操作,不一一列举。
使用docker-compose --help就能知道所有docker-compose的用法。
七、具体部署操作
1)进入springdata-app文件目录
# 这个位置看自己把东西放哪,是不固定的
cd /usr/local/composrApp
2)执行部署命令
docker-compose up -d
3)部署后查看日志
docker-compose logs
4)部署问题解决方案
首次部署时日志中会出现如下错误:
主要是因为nacos
容器启动速度比其他依赖nacos
的微服务慢。
其它微服务已经启动了却连接不上nacos
,也获取不到nacos
中的配置信息。
解决方案:重启所有依赖nacos的微服务
docker-compose restart gateway userservice cardservice
重启完成后查看cardservice的日志
docker-compose logs -f cardservice
发现新出现的日志已经没有任何错误了。
八、基于自定义的jdk镜像部署微服务(推荐)
上面的方式有的人可能会觉得繁琐,每个微服务都有一个单独的文件夹,而且里面都有一个Dockerfile
文件。
确实文件有点多。
还有一种方法可以让所有jar
包放在一个文件夹中,并且不需要这么多重复的Dockerfile
文件。
越来越多人也会选用这种方式来部署,并且这种方式,未来如果使用portainer
管理docker
时会很容易移植。
具体选择哪种方式,可以结合自己实际情况决定。
1)新建存放目录和文件
# 进入目录/usr/local/
cd /usr/local
# 新建app目录
mkdir app
# 新建Dockerfile文件
touch Dockerfile
存放位置可以根据部署需求自行指定
2)编写Dockerfile文件
# 构建镜像,执行命令:【docker build -t openjdk:8 .】
FROM openjdk:8u212-jre # 基础镜像
MAINTAINER xxx # 作者
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
ENTRYPOINT ["java", "-server", "-Xms512M", "-Xmx512M", "-Djava.security.egd=file:/dev/./urandom", "-Dfile.encoding=UTF-8", "-XX:+HeapDumpOnOutOfMemoryError", "-jar", "/app/app.jar" ]
3)使用Dockerfile文件构建一个openjdk镜像
docker build -t openjdk:8 .
4)编写docker-compose.yml文件
version: '3'
services:
mysql:
image: mysql:8
container_name: gddst-mysql-dev
environment:
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=89225300
- MYSQL_DATABASE=nacos_config
- MYSQL_USER=gddst
- MYSQL_PASSWORD=123456
ports:
- "3306:3306"
volumes:
- /usr/local/workspace/mysql/data:/var/lib/mysql
- /usr/local/workspace/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
nacos:
image: nacos/nacos-server:v2.1.1-slim
container_name: gddst-nacos-dev
environment:
- MODE=standalone
- PREFER_HOST_MODE=hostname
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=89225300
- MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
ports:
- "8848:8848"
- "9848:9848"
- "9555:9555"
volumes:
- /usr/local/workspace/nacos/logs:/home/nacos/logs
- /usr/local/workspace/nacos/data:/home/nacos/data
depends_on:
- mysql
gateway:
image: openjdk:8
container_name: gateway
ports:
- 8080:8080
environment:
- nacos_host=nacos
- nacos_port=8848
volumes:
- /usr/local/workspace/app/gddst-cloud-gateway.jar:/app/app.jar
userservice:
image: openjdk:8
container_name: userservice
environment:
- nacos_host=nacos
- nacos_port=8848
volumes:
- /usr/local/workspace/app/userservice.jar:/app/app.jar
depends_on:
- mysql
- nacos
cardservice:
image: openjdk:8
container_name: cardservice
environment:
- nacos_host=nacos
- nacos_port=8848
volumes:
- /usr/local/workspace/app/cardservice.jar:/app/app.jar
depends_on:
- mysql
- nacos
如文件中所示:
执行编排容器命令时,会创建一个mysql
、nacos
、userservice
、cardservice
四个容器。
其中userservice
、cardservice
是自己编写的基于SpringBoot
的微服务项目。
这里的部署配置会复杂一些,和文章上部分有所不同,更偏向于实际开发。
按照这个配置,微服务中的pom
文件中mysql
的依赖需要改成8
的版本,同时yml
文件的驱动也需要更改。
这些都属于项目基本配置,就不再这里缀述了。
这样编写docker-compose.yml
有一些明显的好处:
- 更容易管理每个微服务的端口、容器名称、环境变量、数据卷等何种参数,可维护性是大大提升的
- 不再需要把每个微服务的
jar
搞成一样的名字,可以通过直接看jar
包名称就知道是哪个微服务了 - 不再有那么多重复的
Dockerfile
文件 - 今后部署只有在
docker-compose.yml
中按userservice
新增一项配置,并且把它的jar
包上传到/usr/local/app
下即可
5)上传需要部署的jar文件
根据docker-compose
的配置内容,把网关和业务模块所的jar
包,
即gddst-cloud-gateway.jar
、userservice.jar
、cardservice.jar
的三个jar
包上传到以下目录:
/usr/local/workspace/app/
6)执行部署命令
在docker-compose.yml
文件所在目录下执行:
docker-compose up -d
即可完成部署。
写这步更多的是为了这套步骤的完整性、实际一般会使用
portainer
来进行微服务的可视化部署管理
九、拓展
1)关于能否在一个文件中配置多个相同服务的问题
关于userservice
和cardservice
在一个dcoker-compose.yml
文件里也是可以配置多个的。
只需要打出不同端口号的jar
包即可。
包括mysql
也是,这里只使用了一个,是最简单的格式。即使以后有了主从复制,也可以配置多个mysql
。
这样就能完成一个更完善一些的集群配置。
2)关于fegin-api模块为什么不需要部署
fegin-api
模块只是一个公共模块,被其它微服务所引用。
使用Maven
打包SpringBoot
项目的时候,有关的Maven
依赖会自动打包进当前微服务项目的jar
包中。
也就是说,每个依赖了fegin-api
模块的微服务的jar
包中内部,就已经有了fegin-api
模块的内容。