Docker 学习笔记 - 进阶四 Docker网络和 Docker compose

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose

  • 4. docker 网络
    • 4.1 docker network是什么
      • 4.1.1 docker不启动,默认网络情况
      • 4.1.2 docker启动后,网络情况
    • 4.2 docker network 常用基本命令
      • 4.2.1 全部 network 命令
      • 4.2.2 查看网络: docker network ls
      • 4.2.3 创建和删除网络:
      • 4.2.3 查看网络源数据
    • 4.3 docker network 能解决什么问题
    • 4.4 docker network 的网络模式
      • 4.4.1 总体介绍
      • 4.4.2 容器实例内默认网络IP生产规则
        • 4.4.2.1 先启动两个ubuntu容器实例
        • 4.4.2.2 查看容器ip
      • 4.4.3 docker network 实例说明
        • 4.4.3.1 bridge
          • 4.4.3.1.1 是什么
          • 4.4.3.1.2 bridge的解释
          • 4.4.3.1.3 脚本及验证
        • 4.4.3.2 host
          • 4.4.3.2.1 是什么
          • 4.4.3.2.2 脚本及验证
          • 4.4.3.2.3 如何访问
        • 4.4.3.3 none
          • 4.4.3.3.1 是什么
          • 4.4.3.3.2 案例
        • 4.4.3.4 container
          • 4.4.3.4.1 是什么
          • 4.4.3.4.1 案例
        • 4.4.3.5 自定义网络
          • 4.4.3.5.1 不用自定义网络之前
          • 4.4.3.5.2 使用自定义网络之后
          • 4.4.3.5.3 结论
    • 4.5 Docker平台架构图解
      • 4.5.1 整体说明
      • 4.5.2 整体架构图
  • 5. Docker compose 容器编排
    • 5.1 是什么
    • 5.2 能干吗
    • 5.3 docker compose 下载安装
      • 5.3.1 官网下载地址
      • 5.3.2 下载安装
    • 5.4 docker compose 核心概念
      • 5.4.1 文件: docker-compose.yml
      • 5.4.2 要素:
    • 5.5 Compose使用的三个步骤
    • 5.6 Compose常用命令
    • 5.7 Compose编排微服务(重要)
      • 5.7.1 升级改造微服务工程docker-boot
        • 5.7.1.1 基础版位置
        • 5.7.1.2 MySql 建表建库
        • 5.7.1.3 pom文件
        • 5.7.1.4 yaml 文件
        • 5.7.1.5 主启动类
        • 5.7.1.6 配置类
        • 5.7.1.7 beans
        • 5.7.1.8 mapper(dao)
        • 5.7.1.9 service and serviceImpl
        • 5.7.1.10 controller
        • 5.7.1.11 测试微服务工程
        • 5.7.1.12 本地测试 swagger UI
      • 5.7.2 上面成功了,有哪些问题?
      • 5.7.3 使用 docker compose
        • 5.7.3.1 编写 docker-compose.yaml 文件
        • 5.7.3.2 第二次修改 spring-boot 微服务文件
          • 5.7.3.2.1 yaml 文件
          • 5.7.3.2.2 build jar 包并上传
          • 5.7.3.2.3 构建新镜像 v1.2 版本
          • 5.7.3.2.4 执行docker compose
          • 5.7.3.2.4 进入mysql容器实例并新建库db2021+新建表t_user
          • 5.7.3.2.5 测试
        • 5.7.3.3 docker compose 常用命令
        • 5.7.3.4 关停服务

笔记记录学习尚硅谷周阳老师的 docker 教程
链接地址: https://www.bilibili.com/video/BV1gr4y1U7CY?p=1

4. docker 网络

4.1 docker network是什么

4.1.1 docker不启动,默认网络情况

[root@vm001 admin]# ifconfig
ens33: flags=4163  mtu 1500
        inet 192.168.226.128  netmask 255.255.255.0  broadcast 192.168.226.255
        inet6 fe80::8805:f678:285c:a5c0  prefixlen 64  scopeid 0x20
        ether 00:0c:29:e7:21:88  txqueuelen 1000  (Ethernet)
        RX packets 258  bytes 67570 (65.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 140  bytes 16053 (15.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 48  bytes 4080 (3.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 48  bytes 4080 (3.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:ff:4f:c6  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 1). ens33: linux 宿主机的地址
  • 2). lo: local, 本地地址
  • 3). virbr0: 在CentOS7的安装过程中如果有选择相关虚拟化的的服务安装系统后,启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡(virbr0网卡:它还有一个固定的默认IP地址192.168.122.1),是做虚拟机网桥的使用的,其作用是为连接其上的虚机网卡提供 NAT访问外网的功能。
    Linux安装在勾选安装系统的时候附带了libvirt服务才会生成的一个东西,如果不需要可以直接将libvirtd服务卸载,
yum remove libvirt-libs.x86_64

4.1.2 docker启动后,网络情况

会产生一个名为docker0的虚拟网桥

## 启动 docker
[root@vm001 admin]# systemctl start docker
[root@vm001 admin]# docker images
REPOSITORY                                                    TAG          IMAGE ID       CREATED         SIZE
orderservice6001                                              v1.1         f5c5e0bb8815   22 hours ago    685MB
## 查询 ip网络信息
[root@vm001 admin]# ifconfig
docker0: flags=4163  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:f5ff:fea1:eede  prefixlen 64  scopeid 0x20
        ether 02:42:f5:a1:ee:de  txqueuelen 0  (Ethernet)
        RX packets 31  bytes 2658 (2.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 52  bytes 18674 (18.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
## 其余省略

查看docker网络模式命令:docker network ls
--------- 默认创建三大网络模式

[root@vm001 admin]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
3f6c87b881bb   bridge    bridge    local
2e4dd2180dd1   host      host      local
4fdddc082793   none      null      local
[root@vm001 admin]# 

4.2 docker network 常用基本命令

4.2.1 全部 network 命令

[root@vm001 admin]# docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

4.2.2 查看网络: docker network ls

在4.1.2 中有

4.2.3 创建和删除网络:

创建: docker network create

[root@vm001 admin]# docker network create aa_network
e810395831b1e5069e447c6730df76917dbb981c82e5519970c3d33965f463f3
[root@vm001 admin]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
e810395831b1   aa_network   bridge    local
3f6c87b881bb   bridge       bridge    local
2e4dd2180dd1   host         host      local
4fdddc082793   none         null      local

删除: docker network rm

[root@vm001 admin]# docker network rm aa_network 
aa_network
[root@vm001 admin]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
3f6c87b881bb   bridge    bridge    local
2e4dd2180dd1   host      host      local
4fdddc082793   none      null      local

4.2.3 查看网络源数据

docker network inspect XXX网络名字
如: docker network inspect bridge
显示出来的就是上面看到的 docker0 那个网桥

[root@vm001 admin]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
3f6c87b881bb   bridge    bridge    local
2e4dd2180dd1   host      host      local
4fdddc082793   none      null      local
[root@vm001 admin]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "3f6c87b881bbceedca34897b2fa0794a52269d10de7dd0c84ab694a927325c5d",
        "Created": "2022-05-09T23:32:21.056937312+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "b014f0b061b4c39c5d13cfdcbc38e4cbb64cbb8c5939ba4fa2385cbd5628165b": {
                "Name": "suspicious_keldysh",
                "EndpointID": "1677be925e9c7c04a5a1651f48c16f62b7efca13d96c34e6c82c4607c0dd84f7",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "e2ddfc2abe317482bac74809279e91bbd91a55cbdc2a842720317993d0b1c091": {
                "Name": "zk01",
                "EndpointID": "304da47bd4bb8e0dafca3ebda522b5587e5d301a30e060dab9ce2c1ab56ab9a7",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "f27be7bd716acb811fd9d28fa4809e19a60c88db9cceefddafb3eae65a113ee8": {
                "Name": "consul",
                "EndpointID": "6d3d9798c592807b3c9a9a817d536ce860a28c455e69ccf1340216d0342f461e",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

4.3 docker network 能解决什么问题

在单机模式不明显,但是在公司,需要作docker网络管理和容器调用之间的规划。
需要考虑使用常见的网络桥接模式还是其他模式等问题

  • 1). 容器间的互联和通信以及端口映射
  • 2). 容器IP变动时候可以通过服务名直接网络通信而不受到影响

4.4 docker network 的网络模式

4.4.1 总体介绍

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第1张图片
bridge模式:使用–network bridge指定,默认使用docker0
host模式:使用–network host指定
none模式:使用–network none指定
container模式:使用–network container:NAME或者容器ID指定

4.4.2 容器实例内默认网络IP生产规则

4.4.2.1 先启动两个ubuntu容器实例

[root@vm001 admin]# docker run -it --name ub1 ubuntu bash
# 启动后, 使用 ctrl + p + q 退出,容器仍然运行
root@e46ea4e05596:/# [root@vm001 admin]# 
# 启动后, 使用 ctrl + p + q 退出,容器仍然运行
[root@vm001 admin]# docker run -it --name ub2 ubuntu bash
root@67a5ade74ae2:/# [root@vm001 admin]# 
[root@vm001 admin]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                                                         NAMES
67a5ade74ae2   ubuntu         "bash"                   7 seconds ago    Up 5 seconds                                                                                                  ub2
e46ea4e05596   ubuntu         "bash"                   44 seconds ago   Up 43 seconds 

4.4.2.2 查看容器ip

命令:docker inspect 容器ID or 容器名字

docker inspect ub1 | tail -n 20
docker inspect ub2 | tail -n 20

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第2张图片
关闭ub2实例,新建ub3,查看ip变化
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第3张图片
所以: docker容器内部的ip是有可能会发生改变的

4.4.3 docker network 实例说明

4.4.3.1 bridge

4.4.3.1.1 是什么

Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

# 查看 bridge 网络的详细信息,并通过 grep 获取名称项
# docker network inspect bridge | grep name
[root@vm001 admin]# docker network inspect bridge | grep name
            "com.docker.network.bridge.name": "docker0",
# ifconfig
[root@vm001 admin]# ifconfig | grep docker
docker0: flags=4163  mtu 1500
4.4.3.1.2 bridge的解释
1 Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),
Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,
称为Container-IP,同时Docker网桥是每个容器的默认网关。
因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

2 docker run 的时候,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。
在宿主机ifconfig,就可以看到docker0和自己create的network(后面讲)eth0,eth1,eth2……代表网卡一,网卡二,网卡三……,
lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址

3 网桥docker0创建一对对等虚拟设备接口一个叫veth,另一个叫eth0,成对匹配。
   3.1 整个宿主机的网桥模式都是docker0,类似一个交换机有一堆接口,每个接口叫veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
   3.2 每个容器实例内部也有一块网卡,每个接口叫eth0;
   3.3 docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配。

通过上述,将宿主机上的所有容器都连接到这个内部网络上,
两个容器在同一个网络下,会从这个网关下各自拿到分配的ip,
此时两个容器的网络是互通的。

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第4张图片

4.4.3.1.3 脚本及验证
[root@vm001 admin]# docker run -d -p 8081:8080   --name tomcat81 billygoo/tomcat8-jdk8
76e19d0cdaa03641ac807e5d03abcb4424428736a116946bb21aa5d74f55ffd8
[root@vm001 admin]# docker run -d -p 8082:8080   --name tomcat82 billygoo/tomcat8-jdk8
e776f5f5c02c39042c52914a06f8e4db4c8c4e5f44211a2228cc1dc47fb46b2e
[root@vm001 admin]# docker ps
CONTAINER ID   IMAGE                   COMMAND             CREATED          STATUS          PORTS                                       NAMES
e776f5f5c02c   billygoo/tomcat8-jdk8   "catalina.sh run"   3 seconds ago    Up 2 seconds    0.0.0.0:8082->8080/tcp, :::8082->8080/tcp   tomcat82
76e19d0cdaa0   billygoo/tomcat8-jdk8   "catalina.sh run"   12 seconds ago   Up 11 seconds   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp   tomcat81

两两验证:
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第5张图片

4.4.3.2 host

4.4.3.2.1 是什么

直接使用宿主机的 IP 地址与外界进行通信,不再需要额外进行NAT 转换。

4.4.3.2.2 脚本及验证
  • 1). 带警告的代码

docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8

[root@vm001 admin]# docker run -d -p 8083:8080 --network host --name tomcat83 billygoo/tomcat8-jdk8
WARNING: Published ports are discarded when using host network mode
a9fcd26d8aafbb37047b43aee7aaad6a5dfea4cc5fb6a4c7906cf3f90f2a8f8a
[root@vm001 admin]# docker ps
## 能启动,但是没有 port信息
CONTAINER ID   IMAGE                   COMMAND             CREATED          STATUS          PORTS                                       NAMES
a9fcd26d8aaf   billygoo/tomcat8-jdk8   "catalina.sh run"   47 seconds ago   Up 46 seconds                                               tomcat83
问题:
     docker 启动时总是遇见标题中的警告
原因:
    docker启动时指定--network=host或-net=host,如果还指定了-p映射端口,那这个时候就会有此警告,
并且通过-p设置的参数将不会起到任何作用,端口号会以主机端口号为主,重复时则递增。

解决:
    解决的办法就是使用docker的其他网络模式,例如--network=bridge,这样就可以解决问题,或者直接无视。。。
  • 2). 正确脚本
    docker run -d --network host --name tomcat83 billygoo/tomcat8-jdk8
    使用 --network host 时不指定端口号
[root@vm001 admin]# docker run -d --network host  --name tomcat83 billygoo/tomcat8-jdk8
b037a62b81fe56471e6280ec30e11610a5675fd1495a6a8eb0ef6aaa4305e2ee
[root@vm001 admin]# docker ps
CONTAINER ID   IMAGE                   COMMAND             CREATED          STATUS          PORTS                                       NAMES
b037a62b81fe   billygoo/tomcat8-jdk8   "catalina.sh run"   3 seconds ago    Up 3 seconds                                                tomcat83

此时就不会有容器的配对显示了

## 查看容器实例内部, 可以看到网关和IPAddress 都是空的
[root@vm001 admin]# docker inspect tomcat83 | tail -n 20
            "Networks": {
                "host": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "2e4dd2180dd1aadc6d206a836e91965a6a6cea23f31d83374e006a414723d96a",
                    "EndpointID": "fffa8c63bb68c239f94dec596c719a26562e2ad8c24edf05ad5fa9858a99f70b",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
            }
        }
    }
]

4.4.3.2.3 如何访问

没有设置-p的端口映射了,如何访问启动的tomcat83呢

在CentOS里面用默认的火狐浏览器访问容器内的tomcat83看到访问成功,因为此时容器的IP借用主机的,

所以容器共享宿主机网络IP,这样的好处是外部主机与容器可以直接通信。
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第6张图片
在容器外部访问也成功
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第7张图片

4.4.3.3 none

4.4.3.3.1 是什么

在none模式下,并不为Docker容器进行任何网络配置。

也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo
需要我们自己为Docker容器添加网卡、配置IP等。

结果: 禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)

4.4.3.3.2 案例

Networks 为空

[root@vm001 admin]# docker run -d -p 8084:8080 --network none  --name tomcat84 billygoo/tomcat8-jdk8
e137ca5aca6647b49537692c492be6d749cf7205b81d9db9196771c36025a126
[root@vm001 admin]# docker inspect tomcat84 |tail -n 20
            "Networks": {
            ## none
                "none": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "4fdddc0827933ee2d823ae0dac5ff6af1cc671d0b2790146213ae9d82290c27d",
                    "EndpointID": "d66ad5e927d8bf1815b944e2ea226ef80ab7f146ccb62e32e607f1a194116da8",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
            }
        }
    }
]

且容器内部只有 lo, 即localhost

[root@vm001 admin]# docker exec -it tomcat84 /bin/bash
root@e137ca5aca66:/usr/local/tomcat# ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
root@e137ca5aca66:/usr/local/tomcat# 

4.4.3.4 container

4.4.3.4.1 是什么

container⽹络模式:
新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第8张图片

4.4.3.4.1 案例

不适合使用 tomcat进行演示:

docker run -d -p 8085:8080  							--name tomcat85 billygoo/tomcat8-jdk8
docker run -d -p 8086:8080 --network container:tomcat85 --name tomcat85 billygoo/tomcat8-jdk8

因为相当于tomcat86和tomcat85公用同一个ip同一个端口,导致tomcat端口冲突

使用Alpine:
Alpine操作系统是一个面向安全的轻型 Linux发行版

docker run -it                              --name alpine1  alpine /bin/sh
docker run -it --network container:alpine1  --name alpine2  alpine /bin/sh
## 能够看到两个容器的 network是一样的
[root@vm001 admin]# docker exec -it alpine1 /bin/sh
/ # ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
30: eth0@if31:  mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # exit
[root@vm001 admin]# docker exec -it alpine2 /bin/sh
/ # ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
30: eth0@if31:  mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 

此时如果关闭 alpine1, 那么alpine2 只有lo,
30: eth0@if31消失了

/ # ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

4.4.3.5 自定义网络

利用自定义网络更好地进行网络互联

4.4.3.5.1 不用自定义网络之前

docker run -d -p 8081:8080 --name tomcat81 billygoo/tomcat8-jdk8
docker run -d -p 8082:8080 --name tomcat82 billygoo/tomcat8-jdk8
上述成功启动并用docker exec进入各自容器实例内部

按照ip 互相ping对方的地址是可以的:

[root@vm001 admin]# docker exec -it tomcat81 /bin/bash
root@76e19d0cdaa0:/usr/local/tomcat# ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
24: eth0@if25:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@76e19d0cdaa0:/usr/local/tomcat# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.103 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.083 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.103 ms
[root@vm001 admin]# docker exec -it tomcat82 /bin/bash
root@e776f5f5c02c:/usr/local/tomcat# ip addr
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
26: eth0@if27:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
root@e776f5f5c02c:/usr/local/tomcat# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.100 ms

按照服务名ping 会出现问题:

root@76e19d0cdaa0:/usr/local/tomcat# ping tomcat82
ping: tomcat82: Name or service not known


root@e776f5f5c02c:/usr/local/tomcat# ping tomcat81
ping: tomcat81: Name or service not known
4.4.3.5.2 使用自定义网络之后

自定义桥接网络,自定义网络默认使用的是桥接网络bridge

  • 1). 新建自定义网络 cc_network
[root@vm001 admin]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
60050306e695   bridge    bridge    local
2e4dd2180dd1   host      host      local
4fdddc082793   none      null      local
[root@vm001 admin]# docker network create cc_network
4d59aa365f0fac6313112676e313de65259ffadd31f46abf86be255440bf8e2d
[root@vm001 admin]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
60050306e695   bridge       bridge    local
4d59aa365f0f   cc_network   bridge    local
2e4dd2180dd1   host         host      local
4fdddc082793   none         null      local
  • 2). 新建容器加入上一步新建的自定义网络
[root@vm001 admin]# docker run -d -p 8081:8080 --network cc_network   --name tomcat81 billygoo/tomcat8-jdk8
4d56fd03e06047be5ac3135df7cf885c0d3c4df8340b2f1026f4da42ae459d20
[root@vm001 admin]# docker run -d -p 8082:8080 --network cc_network   --name tomcat82 billygoo/tomcat8-jdk8
940da1af2795cfb22e2a39300f2740b7faf0ad805d7061c5c23218870865b858
[root@vm001 admin]# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                                         NAMES
940da1af2795   billygoo/tomcat8-jdk8   "catalina.sh run"        4 seconds ago    Up 3 seconds    0.0.0.0:8082->8080/tcp, :::8082->8080/tcp                                                     tomcat82
4d56fd03e060   billygoo/tomcat8-jdk8   "catalina.sh run"        11 seconds ago   Up 10 seconds   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp                                                     tomcat81
  • 3). 互相 ping 对方, 成功
[root@vm001 admin]# docker exec -it tomcat81 /bin/bash
#### 81 ping 82
root@4d56fd03e060:/usr/local/tomcat# ping tomcat82
PING tomcat82 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat82.cc_network (172.18.0.3): icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from tomcat82.cc_network (172.18.0.3): icmp_seq=2 ttl=64 time=0.110 ms
^C
--- tomcat82 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.076/0.093/0.110/0.017 ms
root@4d56fd03e060:/usr/local/tomcat# exit
exit
[root@vm001 admin]# docker exec -it tomcat82 /bin/bash
#### 82 ping 81
root@940da1af2795:/usr/local/tomcat# ping tomcat81
PING tomcat81 (172.18.0.2) 56(84) bytes of data.
64 bytes from tomcat81.cc_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from tomcat81.cc_network (172.18.0.2): icmp_seq=2 ttl=64 time=0.068 ms
^C
--- tomcat81 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.058/0.063/0.068/0.005 ms
4.4.3.5.3 结论

自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)
自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)
自定义网络本身就维护好了主机名和ip的对应关系(ip和域名都能通)

4.5 Docker平台架构图解

4.5.1 整体说明

从其架构和运行流程来看,Docker 是一个 C/S 模式的架构,
后端是一个松耦合架构,众多模块各司其职。 

Docker 运行的基本流程为:

1 用户是使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者。

2 Docker Daemon 作为 Docker 架构中的主体部分,首先提供 Docker Server 
的功能使其可以接受 Docker Client 的请求。

3 Docker Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 
的形式的存在。

4 Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,
并通过镜像管理驱动 Graph driver将下载镜像以Graph的形式存储。

5 当需要为 Docker 创建网络环境时,通过网络管理驱动 Network driver 
创建并配置 Docker 容器网络环境。

6 当需要限制 Docker 容器运行资源或执行用户指令等操作时,
则通过 Execdriver 来完成。

7 Libcontainer是一项独立的容器管理包,Network driver以及Exec driver
都是通过Libcontainer来实现具体对容器进行的操作。

4.5.2 整体架构图

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第9张图片

5. Docker compose 容器编排

5.1 是什么

Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器

Docker-Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。

就跟spring的 applicationContext.xml 对bean的管理类似,docker compose实现对容器的管理编排
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第10张图片

5.2 能干吗

docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,
所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?

如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,
构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署
的工具

例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端
的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容
器等等。。。。。。

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来
定义一组相关联的应用容器为一个项目(project)。

可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个
应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理
编排的问题。

5.3 docker compose 下载安装

5.3.1 官网下载地址

## 官网:https://docs.docker.com/compose/compose-file/compose-file-v3/

## 官网下载地址:https://docs.docker.com/compose/install/

docker compose 与 docker 版本匹配
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第11张图片

5.3.2 下载安装

参考:https://docs.docker.com/compose/install/

 apt-get update
 apt-get install docker-compose-plugin

或者老师的笔记

yum install docker-compose-plugin

# curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# chmod +x /usr/local/bin/docker-compose

结果:

[root@vm001 bin]# yum install docker-compose-plugin
已加载插件:fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: mirrors.dgut.edu.cn
 * extras: mirrors.dgut.edu.cn
 * updates: mirrors.dgut.edu.cn
软件包 docker-compose-plugin-2.5.0-3.el7.x86_64 已安装并且是最新版本
无须任何处理

[root@vm001 admin]# docker compose version
Docker Compose version v2.5.0
[root@vm001 admin]# chmod +x /usr/local/bin/docker-compose

命令列表:

[root@vm001 bin]# docker compose --help

Usage:  docker compose [OPTIONS] COMMAND

Docker Compose

Options:
      --ansi string                Control when to print ANSI control characters ("never"|"always"|"auto") (default "auto")
      --compatibility              Run compose in backward compatibility mode
      --env-file string            Specify an alternate environment file.
  -f, --file stringArray           Compose configuration files
      --profile stringArray        Specify a profile to enable
      --project-directory string   Specify an alternate working directory
                                   (default: the path of the Compose file)
  -p, --project-name string        Project name

Commands:
  build       Build or rebuild services
  convert     Converts the compose file to platform's canonical format
  cp          Copy files/folders between a service container and the local filesystem
  create      Creates containers for a service.
  down        Stop and remove containers, networks
  events      Receive real time events from containers.
  exec        Execute a command in a running container.
  images      List images used by the created containers
  kill        Force stop service containers.
  logs        View output from containers
  ls          List running compose projects
  pause       Pause services
  port        Print the public port for a port binding.
  ps          List containers
  pull        Pull service images
  push        Push service images
  restart     Restart containers
  rm          Removes stopped service containers
  run         Run a one-off command on a service.
  start       Start services
  stop        Stop services
  top         Display the running processes
  unpause     Unpause services
  up          Create and start containers
  version     Show the Docker Compose version information

5.4 docker compose 核心概念

5.4.1 文件: docker-compose.yml

5.4.2 要素:

  • 1). 服务(service)
    一个一个的应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器
  • 2). 工程(project)
    由一组关联的应用容器组成的一个完整业务单元,在​docker-compose.yaml 文件中定义。

5.5 Compose使用的三个步骤

Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第12张图片

1). 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
	
2). 使用 docker-compose.yml​ 定义一个完整业务单元,安排好整体应用中
	的各个容器服务。

3). 最后,执行docker-compose up命令​来启动并运行整个应用程序,
	完成一键部署上线

5.6 Compose常用命令

docker-compose -h                           # 查看帮助

docker-compose up                           # 启动所有docker-compose服务

docker-compose up -d                        # 启动所有docker-compose服务并后台运行

docker-compose down                         # 停止并删除容器、网络、卷、镜像。

docker-compose exec  yml里面的服务id                 # 进入容器实例内部  docker-compose exec docker-compose.yml文件中写的服务id /bin/bash

docker-compose ps                      # 展示当前docker-compose编排过的运行的所有容器

docker-compose top                     # 展示当前docker-compose编排过的容器进程

 

docker-compose logs  yml里面的服务id     # 查看容器输出日志

docker-compose config     # 检查配置

docker-compose config -q  # 检查配置,有问题才有输出

docker-compose restart   # 重启服务

docker-compose start     # 启动服务

docker-compose stop      # 停止服务

5.7 Compose编排微服务(重要)

5.7.1 升级改造微服务工程docker-boot

结构:
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第13张图片

5.7.1.1 基础版位置

https://blog.csdn.net/BogerPeng/article/details/124601243

5.7.1.2 MySql 建表建库

create database db2021;
go

use db2021;
CREATE TABLE `t_user` (

  `id` int(10) NOT NULL AUTO_INCREMENT,
	
  `username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',

  `password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',

  `sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',

  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',

  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'

5.7.1.3 pom文件



    
        UTF-8
        1.8
        1.8
        4.12
        1.2.17
        1.16.18
        5.1.47
        1.1.16
        4.1.5
        1.3.0
    

    
        
        
            com.google.guava
            guava
            23.0
        
        
        
            org.redisson
            redisson
            3.13.4
        
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
        
            io.springfox
            springfox-swagger2
            2.9.2
        
        
            io.springfox
            springfox-swagger-ui
            2.9.2
        
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
        
            org.springframework.boot
            spring-boot-starter-cache
        
        
        
            org.apache.commons
            commons-pool2
        
        
        
            redis.clients
            jedis
            3.1.0
        
        
        
            mysql
            mysql-connector-java
            8.0.19
        
        
        
            com.alibaba
            druid-spring-boot-starter
            1.1.16
        
        
            com.alibaba
            druid
            ${druid.version}
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
        
        









        
        
        
            cn.hutool
            hutool-all
            5.2.3
        
        
            junit
            junit
            ${junit.version}
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            log4j
            log4j
            ${log4j.version}
        
        
            org.projectlombok
            lombok
            ${lombok.version}
            true
        
        
        
            javax.persistence
            persistence-api
            1.0.2
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    true
                
                
                    
                        
                            
                            repackage
                        
                    
                
            
            
                org.apache.maven.plugins
                maven-resources-plugin
                3.1.0
            
        
    

5.7.1.4 yaml 文件

server:
  port: 6001
# ========================alibaba.druid相关配置=====================
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.226.128:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false
#          jdbc:mysql://192.168.226.129:3306/seata_order?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    druid:
      test-while-idle: false
# ========================swagger=====================
  swagger2:
    enabled: true
# ========================redis相关配置=====================
  redis:
    database: 0
    host: 192.168.226.128
    port: 6379    # 6381
    ## redis 密码在 redis.conf 文件中指定
    password: 123456
    lettuce:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0
    #cluster:
    #  nodes: 192.168.226.128:6381,192.168.226.128:6382,192.168.226.128:6383,192.168.226.128:6384,192.168.226.128:6385,192.168.226.128:6386
# ========================mybatis plus相关配置===================
mybatis-plus:     #myBatis plus的配置文件位置
  mapper-locations: classpath*:mybatis/mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true

5.7.1.5 主启动类

package com.pyh.springcloud;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.pyh.springcloud.dao")
public class DockerBootApplication {
    public static void main(String[] args){
        SpringApplication.run(DockerBootApplication.class, args);
    }
}

5.7.1.6 配置类

RedisConfig:

package com.pyh.springcloud.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;

@Configuration
@Slf4j
public class RedisConfig {
    /**
     * @param lettuceConnectionFactory
     * @return
     *
     * redis序列化的工具配置类,下面这个请一定开启配置
     * 127.0.0.1:6379> keys *
     * 1) "ord:102"  序列化过
     * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
     */
    @Bean
    public RedisTemplate<String, Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Serializable> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

SwaggerConfig:

package com.pyh.springcloud.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.text.SimpleDateFormat;
import java.util.Date;

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Value("${spring.swagger2.enabled}")
    private Boolean enabled;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .enable(enabled)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.pyh.springcloud")) //你自己的package
                .paths(PathSelectors.any())
                .build();
    }

    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Docker compose example"+"\t"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
                .description("docker-compose")
                .version("1.0")
                .termsOfServiceUrl("https://www.xxx.com/")
                .build();
    }
}

MyDataSourceConfig:

package com.pyh.springcloud.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.sql.SQLException;

//@Deprecated
@Configuration      //引入了druid-spring-boot-starter之后,可以不需要该配置
public class MyDataSourceConfig {

    @Value("${mybatis-plus.mapper-locations}")
    private String mapperLocations;

    //    @ConfigurationProperties("spring.datasource")
    @ConfigurationProperties(prefix = "spring.datasource")  // 与上面相同
    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        return druidDataSource;

    }

    //代理mybaits-plus
    @Bean
    public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
        return sqlSessionFactoryBean;
    }
}

5.7.1.7 beans

User:

package com.pyh.springcloud.beans;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User
{

    @TableId(type = IdType.AUTO) // id 自增长
    private Integer id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 性别 0=女 1=男
     */
    private Byte sex;
    /**
     * 删除标志,默认0不删除,1删除
     */
    private Byte deleted;
    /**
     * 更新时间
     */
    @Column(name = "update_time")
    private Date updateTime;
    /**
     * 创建时间
     */
    @Column(name = "create_time")
    private Date createTime;
    /**
     * @return id
     */
    public Integer getId() {
        return id;
    }
    /**
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }
    /**
     * 获取用户名
     * @return username - 用户名
     */
    public String getUsername() {
        return username;
    }
    /**
     * 设置用户名
     * @param username 用户名
     */
    public void setUsername(String username) {
        this.username = username;
    }
    /**
     * 获取密码
     * @return password - 密码
     */
    public String getPassword() {
        return password;
    }
    /**
     * 设置密码
     * @param password 密码
     */
    public void setPassword(String password) {
        this.password = password;
    }
    /**
     * 获取性别 0=女 1=男
     * @return sex - 性别 0=女 1=男
     */
    public Byte getSex() {
        return sex;
    }
    /**
     * 设置性别 0=女 1=男
     * @param sex 性别 0=女 1=男
     */
    public void setSex(Byte sex) {
        this.sex = sex;
    }
    /**
     * 获取删除标志,默认0不删除,1删除
     * @return deleted - 删除标志,默认0不删除,1删除
     */
    public Byte getDeleted() {
        return deleted;
    }
    /**
     * 设置删除标志,默认0不删除,1删除
     * @param deleted 删除标志,默认0不删除,1删除
     */
    public void setDeleted(Byte deleted) {
        this.deleted = deleted;
    }
    /**
     * 获取更新时间
     * @return update_time - 更新时间
     */
    public Date getUpdateTime() {
        return updateTime;
    }
    /**
     * 设置更新时间
     * @param updateTime 更新时间
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    /**
     * 获取创建时间
     * @return create_time - 创建时间
     */
    public Date getCreateTime() {
        return createTime;
    }
    /**
     * 设置创建时间
     * @param createTime 创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}

UserDTO:

package com.pyh.springcloud.beans;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(value = "用户信息")
public class UserDTO implements Serializable
{
    @ApiModelProperty(value = "用户ID")
    private Integer id;
    @ApiModelProperty(value = "用户名")
    private String username;
    @ApiModelProperty(value = "密码")
    private String password;
    @ApiModelProperty(value = "性别 0=女 1=男 ")
    private Byte sex;
    @ApiModelProperty(value = "删除标志,默认0不删除,1删除")
    private Byte deleted;
    @ApiModelProperty(value = "更新时间")
    private Date updateTime;
    @ApiModelProperty(value = "创建时间")
    private Date createTime;
    /**
     * @return id
     */
    public Integer getId() {
        return id;
    }
    /**
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }
    /**
     * 获取用户名
     * @return username - 用户名
     */
    public String getUsername() {
        return username;
    }
    /**
     * 设置用户名
     * @param username 用户名
     */
    public void setUsername(String username) {
        this.username = username;
    }
    /**
     * 获取密码
     * @return password - 密码
     */
    public String getPassword() {
        return password;
    }
    /**
     * 设置密码
     * @param password 密码
     */
    public void setPassword(String password) {
        this.password = password;
    }
    /**
     * 获取性别 0=女 1=男
     * @return sex - 性别 0=女 1=男
     */
    public Byte getSex() {
        return sex;
    }
    /**
     * 设置性别 0=女 1=男
     * @param sex 性别 0=女 1=男
     */
    public void setSex(Byte sex) {
        this.sex = sex;
    }
    /**
     * 获取删除标志,默认0不删除,1删除
     * @return deleted - 删除标志,默认0不删除,1删除
     */
    public Byte getDeleted() {
        return deleted;
    }
    /**
     * 设置删除标志,默认0不删除,1删除
     * @param deleted 删除标志,默认0不删除,1删除
     */
    public void setDeleted(Byte deleted) {
        this.deleted = deleted;
    }
    /**
     * 获取更新时间
     * @return update_time - 更新时间
     */
    public Date getUpdateTime() {
        return updateTime;
    }
    /**
     * 设置更新时间
     * @param updateTime 更新时间
     */
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
    /**
     * 获取创建时间
     * @return create_time - 创建时间
     */
    public Date getCreateTime() {
        return createTime;
    }
    /**
     * 设置创建时间
     * @param createTime 创建时间
     */
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", sex=" + sex +
                '}';
    }
}

5.7.1.8 mapper(dao)

Mapper:

package com.pyh.springcloud.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pyh.springcloud.beans.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * mybatis plus中,继承BaseMapper,就可以拥有基础的CRUD方法
 */
@Mapper
public interface UserDao extends BaseMapper<User> {
}

UserMapper.xml:
路径:src/main/resources/mybatis/mapper/UserMapper.xml


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.pyh.springcloud.dao.UserDao">
    <resultMap id="BaseResultMap" type="com.pyh.springcloud.beans.User">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="username" jdbcType="VARCHAR" property="username" />
        <result column="password" jdbcType="VARCHAR" property="password" />
        <result column="sex" jdbcType="TINYINT" property="sex" />
        <result column="deleted" jdbcType="TINYINT" property="deleted" />
        <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    resultMap>
mapper>

5.7.1.9 service and serviceImpl

UserService:

package com.pyh.springcloud.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.pyh.springcloud.beans.User;

public interface UserService extends IService<User> {
    void addUser(User user);
    User findUserById(Integer id);
    int updateUser(User user);
    void deleteUser(Integer id);
}

UserServiceImpl:

package com.pyh.springcloud.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pyh.springcloud.beans.User;
import com.pyh.springcloud.dao.UserDao;
import com.pyh.springcloud.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    public static final String CACHE_KEY_USER = "user:";

    @Resource
    private UserDao userMapper;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * addUser
     * @param user
     */
    public void addUser(User user)
    {
        //1 先插入mysql并成功
        int i = userMapper.insert(user);
        if(i > 0)
        {
            //2 需要再次查询一下mysql将数据捞回来并ok
            user = userMapper.selectById(user.getId());
            //3 将捞出来的user存进redis,完成新增功能的数据一致性。
            String key = CACHE_KEY_USER+user.getId();
            redisTemplate.opsForValue().set(key,user);
        }
    }

    /**
     * findUserById
     * @param id
     * @return
     */
    public User findUserById(Integer id)
    {
        User user = null;
        String key = CACHE_KEY_USER+id;

        //1 先从redis里面查询,如果有直接返回结果,如果没有再去查询mysql
        user = (User) redisTemplate.opsForValue().get(key);

        if(user == null)
        {
            //2 redis里面无,继续查询mysql
            user = userMapper.selectById(id);
            if(user == null)
            {
                //3.1 redis+mysql 都无数据
                //具体细化,防止多次穿透,我们规定,记录下导致穿透的这个key回写redis
                return user;
            }else{
                //3.2 mysql有,需要将数据写回redis,保证下一次的缓存命中率
                redisTemplate.opsForValue().set(key,user);
            }
        }
        return user;
    }

    public int updateUser(User user){
        return userMapper.updateById(user);
    }

    public void deleteUser(Integer id){
        userMapper.deleteById(id);
    }
}

5.7.1.10 controller

package com.pyh.springcloud.controller;

import cn.hutool.core.util.IdUtil;
import com.pyh.springcloud.beans.User;
import com.pyh.springcloud.beans.UserDTO;
import com.pyh.springcloud.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Random;

@Api("用户User接口")
@RestController
@Slf4j
public class UserController {
    @Resource
    private UserService userService;

    @ApiOperation("数据库新增3条记录")
    @RequestMapping(value = "/user/add",method = RequestMethod.POST)
    public void addUser()
    {
        for (int i = 1; i <=3; i++) {
            User user = new User();

            user.setUsername("pyh"+i);
            user.setPassword(IdUtil.simpleUUID().substring(0,6));
            user.setSex((byte) new Random().nextInt(2));

            userService.addUser(user);
        }
    }

    @ApiOperation("删除1条记录")
    @RequestMapping(value = "/user/delete/{id}",method = RequestMethod.POST)
    public void deleteUser(@PathVariable Integer id)
    {
        userService.deleteUser(id);
    }

    @ApiOperation("修改1条记录")
    @RequestMapping(value = "/user/update",method = RequestMethod.POST)
    public void updateUser(@RequestBody UserDTO userDTO)
    {
        User user = new User();
        BeanUtils.copyProperties(userDTO,user);
        userService.updateUser(user);
    }

    @ApiOperation("查询1条记录")
    @RequestMapping(value = "/user/find/{id}",method = RequestMethod.GET)
    public User findUserById(@PathVariable Integer id)
    {
        return userService.findUserById(id);
    }
}

5.7.1.11 测试微服务工程

postman add user:
在这里插入图片描述
数据库:
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第14张图片
浏览器 find user:
在这里插入图片描述
post man delete user:
在这里插入图片描述
在这里插入图片描述

5.7.1.12 本地测试 swagger UI

URL: http://localhost:6001/swagger-ui.html
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第15张图片
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第16张图片
能够成功调用接口

5.7.2 上面成功了,有哪些问题?

  • 1). 先后顺序要求固定,先mysql+redis才能微服务访问成功
  • 2). 多个run命令…
  • 3). 容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错,要么生产IP写死(可以但是不推荐),要么通过服务调用

5.7.3 使用 docker compose

服务编排,一套即可完成

5.7.3.1 编写 docker-compose.yaml 文件


version: "3"

services:
  microService:
    image: orderservice6001:v1.2
    container_name: ms01
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks: 
      - cc_network 
    depends_on: 
      - redis
      - mysql

  redis:
  # 不带版本号表示最新版本, 如果带版本号也要写上,如 redis:6.0.8
    image: redis
    ports:
      - "6379:6379"
    volumes:
     - /app/redis/redis.conf:/etc/redis/redis.conf
     - /app/redis/data:/data
    networks: 
      - cc_network
    command: redis-server /etc/redis/redis.conf

  mysql:
    image: mysql:8.0.27
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'db2021'
      MYSQL_USER: 'pyh'
      MYSQL_PASSWORD: 'pyh123'
    ports:
       - "3306:3306"
    volumes:
       - /app/mysql/db:/var/lib/mysql
       - /app/mysql/conf/my.cnf:/etc/my.cnf
       - /app/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - cc_network
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问

networks: 
   cc_network: 
   

5.7.3.2 第二次修改 spring-boot 微服务文件

5.7.3.2.1 yaml 文件

通过服务名访问,与IP无关
服务名由docker-compose.yaml 文件指定

spring:
  datasource:
    ## url: jdbc:mysql://192.168.226.128:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false
    url: jdbc:mysql://mysql:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false
  redis:
    ## host: 192.168.226.128
    host: redis
5.7.3.2.2 build jar 包并上传

参照 docker 进阶三笔记的 4.2 小节,build jar包:
URL: https://blog.csdn.net/BogerPeng/article/details/124601243

## 上传到linux宿主机的相同目录下
[root@vm001 dockertest20220516]# pwd
/dockerfiles/dockertest20220516
[root@vm001 dockertest20220516]# ll
总用量 57172
-rw-r--r--. 1 root root 58534184 5月  16 17:29 docker-boot-1.0-SNAPSHOT.jar
-rw-r--r--. 1 root root     1173 5月  16 17:06 docker-compose.yaml
-rw-r--r--. 1 root root      478 5月  16 15:12 Dockerfile
5.7.3.2.3 构建新镜像 v1.2 版本
[root@vm001 dockertest20220516]# docker build -t orderservice6001:v1.2 .
Sending build context to Docker daemon  58.54MB
Step 1/7 : FROM java:8
 ---> d23bdf5b1b1b

######## 其他日志略--省点文章长度

Step 7/7 : EXPOSE 6001
 ---> Running in 224851e72012
Removing intermediate container 224851e72012
 ---> 9b85c31bb9e7
Successfully built 9b85c31bb9e7
Successfully tagged orderservice6001:v1.2
[root@vm001 dockertest20220516]# docker images
REPOSITORY                                                    TAG          IMAGE ID       CREATED         SIZE
orderservice6001                                              v1.2         9b85c31bb9e7   4 seconds ago   760MB
5.7.3.2.4 执行docker compose

docker compose up 或者
docker compose up -d (后台运行)

[root@vm001 dockertest20220516]# docker compose up -d
[+] Running 4/4
 ⠿ Network dockertest20220516_cc_network  Created                                                                                                                                   0.4s
 ⠿ Container dockertest20220516-mysql-1   Started                                                                                                                                   0.8s
 ⠿ Container dockertest20220516-redis-1   Started                                                                                                                                   0.8s
 ⠿ Container ms01                         Started 

[root@vm001 dockertest20220516]# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                                         NAMES
a5a13d9bbe2c   orderservice6001:v1.2   "java -jar /OrderSer…"   19 minutes ago   Up 19 minutes   0.0.0.0:6001->6001/tcp, :::6001->6001/tcp                                                     ms01
466cfff873c6   mysql:8.0.27            "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp                                          dockertest20220516-mysql-1
e12df8432b99   redis                   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp                                                     dockertest20220516-redis-1
5.7.3.2.4 进入mysql容器实例并新建库db2021+新建表t_user

参考 5.7.1.2

5.7.3.2.5 测试

在宿主机测试:
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第17张图片
Docker 学习笔记 - 进阶四 Docker网络和 Docker compose_第18张图片
区数据库查看,数据能成功插入

5.7.3.3 docker compose 常用命令

Compose常用命令

docker-compose -h                           # 查看帮助

docker-compose up                           # 启动所有docker-compose服务

docker-compose up -d                        # 启动所有docker-compose服务并后台运行

docker-compose down                         # 停止并删除容器、网络、卷、镜像。

docker-compose exec  yml里面的服务id                 # 进入容器实例内部  docker-compose exec docker-compose.yml文件中写的服务id /bin/bash

docker-compose ps                      # 展示当前docker-compose编排过的运行的所有容器

docker-compose top                     # 展示当前docker-compose编排过的容器进程

 

docker-compose logs  yml里面的服务id     # 查看容器输出日志

dokcer-compose config     # 检查配置

dokcer-compose config -q  # 检查配置,有问题才有输出

docker-compose restart   # 重启服务

docker-compose start     # 启动服务

docker-compose stop      # 停止服务

5.7.3.4 关停服务

docker compose down

[root@vm001 dockertest20220516]# docker compose down
[+] Running 4/4
 ⠿ Container ms01                         Removed                                                                                                                                   0.5s
 ⠿ Container dockertest20220516-redis-1   Removed                                                                                                                                   0.3s
 ⠿ Container dockertest20220516-mysql-1   Removed                                                                                                                                   3.5s
 ⠿ Network dockertest20220516_cc_network  Removed                                                                                                                                   0.3s
[root@vm001 dockertest20220516]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED        STATUS       PORTS                                                                                         NAMES
## 没有运行中的实例

你可能感兴趣的:(docker,网络,学习)