12docker精髓-容器数据卷、DockerFile、Docker网络

12docker精髓-容器数据卷、DockerFile、Docker网络

1、容器数据卷

1.1什么是容器数据卷

docker的理念回顾

将应用和环境打包成一个镜像!

数据?如果数据都在容器中,那么我们容器删除,数据就会丢失! 需求︰数据可以持久化

MySQL,容器删了,删库跑路! 需求:MySQL数据可以存储在本地!

容器之间可以有一个数据共享的技术! Docker容器中产生的数据,同步到本地! 这就是卷技术!

目录的挂载,将我们容器内的目录,挂载到Linux上面!|

容器数据卷就是为了解决容器数据持久化和同步操作,容器间也可以数据共享

image-20220605154850516

总结一句话:容器的持久化和同步操作! 容器间也是可以数据共享的!

1.2使用数据卷

方式一: 直接使用命令挂载 -v

# docker run -v 命令
$ docker run -v 主机目录:容器内目录	(文件映射)			# -p 主机端口:容器内端口		(端口映射)

# 测试
[root@MyCould ~]# docker run -it --name mycentos -v /home/ceshi:/home centos /bin/bash

#启动起来时候我们可以通过docker inspect容器id

image-20220605154918964

文件的同步测试

image-20220605154956781

再来测试!

1、停止容器

2、宿主机上修改文件

3、启动容器

4、容器内的数据依旧是同步的!

image-20220605155025604

好处∶我们以后修改只需要在本地修改即可,容器内会自动同步!

1.3实战:安转MySQL

思考:MySQL数据的可持久化问题!

#获取MySQL镜像:5.7
[root@MyCould home]# docker pull mysql:5.7

# 运行容器时,需要做数据挂载。 安装mysql是需要配置密码的!
# 官方测试
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
# 测试
$ docker run -d -p 3344:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/bin/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7

# 启动了mysql
-d 后台运行
-p 主机端口:容器端口
-v 容器数据卷映射(挂载)
-e 容器环境配置
--name 容器名称

[root@MyCould data]# docker run -d -p 3344:3306 -v /home/mysql/conf.d/:/etc/mysql/conf.d/ -v /home/mysql/data/:/var/lib/mysql/ -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7


#启动成功之后,我们在本地使用 Navicat Premium 来接测试一下
# Navicat Premium -->连接到服务器的3344 --->3344和容器内的3306映射,这个时候我们就可以连接上了!
#在本地测试创建一个数据库,查看一下我们映射的路径是否ok !

image-20220530093013382

image-20220605155102676

image-20220530095741220

​ 发现,我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能 ! (即使不小心删除了数据库容器,也不会导致,一下子把数据都丢失掉,数据的持久化)

1.4 具名与匿名数据卷

# 匿名挂载
-V 挂载容器数据卷
$ docker volume 命令

# 命令:
  create      # 创建数据卷
  inspect     # 显示一个或多个卷的详细信息
  ls          # 数据卷列表
  prune       # 删除所有未使用的本地卷
  rm          # 删除单个数据卷或多个数据卷
  
# 查看所有volume的情况
[root@MyCould home]# docker volume ls
DRIVER    VOLUME NAME
local     0795854c954dcebb6cd764ea754e44a6163f608f9cd4de84e6ed7c9553f68bad


[root@MyCould home]# docker run -d -P --name nginx02 -v juming:/etc/nginx nginx
1c7c59548033d8e05eb0d96e31ec85ca626f9e73b5f5ac9ea1515b601bff237b
[root@MyCould home]# docker ps 
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                     NAMES
1c7c59548033   nginx     "/docker-entrypoint.…"   4 seconds ago   Up 2 seconds   0.0.0.0:49153->80/tcp, :::49153->80/tcp   nginx02
[root@MyCould home]# docker volume ls
DRIVER    VOLUME NAME
local     0795854c954dcebb6cd764ea754e44a6163f608f9cd4de84e6ed7c9553f68bad
local     juming
[root@MyCould home]# 

# -v 卷名:容器内路径

[root@MyCould home]# docker inspect juming 				# 未指定主机路径,则默认存储在:/var/lib/docker/volumes/下
[
    {
        "CreatedAt": "2022-05-30T22:59:44+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming/_data",
        "Name": "juming",
        "Options": null,
        "Scope": "local"
    }
]

所有的docker容器内的卷,没有指定目录的情况下都是在 /var/Tib/docker/volumes/xxxx/_data我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的 具名挂载

# 区分匿名挂载与具名挂载,指定路径挂载!
-v 容器内路径			 # 匿名挂载
-v 卷名:容器内路径			# 具名挂载
-v /宿主机路径:容器内路径	  # 指定路径挂载

拓展:

# 通过 -v容器内路径:rorw改变读写权限
roreadonly 			#只读
rwreadwrite			#可读可写

# 一旦这个了设置了容器权限,容器对我们挂载出来的内容就有限定了!
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -p --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!

1.5初识DockerFile

dockerfile 就是用来构建docker镜像的。命令脚本! 体验一下!

生成镜像:

方式一: commit

方式二: dockerfile

​ docker build 命令

通过这个脚本可以生成镜像,镜像是一层一层的,脚本一个个的命令,每个命令都是一层!

[root@MyCould docker-test-volume]# docker build --help
# 可选参数
	  --add-host list           # 添加自定义主机到IP映射(主机:IP)
      --build-arg list          # 设置构建时变量
  -c, --cpu-shares int          # CPU份额(相对权重)
  -f, --file string             # Dockerfile的名称(默认值为“path/Dockerfile”)
  -m, --memory bytes            # 内存限制
  -q, --quiet                   Suppress the build output and print image ID on success
  -t, --tag list                Name and optionally a tag in the 'name:tag' format
[root@MyCould docker-test-volume]# vim dockerfile01
[root@MyCould docker-test-volume]# ls
dockerfile01
[root@MyCould docker-test-volume]# cat dockerfile01 
FROM centos
VOLUME ['volume01','volume02']
CMD echo '----end----'
CMD /bin/bash

[root@MyCould docker-test-volume]#
[root@MyCould docker-test-volume]# docker build -f ./dockerfile01 -t redskaber/centos:1.0 .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume01","volume02"]					# 这里的volume需要用双引号: -v volume01 -v volume02
 ---> Running in a7c765d4fc38				
Removing intermediate container a7c765d4fc38
 ---> d21446419368
Step 3/4 : CMD echo '----end----'
 ---> Running in 10ec1a652275
Removing intermediate container 10ec1a652275
 ---> 6696a7fca4e4
Step 4/4 : CMD /bin/bash
 ---> Running in edb647d027af
Removing intermediate container edb647d027af
 ---> 137bb5de5bec
Successfully built 137bb5de5bec
Successfully tagged redskaber/centos:1.0
[root@MyCould docker-test-volume]#
# 这里的每一个命令都是镜像中的一层!

image-20220531161849462

# 启动自己的容器
[root@MyCould docker-test-volume]# docker run -it redskaber/centos:1.0 /bin/bash

image-20220531163056131

image-20220531170857989

测试一下刚才的文件是否同步出去了!
这种方式我们未来使用的十分多,因为我们通常会构建自己的镜像!
假设构建镜像时候没有挂载卷,要手动镜像挂载 -v 卷名:容器内路径!

1.6数据卷容器

容器与容器之间的同步(例:多个MySQL数据同步!)

image-20220605155138689

子容器挂载父容器

docekr run --help
	--volumes-from list              # 从指定容器装载卷
# 容器间的数据同步与宿主机的数据同步其实没啥区别,只是一个挂载在宿主机,一个挂载在宿主机的容器上。

image-20220531174550189

image-20220531175659771

image-20220531175754560

image-20220531175844238

不同容器之间

image-20220531180244832

image-20220605155231639

结论∶
容器之间配置信息的传递,数据卷容器的生命周期一直持续到没有容器使用为止。

但是一旦你持久化到了本地,这个时候,本地的数据是不会删除的!

容器之间的数据卷是采用“拷贝备份的机制”,即使俩个子容器 --volume-from 父容器,这个父容器被干掉了,俩个子容器之间也可以正常的使用数据卷共享数据。

2、DockerFile

dockerfile是用来构建dokcer镜像的文件!

命令参数脚本!

构建步骤︰
1、编写一个dockerfile文件

​ 2、 docker build构建成为一个镜像

​ 3、docker run运行镜像

​ 4、docker push发布镜像(DockerHub、阿里云镜像仓库!)

2.1查看官方是怎么做的 ?

image-20220601113717003

image-20220601114018555

很多官方镜像都是基础包,很多功能没有,我们通常会自己搭建自己的镜像!官方既然可以制作镜像,那我们也可以!

2.2 DockerFile介绍

img

image-20220601141146336

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!

Docker镜像逐渐成为企业交付的标准,必须要掌握 !

步骤: 开发,部署,运维.....缺一不可!

DockerFile:构建文件,定义了一切的步骤,源代码

Dockerlmages : 通过DockerFile构建生成的镜像,最终发布和运行的产品!

Docker容器︰ 容器就是镜像运行起来提供服务器

2.3 DockerFile指令

以前的话我们就是使用别人的,现在我们知道了这些指令后,我们来练习自己写一个镜像!

FROM			# 基础镜镜像, 一切从这里开始构建
MAINTAINER		# 镜像是谁写的, 姓名+邮箱
RUN				# 镜像构建的时候需要运行的命令
ADD				# 步骤: tomcat镜像, 这个tomcat压缩包! 添加内容 ADD会自动解压
WORKDIR			# 镜像的工作目录
VOLUME			# 挂载的目录
EXPOSE			# 保留端口配置
CMD				# 指定这个容器启动的时候要运行的命令, 只有最后一个会生效,可被替代
ENTRYPOINT		# 指定这个容器启动的时候要运行的命令, 可以追加命令
COPY			# 类似ADD , 将我们文件拷贝到镜像中 COPY不会自动解压
ENV				# 构建的时候设置环境变量!
ONBUILD			# 触发指令。 ONBUILD是一个特殊的指令它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的 时候才会被执行  (当前镜像作为父类镜像,被子镜像FROM的时候触发)

image-20220605155321116

实战测试:centos镜像

Docker Hub中 99% 镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行的构建

image-20220601141610130

创建一个自己的centos

# 编写一个DockerFile 脚本
[root@MyCould dockerfile]# ls
dockerfile-mycentos
[root@MyCould dockerfile]# cat dockerfile-mycentos 
FROM centos:7
MAINTAINER redskaber<277441632@qq.com>

ENV MYPATH /usr/local
WORKDIR	$MYPATH

RUN yum install -y vim
RUN yum install -y net-tools

EXPOSE 80

CMD echo $MYPATH
CMD ehco "--------end--------"
CMD ["/bin/bash"]

# 通过这个文件构建镜像
[root@MyCould dockerfile]# docker build -f ./dockerfile-mycentos -t mycentos .
Sending build context to Docker daemon  2.048kB
......
Removing intermediate container 80ea28928021
 ---> cb854bd4c4da
Successfully built cb854bd4c4da
Successfully tagged mycentos:latest

# 测试运行
[root@MyCould dockerfile]# docker run -it cb854bd4c4da /bin/bash

对比:之前的原生的centos

image-20220605155358153

我们增加之后的镜像

image-20220605155426226

history 查看一个镜像的历史,构建过程

image-20220605155505000

我们平时拿到一个镜像,可以研究一下它是怎么做的了?,github

CMD 和 ENTRYPOINT 的区别

CMD 和 ENTRYPOINT 的区别

CMD				# 指定这个容器启动的时候要运行的命令, 只有最后一个会生效,可被替代
ENTRYPOINT		# 指定这个容器启动的时候要运行的命令, 可以追加命令

测试CMD

[root@MyCould dockerfile]# vim dockerfile-cmd
[root@MyCould dockerfile]# cat dockerfile-cmd 
FROM centos:7

CMD ["ls","-a"]

# 构建镜像

[root@MyCould dockerfile]# docker build -f ./dockerfile-cmd -t dockerfile-cmd .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/2 : CMD ["ls","-a"]
 ---> Running in 6bda4a4f9ebe
Removing intermediate container 6bda4a4f9ebe
 ---> 84c99a1e067a
Successfully built 84c99a1e067a
Successfully tagged dockerfile-cmd:latest

# 运行测试:发现 ls -a 是生效的

[root@MyCould dockerfile]# docker run dockerfile-cmd:latest 
.
..
.dockerenv
anaconda-post.log
...

# 想追加一个 -l 的命令, ls -al

[root@MyCould dockerfile]# docker run dockerfile-cmd:latest -l
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.

# 使用CMD的情况下,追加的 -l 替代 CMD ["ls","-a"]命令, 而 -l 不是命令,所以报错!

[root@MyCould dockerfile]# docker run dockerfile-cmd:latest  ls -la
total 12
drwxr-xr-x   1 root root     6 Jun  2 06:39 .
drwxr-xr-x   1 root root     6 Jun  2 06:39 ..
-rwxr-xr-x   1 root root     0 Jun  2 06:39 .dockerenv
......
drwxr-xr-x  18 root root   238 Nov 13  2020 var
[root@MyCould dockerfile]# 

测试ENTRYPOINT

[root@MyCould dockerfile]# vim dockerfile-entrypoint
[root@MyCould dockerfile]# cat dockerfile-entrypoint 
FROM centos:7

ENTRYPOINT ["ls","-a"]

# 构建镜像
[root@MyCould dockerfile]# docker build -f ./dockerfile-entrypoint -t dockerfile-entrypoint .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM centos:7
 ---> eeb6ee3f44bd
Step 2/2 : ENTRYPOINT ["ls","-a"]
 ---> Running in e89884eca013
Removing intermediate container e89884eca013
 ---> 9972ffd97e5b
Successfully built 9972ffd97e5b
Successfully tagged dockerfile-entrypoint:latest

# 运行测试:发现 ls -a 是生效的
[root@MyCould dockerfile]# docker run dockerfile-entrypoint:latest 
.
..
.dockerenv
anaconda-post.log
...

# 我们追加的命令是直接拼接在ENTRYPOINT后的
[root@MyCould dockerfile]# docker run dockrfile-entrypoint:latest -l
total 12
drwxr-xr-x   1 root root     6 Jun  2 06:30 .
drwxr-xr-x   1 root root     6 Jun  2 06:30 ..
-rwxr-xr-x   1 root root     0 Jun  2 06:30 .dockerenv
......
drwxr-xr-x  18 root root   238 Nov 13  2020 var
[root@MyCould dockerfile]# 

Dockerfile中很多命令都十分的相似,我们需要了解它们的区别,我们最好的学习就是对比他们然后测试效果!

2.4DockerFile的构建过程

实战测试:tomcat镜像

下载包:

​ [apache-tomcat-9.0.22.tar.gz](Index of /dist/tomcat/tomcat-9/v9.0.22/bin (apache.org))

jdk-8u11-linux-x64.tar.gz

1、准备镜像文件tomcat压缩包,jdk的压缩包!

image-20220605155605315

2、编写dockerfile文件,官方命名Dockerfile, build会自动寻找这个文件,就不需要 -f 指定了!

# 1.基本镜像
FROM centos:7
# 2.维护者
MAINTAINER redskaber<277441632@qq.com>
# 3.copy 文件
COPY README.md /usr/local/README.md
# 4.add 添加文件 
ADD jdk-8u11-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.22.tar.gz  /usr/local/
# 5.run 命令
RUN yum install -y vim
# 6.工作目录
ENV WORKDIR /usr/local/
WORKDIR $WORKDIR
# 7.环境配置
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar		# 错过***
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.22
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.22
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin		# 错过***
# 8.暴露端口
EXPOSE 8080
# 9.容器启动的时候要运行的命令, 只有最后一个会生效,可被替带
CMD /usr/local/apache-tomcat-9.0.22/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.22/logs/catalina.out  # 错过*****



3、构建镜像

$ docker build -t diytomcat .

4、运行测试

$ docker run -d \
    -p 8080:8080 \
    --name redskaber-tomcat \
    -v /home/builds/tomcat/test:/usr/local/apache-tomcat-9.0.22/webapps/test \
    -v /home/builds/tomcat/tomcatlogs:/usr/local/apache-tomcat-9.0.22/logs \
     diytomcat

5、访问测试

image-20220602225025399

发布自己的镜像

Docker Hub

1、注册 Docker Hub 账号:Docker Hub

2、登录Docker Hub

Usage:  docker login [OPTIONS] [SERVER]
# 如果未指定服务器,则默认值由守护程序定义。

# 可选参数:
  -p, --password string   # 密码
      --password-stdin    # 从stdin获取密码
  -u, --username string   # 用户名
[root@MyCould ~]# docker login -u redskaber 
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

docker tag 新建tag名称镜像

# 这里推荐使用 auther/image:tag
docker tag source new      				# 通过原来的image创建一个带tag标记的image,(新添,修改镜像名称)


[root@MyCould ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
diytomcat    latest    ee64299a1ad6   21 hours ago   769MB
centos       7         eeb6ee3f44bd   8 months ago   204MB

[root@MyCould ~]# docker tag diytomcat:latest  redskaber/tomcat:1.0	
[root@MyCould ~]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED        SIZE
diytomcat          latest    ee64299a1ad6   21 hours ago   769MB
redskaber/tomcat   1.0       ee64299a1ad6   21 hours ago   769MB
centos             7         eeb6ee3f44bd   8 months ago   204MB

docker push 发布自己的镜像

Usage:  docker push [OPTIONS] NAME[:TAG]

# 可选参数:
  -a, --all-tags                # 推送存储库中的所有镜像
      --disable-content-trust   # 跳过图像签名(默认为true)
  -q, --quiet                   # 抑制详细输出
  
  [root@MyCould ~]# docker push redskaber/tomcat:1.0 

image-20220603192310397

阿里云镜像服务上

1、登录阿里云

2、选择容器镜像服务

3、申请个人实例

4、创建命名空间

image-20220603193457693

5、创建镜像仓库

image-20220603194035162

6、根据说明实现

image-20220603194121905

将镜像推送到Registry

$ docker login --username=染夏千枫 registry.cn-shenzhen.aliyuncs.com
$ docker tag [ImageId] registry.cn-shenzhen.aliyuncs.com/department/dockerbase:[镜像版本号]
$ docker push registry.cn-shenzhen.aliyuncs.com/department/dockerbase:[镜像版本号]

小结

image-20220605155633825

3、Docker 网络

理解Docker0

学习docker网络时,清空所有环境,方便我们理解Docker网络

三个网络

# 问题:docker是如何处理容器网络访问的?

解决 ip add 命令不存在问题

[root@MyCould /]# docker run -d -p 8080:8080 --name tomcat01 tomcat


# 查看容器的内部网络地址ip addr,发现容器启动的时候会得到一个eth0@if7 ip地址,docker分配的!

[root@MyCould /]# docker exec -it tomcat01 ip addr						# 这里的ip add 是直接 拼接entrypoint里面
1: lo: <LOOPBACK,UP,LOWER_UP> 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
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
       
       
# 思考。liunx能不能ping通容器内部!      

[root@MyCould /]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.066 ms
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 40ms
rtt min/avg/max/mdev = 0.066/0.066/0.066/0.000 ms
[root@MyCould /]# 
# linux 可以ping通docker容器内部网络

image-20220605152130170

原理:

1、我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡dockerO桥接模式,使用的技术是 veth pair技术!

1、再次测试 ip addr

image-20220605153113688

2、再启动一个容器,发现又多了一对网卡~

image-20220605163809253

# 我们发现这个容器带来网卡,都是一对对的
# veth pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性,veth pair 充当一个桥梁,链接各种虚拟设备
# OpenStack, Docker容器之间, ovs的连接, 都是通过 vetn pair技术!

image-20220605172622448

image-20220605172817134

结论: tomcat01和tomcat02是公用的一个路由器,docker0。

所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP

小结

Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥 docker0。

image-20220605173114574

Docker中的所有的网络接口都是虚拟的。虚拟的转发效率高!(内网传递文件!)

只要容器删除,网桥也跟着删除!

(高可用)

思考一个场景,我们编写了一个微服务,database url=ip:, 项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器 ?

[root@MyCould home]# docker run --help | grep "link"
      --link list            # 添加指向其他容器的链接
[root@MyCould home]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
5651753d2ef4d5ee060f5c6f322fecc9692d533fec4ecb98fe008b994df3f13b


[root@MyCould home]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 通过--link 就可以解决 容器之间ping需要ip的问题
[root@MyCould home]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.123 ms
64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.073 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1059ms
rtt min/avg/max/mdev = 0.073/0.098/0.123/0.025 ms
[root@MyCould home]# 

# 反向如果没有指定 --link 容器id 是ping不通的
[root@MyCould home]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

其实这个tomcat03就是在本地配置了tomcat02的配置?

# 查看hosts配置,在这里原理发现!

image-20220606183825798

image-20220606184123203

本质探究: --link 就是我们在hosts配置中增加了一个 172.18.0.3 tomcat02 f39b153bef124路由映射

我们现在玩Docker 已经不建议使用 --link了 ! 自定义网络! 不适用docker0 !

docker0 问题: 他不支持容器名连接访问!

自定义网络

容器互联: 多台物理主机之间的容器互联(暴露容器到真实网络中),包括 --link,自定义网络等都是

查看所有的docker网络

image-20220606185656930

网络模式:

  • bridge模式(桥接模式,默认,自己创建也使用桥接模式)
  • host模式(仅主机模式,与宿主机共享网络)
  • none 不配置网络模式
  • container模式:容器网络连接!(用的少,局限大!了解即可)

测试: 创建bridge模式网络

[root@MyCould home]# docker network  --help
# 命令:
  connect     			# 将容器连接到网络
  create      			# 创建一个网络
  disconnect  			# 断开容器与网络的连接
  inspect     			# 显示单个或多个网络的详细信息
  ls          			# 网络清单
  prune       			# 删除未启用网络
  rm          			# 删除指定单个(多个)网络
  # 我们直接启动时 --network bridge,而这默认为docker0
$ docker run -d -P --name tomcat01 
$ docker run -d -P --name tomcat01 --network bridge


# docker0特点:默认,域名不能访问,--link可以打通连接!

docker network create 创建网络

[root@MyCould home]# docker network create --help

Usage:  docker network create [OPTIONS] NETWORK

# 可选参数:
      --attachable           # 启用手动容器连接
      --aux-address map      # 网络driver使用的辅助IPv4或IPv6地址(默认映射[])
      --config-from string   # 从文件中复制配置的网络
      --config-only          # 创建仅配置的网络
  -d, --driver string        # bridge网络的驱动程序模式 (default "bridge") host、 none、 container.. 
      --gateway strings      # 主要子网的IPv4或IPv6的网关
      --ingress              # 创建群路由网状网络
      --internal             # 限制外部访问网络
      --ip-range strings     # 给容器分配一个子网段ip
      --ipam-driver string   # IP地址管理driver(default "default")
      --ipam-opt map         # 设置 IPAM driver 具体选项 (default map[])
      --ipv6                 # 启用 ipv6的网络
      --label list           # 在网络上设置元数据
  -o, --opt map              # 设置 driver 具体的选项 (default map[])
      --scope string         # 控制网络范围
      --subnet strings       # 表示网段的CIDR格式的子网,分配子网+子网掩码: 192.168.0.0/24 
# 自定义网络
#  -d bridge			
# --subnet 192.168.0.0/24
# --gateway 192.168.0.1
[root@MyCould home]# docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
4b45c628a0a186ae48fa9bc8172d6f40080be9ac2b77f2e7fba17e930b36bacc

image-20220606194442222

[root@MyCould home]# docker run -d -P --name tomcat-net01 --network mynet  tomcat
76f56c6e60ae3e6e687c85fbf0f7228754f4ebeda1401c59b4b40d1223375ebe
[root@MyCould home]# docker run -d -P --name tomcat-net02 --network mynet  tomcat
5fd5135379c7d7a8770cc341253980d4bd9c2a6a904257a0789f01f538890253

# 再次尝试ping
[root@MyCould home]# docker exec -it tomcat-net01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.060 ms
^C
--- 192.168.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1062ms
rtt min/avg/max/mdev = 0.060/0.068/0.076/0.008 ms


# 现在不使用 --link 也可以ping通 名字了
[root@MyCould home]# docker exec -it tomcat-net01 ping tomcat-net02
PING tomcat-net02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.195 ms
64 bytes from tomcat-net02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.092 ms
64 bytes from tomcat-net02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.087 ms
^C
--- tomcat-net02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2033ms
rtt min/avg/max/mdev = 0.087/0.124/0.195/0.049 ms

[root@MyCould home]# docker exec -it tomcat-net01 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
192.168.0.2	76f56c6e60ae

我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络!

好处︰
redis - 不同的集群使用不同的网络,保证集群是安全和健康的

​ mysql - 不同的集群使用不同的网络,保证集群是安全和健康的

网络联通

image-20220606220659882

image-20220606222702732

[root@MyCould ~]# docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
# 可选参数:
      --alias strings           # 为容器添加网络范围的别名
      --driver-opt strings      # driver网络选项
      --ip string               # IPv4 地址 (e.g., 172.30.100.104)
      --ip6 string              # IPv6 地址 (e.g., 2001:db8::33)
      --link list               # 添加指向其他容器的链接
      --link-local-ip strings   # 为容器添加链接本地地址 
# 测试打通 tomcat01  -  mynet
[root@kuangshen/]# docker network connect mynet tomcat01

# 连通之后就是将 tomcat01 放到了 mynet 网络下?
# 一个容器两个 ip 地址 !
# 阿里云服务:公网ip    私网ip

docker network inspect mynet

image-20220606232404779

# 01 ping通 ok
[root@MyCould ~]# docker exec -it tomcat01 ping tomcat-net01
PING tomcat-net01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from tomcat-net01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.085 ms
64 bytes from tomcat-net01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.098 ms
^C
--- tomcat-net01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2042ms
rtt min/avg/max/mdev = 0.085/0.092/0.098/0.005 ms

# 02 ping不通
[root@MyCould ~]# docker exec -it tomcat02 ping tomcat-net01
ping: tomcat-net01: Name or service not known
[root@MyCould ~]# 

结论︰假设要跨网络操作别人,就需要使用 docker network connect连通 ! 。。。。

实战:Redis集群布署

image-20220607153545072

shell 脚本

# 1、创建一个网络redis
$ docker network create redis --subnet 192.168.38.0/24


# 2、通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.38.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# shell 脚本运行
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;
# done



# 自己写
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;

docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;

docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;

docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;

docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;

docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 192.168.38.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;




# 3、创建集群
/data # redis-cli --cluster create 192.168.38.11:6379 192.168.38.12:6379 192.168.38.13:6379 192.168.38.14:6379 192.168.38.15:6379 192.168.38.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.38.15:6379 to 192.168.38.11:6379
Adding replica 192.168.38.16:6379 to 192.168.38.12:6379
Adding replica 192.168.38.14:6379 to 192.168.38.13:6379
M: b36b474e6f137d4ff814cb5e052a49bb0732a267 192.168.38.11:6379
   slots:[0-5460] (5461 slots) master
M: 92bfa5e8cafd57ce28af73c32b7c3138dc068ef0 192.168.38.12:6379
   slots:[5461-10922] (5462 slots) master
M: 654bb6d7b2dd00afcaf64f1e1343c7ed714c9112 192.168.38.13:6379
   slots:[10923-16383] (5461 slots) master
S: 03c6ef0d0262fc9875c7f7e6a8aab05d84ab292b 192.168.38.14:6379
   replicates 654bb6d7b2dd00afcaf64f1e1343c7ed714c9112
S: ee4e413aa4910a651972f7449d6d5c47647a9cb1 192.168.38.15:6379
   replicates b36b474e6f137d4ff814cb5e052a49bb0732a267
S: 8fb3f2b099ae37474833a9976b7cc2450844ce8e 192.168.38.16:6379
   replicates 92bfa5e8cafd57ce28af73c32b7c3138dc068ef0
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.....
>>> Performing Cluster Check (using node 192.168.38.11:6379)
M: b36b474e6f137d4ff814cb5e052a49bb0732a267 192.168.38.11:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 8fb3f2b099ae37474833a9976b7cc2450844ce8e 192.168.38.16:6379
   slots: (0 slots) slave
   replicates 92bfa5e8cafd57ce28af73c32b7c3138dc068ef0
M: 92bfa5e8cafd57ce28af73c32b7c3138dc068ef0 192.168.38.12:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 654bb6d7b2dd00afcaf64f1e1343c7ed714c9112 192.168.38.13:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: ee4e413aa4910a651972f7449d6d5c47647a9cb1 192.168.38.15:6379
   slots: (0 slots) slave
   replicates b36b474e6f137d4ff814cb5e052a49bb0732a267
S: 03c6ef0d0262fc9875c7f7e6a8aab05d84ab292b 192.168.38.14:6379
   slots: (0 slots) slave
   replicates 654bb6d7b2dd00afcaf64f1e1343c7ed714c9112
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
/data # 

image-20220607163407060

我们使用了docker之后,所有的技术都会慢慢的变得简单起来!

posted @ 2022-06-10 19:25  Redskaber  阅读(641)  评论(0)    收藏  举报