Docker Compose使用
Docker-Compose是什么
docker建议我们每一个容器中只运行一个服务,因为doker容器本身占用资源极少,所以最好是将每个服务单独分割开来,但是这样我们又面临了一个问题:
如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具。
例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysqI服务容器,redis服务容器,注册中心naocs,甚至还包括负载均衡容器等等。。。
Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project),
可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它使用一个 YAML 文件来配置应用程序的服务,然后使用一个单一的命令部署和启动应用程序的全部服务。
使用 Docker Compose 的主要优势包括:
- 简化容器编排: Compose 允许你在单个配置文件中定义整个应用程序栈,包括不同的服务、网络和存储卷等。这大大简化了容器编排的复杂性。
- 一致的开发环境: Compose 确保开发、测试和生产环境的一致性,因为所有环境都使用相同的 Compose 文件。
- 快速部署: Compose 可以一次性启动应用程序的所有服务,大大加快了部署速度。
- 扩展性: Compose 允许你轻松地扩展应用程序的任何服务。
使用 Docker Compose 的一般流程如下:
- 创建一个
docker-compose.yml文件,定义应用程序的服务。 - 在终端中运行
docker-compose up命令来启动应用程序。 - 运行
docker-compose down命令来停止并删除容器。
Compose 支持多种配置选项,例如指定服务的镜像、端口映射、环境变量、依赖关系等。这使得管理复杂的多容器应用程序变得更加简单和高效。
下载安装
如果你的网很慢,访问不了外网,可以去这里的百度盘直接下载,也包括下面微服务用到的jar包
链接:https://pan.baidu.com/s/1LcwN-LbfKt10ul8d9_-sCA
提取码:wzyy
官网地址
https://docs.docker.com/compose/
在 CentOS 下下载最新版本的 Docker Compose 文件,可以使用以下命令:
curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
这个命令会:
- 使用
curl命令从 GitHub 上下载最新版本的 Docker Compose 文件。 - 将文件保存到
/usr/local/bin/docker-compose目录下。
下载完成后,还需要执行以下命令来赋予可执行权限:
chmod +x /usr/local/bin/docker-compose
这样就可以在 CentOS 系统上使用 docker-compose 命令了。
如果你想确认当前安装的 Docker Compose 版本,可以执行以下命令:
docker-compose --version
这将显示已安装的 Docker Compose 版本信息。
需要注意的是,这个命令下载的是最新版本的 Docker Compose。如果你需要使用特定版本,可以在下载链接中指定版本号,例如:
curl -L https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
这将下载 v2.17.3 版本的 Docker Compose。
执行上述命令
[root@localhost ~]# curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose% Total % Received % Xferd Average Speed Time Time Time CurrentDload Upload Total Spent Left Speed0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 00 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0
100 60.0M 100 60.0M 0 0 156k 0 0:06:33 0:06:33 --:--:-- 570k
[root@localhost ~]# chmod +x /usr/local/bin/docker-compose
[root@localhost ~]# docker-compose --version
Docker Compose version v2.27.0
[root@localhost ~]#
如果想要卸载,执行
rm /usr/local/bin/docker-compose
核心概念
Docker Compose 的核心概念包括以下几点,其中最重要的是
服务、配置文件和工程。可以理解为:通过配置文件 (
docker-compose.yml),将多个服务 (Services),组合成一个工程 (project) 。
- 服务 (
Services): Docker Compose 的基本构建块是服务。一个服务代表一个 Docker 容器,可以包含应用程序、数据库、消息队列等组件。每个服务都有自己的配置,如镜像、端口映射、环境变量等。 - 配置文件 (
docker-compose.yml): 所有的 Compose 配置都定义在一个 YAML 格式的配置文件中,通常命名为docker-compose.yml。该文件描述了整个应用程序的结构,包括各个服务、网络和卷的定义。 - 工程 (
project):在 Docker Compose 中,Project 表示一组相关的服务,它们会被一起管理和部署。docker-compose.yml文件定义了 Project 中的所有服务、网络和卷,同一个 Project 可以包含多个 docker-compose.yml 文件,比如一个用于开发环境、一个用于生产环境。 - 网络 (Networks): Docker Compose 可以自动创建并管理容器之间的网络连接。你可以为不同的服务指定不同的网络,实现容器之间的隔离和通信。
- 卷 (Volumes): Compose 可以管理持久化数据存储,包括创建和挂载卷。这样可以确保数据在容器重启或删除后不会丢失。
- 命令行工具 (docker-compose): Compose 提供了一个命令行工具
docker-compose,可用于管理整个应用程序的生命周期,包括构建、启动、停止、查看日志等操作。 - 扩展性 (Scaling): Compose 支持轻松地水平扩展服务实例的数量,可以根据需求动态增加或减少容器的数量。
- 依赖管理: Compose 会自动处理服务之间的依赖关系,确保先启动依赖服务再启动被依赖服务。
总的来说,Docker Compose 提供了一种声明式的方式来定义和管理整个应用程序的基础设施,使得应用程序的部署和扩展变得更加简单和高效。
使用步骤
- 编写
Dockerfile定义各个微服务应用并构建出对应的镜像文件。 - 使用
docker-compose.yml定义一个完整业务单元,安排好整体应用中的各个容器服务。 - 最后,执行
docker-compose up命令来启动并运行整个应用程序,完成一键部署上线。
常用的命令
Docker Compose 提供了一系列常用的命令,下面是一些常用的命令及其用途:
-
docker-compose up
- 启动并运行整个应用程序
- 可以使用
-d参数在后台运行 - 如果镜像不存在,会自动构建
-
docker-compose down
- 停止并删除整个应用程序
- 包括容器、网络和卷
-
docker-compose ps
列出当前 Project 中正在运行的容器
-
docker-compose build
构建或重新构建服务的镜像
-
docker-compose start/stop/restart
分别启动、停止或重启整个应用程序
-
docker-compose logs 服务id
查看应用程序的日志输出,可以使用
-f参数实时查看日志
-
docker-compose exec 服务id
进入正在运行的容器内部,可以在容器内部执行命令
-
docker-compose config
验证并查看
docker-compose.yml文件的配置docker-compose config -q: 检查配置,只是在出现问题时才会输出信息
-
docker-compose pull:
拉取服务所需的镜像
-
docker-compose scale
动态调整某个服务的容器数量
这些只是 Docker Compose 最常用的一些命令,实际上 Compose 还有更多功能和命令可供使用。
编写配置文件
写一个docker-compose.yml,并进行服务编排
要确保下面配置中,所有的volumes:下面的挂载点目录已存在,不存在要先创建
(注意:目前新版的docker-compose默认可以不用写version了)
services:#自定义的服务名,必须小写eureka7001:#指定dockerfile来构建镜像并运行实例,context用来指定Dockerfile所在的目录build:context: /wzy/cloud-images/eurekadockerfile: Dockerfile#image: eureka_docker:1.0 #如果有现成的镜像,可以在这里指定,直接用来运行容器,使用此项要注释掉build及其内容#container_name: eureka01 指定容器的名字,如果不指定,会由docker自动生成ports:- "7001:7001"#挂载容器卷 volumes:- /wzy/eurekaService:/data #指定使用的网络,所有服务的网络一致,即可以使用服务名通信忽略ip地址 networks:- wzy_net#自定义的服务名,必须小写payment8001:build:context: /wzy/cloud-images/pay8001dockerfile: Dockerfile #image: payment01_docker:1.0#container_name: payment01ports:- "8001:8001"volumes:- /wzy/paymentMysqlService:/data networks:- wzy_net#指定本服务依赖的服务,会等依赖的服务运行后在运行本服务 depends_on:- eureka7001 - mysql #自定义的服务名,必须小写 payment8002:build:context: /wzy/cloud-images/pay8002dockerfile: Dockerfile #image: payment02_docker:1.0#container_name: payment02ports:- "8002:8002"volumes:- /wzy/paymentRedisService:/data networks:- wzy_netdepends_on:- eureka7001- redis #自定义的服务名,必须小写,也可以叫别的,springboot服务可以在yaml中将redis的ip换成这个名字 redis:image: redis:6.2.6ports:- "6379:6379"volumes:- /wzy/redis/redis.conf:/etc/redis/redis.conf- /wzy/redis/data:/data networks:- wzy_net#运行指令 command: redis-server /etc/redis/redis.conf #自定义的服务名,必须小写,也可以叫别的,springboot服务可以在yaml中将redis的ip换成这个名字 mysql:image: mysql:latest#环境参数配置environment:#注意这里的密码要和微服务连接mysql的配置对应上MYSQL_ROOT_PASSWORD: '123456'MYSQL_ALLOW_EMPTY_PASSWORD: 'NO'MYSQL_DATABASE: 'mybatis-plus'MYSQL_USER: 'wzy'MYSQL_PASSWORD: '123456'ports:- "3306:3306"volumes: - /wzy/mysql/log:/var/log/mysql- /wzy/mysql/data:/var/lib/mysql- /wzy/mysql/conf:/etc/mysql/conf.dnetworks:- wzy_netcommand: --default-authentication-plugin=mysql_native_password #解决外部无法访问#创建网络
networks:wzy_net:
微服务展示
除了docker中的redis及mysql之外,这里还用了三个springcloud服务做演示:
- mysql的微服务实现向mysql数据库插入数据
- redis的微服务实现向redis插入数据
- eureka中会注册上面两个微服务
eureka的服务
主要展示配置文件,代码就不展示了,需要的话去上面的下载安装标题处提取
主要是hostname,这里写成了eureka7001,就是上面编排文件的eureka的服务名,因为配置网络后可以直接忽略ip使用服务名,可以解决网络ip变动服务通信失败问题
server:port: 7001eureka:instance:#用docker服务名,不用iphostname: eureka7001client:#表示是否将自己注册进eureka,本moudle本身就是注册中心,不需要注册register-with-eureka: false#表示自己就是注册中心,维护服务实例,其他服务要注册到本moudle中fetch-registry: false#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址service-url:#defaultZone: http://erueka7002.com:7002/eureka #集群配置指向另一个服务注册中心defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置#Eureka自我保护模式:当微服务在默认90秒内不发送心跳给eureka注册中心后,不会立刻抹除微服务得信息server:enable-self-preservation: false #禁用自我保护eviction-interval-timer-in-ms: 5000 #毫秒,设置多少毫秒微服务不可用就剔除
mysql的微服务
sql
代码中要用到的表
CREATE TABLE `number_test` (`one` int NOT NULL,`two` varchar(255) DEFAULT NULL,`three` varchar(255) DEFAULT NULL,`four` varchar(255) DEFAULT NULL,PRIMARY KEY (`one`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
ymal
数据库
datasource的url处使用编排文件的服务名,eureka的service-url的defaultZone用编排文件中erueka注册中心的服务名
server:port: 8001spring:application:name: cloud-payment-servicedatasource:driver-class-name: com.mysql.cj.jdbc.Driver#mysql:3306,使用docker服务名,不用ipurl: jdbc:mysql://mysql:3306/mybatis-plus?nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: wzypassword: 123456mybatis-plus:mapper-locations: classpath:/mapper/*Mapper.xmleureka:client:#表示是否将自己注册进eurekaregister-with-eureka: true#是否从eurekaServer抓取已有注册信息,默认为true。单点无所谓,集群必须设置true才能配合Ribbon使用负载均衡fetchRegistry: true#入驻的eureka服务地址service-url:#############使用docker服务名,不用ip#############defaultZone: http://eureka7001:7001/eureka #单机版#defaultZone: http://erueka7001.com:7001/eureka,http://erueka7002.com:7002/eureka #集群版#配置eureka前台界面服务名字的status名字显示instance:instance-id: payment8001prefer-ip-address: true #访问路径可以显示ip地址#Eureka客户端向服务端发送心跳的时间间隔,单位秒lease-renewal-interval-in-seconds: 10#Eureka服务端在收到最后一次心跳后等待时间上限,单位秒(默认是90秒),超时将认为服务不可用lease-expiration-duration-in-seconds: 20
Controller
@RestController
@RequestMapping("ntest")
public class NumberTestController {@Autowiredprivate NumberTestService numberTestService;@GetMapping("save")public boolean insertTest(){NumberTest test = new NumberTest();test.setOne(1);test.setTwo("2");test.setThree("3");test.setFour("4");return numberTestService.save(test);}}
访问地址
http://localhost:8001/ntest/save
redis的微服务
yaml
host处使用编排redis的服务名,因为本微服务要连接docker的redis容器
server:port: 8002spring:application:name: cloud-payment-serviceredis:#使用docker服务名,不用iphost: redisport: 6379lettuce:shutdown-timeout: 0 # 连接超时时间(毫秒)pool:max-active: 8max-wait: -1max-idle: 500min-idle: 0eureka:client:#表示是否将自己注册进eurekaregister-with-eureka: true#是否从eurekaServer抓取已有注册信息,默认为true。单点无所谓,集群必须设置true才能配合Ribbon使用负载均衡fetchRegistry: true#入驻的eureka服务地址service-url:#############使用docker服务名,不用ip#############defaultZone: http://eureka7001:7001/eureka #单机版#defaultZone: http://erueka7001.com:7001/eureka,http://erueka7002.com:7002/eureka #集群版#配置eureka前台界面服务名字的status名字显示instance:instance-id: payment8002prefer-ip-address: true #访问路径可以显示ip地址
config
/*** SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。* 但是,这个RedisTemplate的泛型是<Object,Object>,写代码不方便,需要写好多类型转换的代码;* 我们需要一个泛型为<String,Object>形式的RedisTemplate。* 并且,这个默认的RedisTemplate没有设置数据存在Redis时,key及value的序列化方式。如果不序列化,写入redis会报错** */
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();template.setConnectionFactory(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// key采用String的序列化方式,此处为除hash外其他的类型全部做设置template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jacksontemplate.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jacksontemplate.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}
controller
@RestController
@RequestMapping("payment")
public class payment {@Autowiredprivate RedisTemplate redisTemplate;@GetMapping("/redis")public void setCacheObject() {redisTemplate.opsForValue().set("test-key", "test-value");}
}
访问地址
http://localhost:8002/payment/redis
编写Dockerfile
没有写mysql与redis的Dockerfile,因为如果本地没有镜像会自动拉取,我这里复用了以前的镜像,详细安装请参考本专栏的docker安装应用部分:
https://blog.csdn.net/onePlus5T/article/details/139102535
构建eureka的Dockerfile,连同jar包放入编排文件指定的/wzy/cloud-images/eureka目录中
#基础镜像使用java
FROM java:8#作者
MAINTAINER wzy#VOLUME指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp#将jar包添加到容器中并更名为wzy_eureka.jar
ADD cloud-eureka-server-1.0-SNAPSHOT.jar wzy_eureka.jar# 运行jar包
RUN bash -c 'touch /wzy_eureka.jar'
ENTRYPOINT ["java","-jar","/wzy_eureka.jar"]#暴露7001端口,因为上面的代码的端口也是7001
EXPOSE 7001
构建mysql微服务-8001的Dockerfile,连同jar包放入编排文件指定的/wzy/cloud-images/pay8001目录中
#基础镜像使用java
FROM java:8#作者
MAINTAINER wzy#VOLUME指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp#将jar包添加到容器中并更名为wzy_payment8001.jar
ADD cloud-provider-payment8001-1.0-SNAPSHOT.jar wzy_payment8001.jar# 运行jar包
RUN bash -c 'touch /wzy_payment8001.jar'
ENTRYPOINT ["java","-jar","/wzy_payment8001.jar"]#暴露8001端口,因为上面的代码的端口也是8001
EXPOSE 8001
构建redis微服务-8002的Dockerfile,连同jar包放入编排文件指定的/wzy/cloud-images/pay8002目录中
#基础镜像使用java
FROM java:8#作者
MAINTAINER wzy#VOLUME指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp#将jar包添加到容器中并更名为wzy_payment8002.jar
ADD cloud-provider-payment8002-1.0-SNAPSHOT.jar wzy_payment8002.jar# 运行jar包
RUN bash -c 'touch /wzy_payment8002.jar'
ENTRYPOINT ["java","-jar","/wzy_payment8002.jar"]#暴露8002端口,因为上面的代码的端口也是8002
EXPOSE 8002
运行编排
无论将 docker-compose.yml 文件放在哪里,只要确保在执行 Docker Compose 命令时,能正确地指定 Compose 文件的路径即可。比如:
docker-compose -f /wzy/docker-compose.yml up -d
再执行前,可以检查编排配置文件是否有问题,如果执行如下命令没有如何输出,就是没问题 (这里建议先去yaml在线格式化网站校验一下):
docker-compose config -q
这里建议将docker相关内容进行统一存放,我就是存放在了wzy的路径,直接运行:
[root@localhost wzy]# docker-compose config -q
[root@localhost wzy]# docker-compose -f /wzy/docker-compose.yml up -d
[+] Building 35.9s (20/20) FINISHED docker:default=> [eureka7001 internal] load build definition from Dockerfile 0.1s=> => transferring dockerfile: 579B 0.0s=> [payment8002 internal] load metadata for docker.io/library/java:8 30.8s=> [eureka7001 internal] load .dockerignore 0.0s=> => transferring context: 2B 0.0s=> [eureka7001 internal] load build context 0.3s=> => transferring context: 48.86MB 0.3s=> CACHED [payment8002 1/3] FROM docker.io/library/java:8@sha256:c1ff613e8ba258 0.0s=> [eureka7001 2/3] ADD cloud-eureka-server-1.0-SNAPSHOT.jar wzy_eureka.jar 0.3s=> [eureka7001 3/3] RUN bash -c 'touch /wzy_eureka.jar' 1.0s=> [eureka7001] exporting to image 0.2s=> => exporting layers 0.2s=> => writing image sha256:7927120cce252cd5db9ac32eca62c814f6f9005029a9585b9927 0.0s=> => naming to docker.io/library/wzy-eureka7001 0.0s=> [payment8001 internal] load build definition from Dockerfile 0.0s=> => transferring dockerfile: 606B 0.0s=> [payment8002 internal] load build definition from Dockerfile 0.0s=> => transferring dockerfile: 606B 0.0s=> [payment8002 internal] load .dockerignore 0.0s=> => transferring context: 2B 0.0s=> [payment8001 internal] load .dockerignore 0.0s=> => transferring context: 2B 0.0s=> [payment8001 internal] load build context 0.5s=> => transferring context: 66.18MB 0.5s=> [payment8002 internal] load build context 0.5s=> => transferring context: 60.94MB 0.5s=> [payment8001 2/3] ADD cloud-provider-payment8001-1.0-SNAPSHOT.jar wzy_paymen 0.5s=> [payment8002 2/3] ADD cloud-provider-payment8002-1.0-SNAPSHOT.jar wzy_paymen 0.6s=> [payment8001 3/3] RUN bash -c 'touch /wzy_payment8001.jar' 0.9s=> [payment8002 3/3] RUN bash -c 'touch /wzy_payment8002.jar' 0.7s=> [payment8001] exporting to image 0.3s=> => exporting layers 0.3s=> => writing image sha256:983970a54834e6e04ad037f12e5623fd43fc270d5358173ab8a9 0.0s=> => naming to docker.io/library/wzy-payment8001 0.0s=> [payment8002] exporting to image 0.3s=> => exporting layers 0.3s=> => writing image sha256:f9ba7c533f0efb7138d0906c10c26a66b4bd3bb73d79317dbd8d 0.0s=> => naming to docker.io/library/wzy-payment8002 0.0s
[+] Running 6/6✔ Network wzy_wzy_net Created 0.9s ✔ Container wzy-eureka7001-1 Started 1.2s ✔ Container wzy-redis-1 Started 1.5s ✔ Container wzy-mysql-1 Started 1.6s ✔ Container wzy-payment8001-1 Started 4.7s ✔ Container wzy-payment8002-1 Started
[root@localhost wzy]#
以上全部Started就是成功。
注意:上面编排后生成的名字有一些变化,比如redis服务名变成了wzy-redis-1,这是在没有指定名字的情况下docker自己加的,并不影响使用
建表
这时,mysql会根据编排文件自动建立mybatis-plus库,但并不会自动建表:
[root@localhost wzy]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
afe3ca78cc28 wzy-payment8002 "java -jar /wzy_paym…" 8 seconds ago Up 4 seconds 0.0.0.0:8002->8002/tcp, :::8002->8002/tcp wzy-payment8002-1
6e169d6e50de wzy-payment8001 "java -jar /wzy_paym…" 8 seconds ago Up 4 seconds 0.0.0.0:8001->8001/tcp, :::8001->8001/tcp wzy-payment8001-1
490549ec53e8 wzy-eureka7001 "java -jar /wzy_eure…" 8 seconds ago Up 6 seconds 0.0.0.0:7001->7001/tcp, :::7001->7001/tcp wzy-eureka7001-1
2d9e86240ee2 mysql:latest "docker-entrypoint.s…" 20 hours ago Up 6 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp wzy-mysql-1
d8f5e56fde6d redis:6.2.6 "docker-entrypoint.s…" 20 hours ago Up 6 seconds 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp wzy-redis-1
[root@localhost wzy]# docker exec -it 2d9e86240ee2 /bin/bash
root@2d9e86240ee2:/# mysql -u wzy -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.27 MySQL Community Server - GPLCopyright (c) 2000, 2021, Oracle and/or its affiliates.Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mybatis-plus |
+--------------------+
2 rows in set (0.01 sec)mysql> use mybatis-plus;
Database changed
mysql> select * from number_test;
ERROR 1146 (42S02): Table 'mybatis-plus.number_test' doesn't exist
mysql>
我们需要手动建表,不然8001服务执行新增会报错:
mysql> CREATE TABLE `number_test` (-> `one` int NOT NULL,-> `two` varchar(255) DEFAULT NULL,-> `three` varchar(255) DEFAULT NULL,-> `four` varchar(255) DEFAULT NULL,-> PRIMARY KEY (`one`)-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Query OK, 0 rows affected (0.05 sec)mysql> select * from number_test;
Empty set (0.10 sec)mysql>
验证
宿主机直接访问我的虚拟机erueka,可以看到有应用列表有8001与8002,二者成功注册到eureka中

或者直接虚拟机里看:

执行8001的controller,插入数据


验证8002-redis服务
先看所有的key,这是没有:
[root@localhost wzy]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0bb97a880a91 wzy-payment8001 "java -jar /wzy_paym…" 22 minutes ago Up 22 minutes 0.0.0.0:8001->8001/tcp, :::8001->8001/tcp wzy-payment8001-1
918f761ead06 wzy-payment8002 "java -jar /wzy_paym…" 22 minutes ago Up 22 minutes 0.0.0.0:8002->8002/tcp, :::8002->8002/tcp wzy-payment8002-1
2d9e86240ee2 mysql:latest "docker-entrypoint.s…" 22 minutes ago Up 22 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp wzy-mysql-1
d8f5e56fde6d redis:6.2.6 "docker-entrypoint.s…" 22 minutes ago Up 22 minutes 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp wzy-redis-1
240276cd95f1 wzy-eureka7001 "java -jar /wzy_eure…" 22 minutes ago Up 22 minutes 0.0.0.0:7001->7001/tcp, :::7001->7001/tcp wzy-eureka7001-1[root@localhost wzy]# docker exec -it d8f5e56fde6d /bin/bash
root@d8f5e56fde6d:/data# redis-cli
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379>
然后虚拟机中请求:

再查看redis:

注意点
如果遇到问题需要重新编排,或者修改了微服务的yaml配置或代码,要记得将镜像与容器一并删除,在重新编排。
相关文章:
Docker Compose使用
Docker-Compose是什么 docker建议我们每一个容器中只运行一个服务,因为doker容器本身占用资源极少,所以最好是将每个服务单独分割开来,但是这样我们又面临了一个问题: 如果我需要同时部署好多个服务,难道要每个服务单独写Docker…...
如何优雅的卸载linux上的todesk
要优雅地卸载Linux上的ToDesk,您可以按照以下步骤操作: 打开终端。 输入以下命令来停止ToDesk服务(如果它正在运行的话): sudo systemctl stop todesk 然后,使用包管理器卸载ToDesk。如果您使用的是apt&…...
【Vue】el-checkbox多选框实现单选效果,选中一个选项则自动取消其他勾选
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回&#…...
Linux中使用vi编辑器自动缩进4个字符
平常在Linux操作系统下书写shell脚本内容,或是把写好的shell内容直接复制到vi编辑器中,本来缩进好的字符,会自动变乱,这是因为Linux的vi编辑器默认是缩进8个字符造成,可以使用下面2个方法解决该问题的发生。 1、本用户…...
#笔记#笔记#其他
大鱼论文是一款非常靠谱、方便、值得推荐的论文写作工具。无论是在学术研究中还是在日常写作中,大鱼论文都能够帮助用户轻松完成论文的写作工作。 首先,大鱼论文提供了强大的查重降重功能,能够帮助用户快速定位论文中可能存在的抄袭问题&…...
gtask笔记
1、创建Task GTask *g_task_new (gpointer source_object, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer callback_data); source_object:GObject对象,拥有者 cancellable:可否取消 callback:task完成后…...
【Linux学习】深入探索进程等待与进程退出码和退出信号
文章目录 退出码return退出 进程的等待进程等待的方法 退出码 main函数的返回值:进程的退出码。 一般为0表示成功,非0表示失败。 每一个非0退出码都表示一个失败的原因; echo $?命令 作用:查看进程退出码。…...
Linux:线程
文章目录 前言1. 线程概念1.1 什么是线程1.2 线程比进程更加轻量化1.3 虚拟地址到物理地址的转化物理内存的管理页表 1.4 线程的优点1.5 线程的缺点1.6 线程异常1.7 线程用途 2. 进程 vs 线程3. 线程控制3.1 线程创建3.2 线程退出3.3 线程等待3.4 分离线程3.5 线程取消 4. 线程…...
卡到BUG了:删除重发白得积分(以前删除会扣减积分)
以前是:删除文章,积分减少,点赞积分减少,从回收站恢复文章,积分恢复,点赞数恢复但点赞积分不恢复。也就是删除重发总积分减少点赞的积分,有损失。 今天是:删除文章,积分不…...
轻松拿捏C语言——【字符函数】字符分类函数、字符转换函数
🥰欢迎关注 轻松拿捏C语言系列,来和 小哇 一起进步!✊ 🌈感谢大家的阅读、点赞、收藏和关注💕 🌹如有问题,欢迎指正 感谢 目录👑 一、字符分类函数🌙 二、字符转换函数…...
【Rust日报】ratatui版本更新
[new ver] ratatui v0.26.3 一个构建终端用户界面的库。新版本包括: 修复Unicode 截断 bug对颜色更好地序列化更快的渲染弃用assert_buffer_eq宏暴露错误类型常量函数和类型 官网: https://ratatui.rs/ 链接: https://ratatui.rs/highlights/v0263/ [new lib] ansi2…...
力扣每日一题 5/28
题目:2951-找出峰值 给你一个下标从 0 开始的数组 mountain 。你的任务是找出数组 mountain 中的所有 峰值。 以数组形式返回给定数组中 峰值 的下标,顺序不限 。 注意: 峰值 是指一个严格大于其相邻元素的元素。数组的第一个和最后一个元…...
async函数和await函数
一、async函数 async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。 因此对async函数可以直接then,返回值就是then方法传入的函数。 // async基础语法 async function fun0(){console.log(1);return 1; } fun0()…...
Redis面试题深度解析
1、我看你做的项目中,都用到了redis,你在最近的项目中哪些场景使用了redis呢? 2、缓存穿透 布隆过滤器的误判现象 Redisson和Guava都对布隆过滤器进行了实现 3、缓存击穿 互斥锁,就是一个线程来修改,并占据了锁,另外其…...
Ubuntu 22.04 .NET8 程序 环境安装和运行
前言 我们需要将.NET8编写的console控制台程序,部署在Ubuntu服务器上运行。 安装.NET运行时 1.增加微软包安装源 wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb sudo dpkg -i packages…...
MetaRTC-ffmpeg arm移植
touch cmake_arm.sh 添加 rm -rf build mkdir build cd build ARCHaarch64.cmake cmake -DCMAKE_BUILD_TYPERelease -DCMAKE_TOOLCHAIN_FILE../$ARCH .. maketouch cmake_arm.sh 添加 SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_C_COMPILER /home/yqw/MetaRTC/BC/stbgcc-6.3-1…...
【乐吾乐3D可视化组态编辑器】模型类型与属性
编辑器地址:3D可视化组态 - 乐吾乐Le5le 本章主要为您介绍模型的属性功能。 一个模型至少会包含一个节点(Node),从节点类型上可以分为转换节点(TransformNode)、网格(Mesh)、实例网…...
PyQt下拉框QComboBox点击下拉时即更新下拉数据
在 PyQt 中,QComboBox 控件本身并没有直接的事件或信号来指示下拉列表何时被打开(即用户点击了下拉箭头)。但是,你可以通过其他方式间接地实现这个功能,比如通过重写 QComboBox 的某些方法或者在用户与 QComboBox 交互…...
网上有哪些正规的兼职副业赚钱平台?分享10类正规的网上兼职赚钱平台,让你在家也能赚钱~
在如今的快节奏社会中,越来越多的人开始寻求兼职副业来增加收入。而随着互联网的普及,网上赚钱平台成为了许多人选择的方式之一。然而,面对众多的网上赚钱平台,我们要如何辨别哪些是正规可靠的呢?在本文中,…...
Spring:JWT
文章目录 一、介绍 一、介绍 JWT(JSON Web Token)是一种开放标准(RFC 7519)的方法,用于在双方之间安全地传输信息。这些信息可以是验证、授权、信息交换等。JWT 通常被用于在客户端和服务器之间传递用户信息ÿ…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
