Dokcer笔记总结

Docker镜像讲解

镜像是什么

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

如何得到镜像:

  • 从远程仓库下载
  • 拷贝别人的
  • 自己制作一个镜像DockerFile

Docker镜像加载原理

UnianFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

bootfs(boot file system)主要包含pootloaderkernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs.文件系统,在Docker镜像的最底层是oootfs。这一层与我们典型的Linux/Unixⅸ系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs4转交给内核,此时系统也会卸载bootfs。

rootfs(root file system),在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Jbuntu,Centos等等。

Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统JnionFS。
在这里插入图片描述
当用docker run启动这个容器时,实际上在镜像的顶部添加了一个新的可写层。这个可写层也叫容器层。
在这里插入图片描述
总的来说:因为Docker镜像是分层的,因此在加载一个镜像的时候,会按照从底层到高层的顺序依次加载该镜像所需要的镜像层。在加载的过程中,如果当前镜像层已经存在,则会跳过当前镜像层。

在这里插入图片描述

分层理解

分层镜像

所有的Dock镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。

举一个简单的例子,假如基于Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

在这里插入图片描述

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

Docker通过存储擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。Linux上可用的存储引擎有AUFS、Overlay:2、Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

在这里插入图片描述

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

在这里插入图片描述

容器数据卷

什么是容器数据卷

docker的理念回顾

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

如果数据都在容器中,那么我们将容器删除,数据就会丢失!
所以我们希望数据可以持久化

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

这就是卷技术!目录的挂载,将我们容器内的目录,挂载到Linux上面!

在这里插入图片描述

使用数据卷

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

docker run -it -v 主机目录:容器目录

#测试
[root@iZbp1cobq68xtff4clzo6uZ ~]# docker run -it -v /home/test:/home centos /bin/bash

#启功后,通过docker inspect 容器id

在这里插入图片描述

测试文件同步
#1、在主机上建立一个文件(或是在容器对应目录中建立一个文件)

#2、可以发现在容器(或是主机中)对应目录中有该文件

在这里插入图片描述

即使容器停止,只要容器还在,主机修改对应目录文件后,启动容器后就会同步过去

具名挂载和匿名挂载

#匿名挂载
-v 容器内路径!
docker run -d -P --name nginx01 -v /ect/nginx nginx

#查看所有的volume的情况
[root@iZbp1cobq68xtff4clzo6uZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     3ec15df8c594e6d69eae596ae597c3a30b3f1640c67ff292fb6b38986af800d8

#可以发现,这种就是匿名挂载,我们在-v只写了容器内的路径,没有写容器外的路径!

#具名挂载
[root@iZbp1cobq68xtff4clzo6uZ home]# docker run -d -p 3344:80 --name nginx02 -v juming-nginx:/etc/nginx nginx
f9d25a9a5c17391024b34cbc258764b9f333a90a7daef6807b981de86e48d537
[root@iZbp1cobq68xtff4clzo6uZ home]# docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx

#通过 -v 卷名:容器内路径
#查看一下这个卷
#命令
docker volume inspect juming-nginx

在这里插入图片描述

所有的docker容器内的卷,没有指定目录的情况下都是在/var/lib/docker/volumes/juming-nginx/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载

#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径			#匿名挂载
-v 卷名:容器内路径		   #具名挂载
-v /宿主机路径:容器内路径	 #指定路径挂载

DockerFile

DockerFile介绍

dockerfile是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

1、编写一个dockerfile文件

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

3、docker run运行镜像

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

查看官方是这么做的?

在这里插入图片描述

DockerFile构建过程

基础知识

1、每个保留关键字(指令)都是必须是大写字母

2、执行从上到下顺序执行

3、# 表示注释

4、每一个指令都会创建提交一个新的镜像层,并提交!

在这里插入图片描述

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

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

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

Docker容器:容器就是镜像运行起来提供的服务!

DockerFile的指令

FROM				#基础镜镜像,,一切从这里开始构建
MAINTAINER			#镜像是谁写的,姓名+邮箱
RUN					#镜像构建的时候需要运行的命令
ADD					#步骡:tomcat镜像,这个tomcat压缩包中添加内容
WORKDIR				#镜像的工作目录
VOLUME				#挂载的目录
EXPOSE				#保留端口配置
CMD					#指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代
ENTRYPOINT			#指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD				#当构建一个被继承DockerFi1e这个时候就会运行ONBUILD的指令。触发指令。
COPY				#类似ADD,将我们文件拷贝到镜像中
ENV					#构建的时候设置环境变量!

在这里插入图片描述

在这里插入图片描述

CMD和ENTRPOINT的区别

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

测试CMD

#编写dockerfi1e文件
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#vim dockerfile-cmd-test
FROM centos 
CMD ["1s","-a"]

#构件镜像
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#docker build -f dockerfile-cmd-test -t cmdtest

#run运行,发现我们的ls非a命令生效
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#docker run dd8e4401d72f
dockerenv
bin
dev
etc
home
lib
1ib64

#想追加一个命令 -l 		ls -al
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#docker run dd8e4401d72f -l
docker:Error response from daemon:OCI runtime create failed:container_linux.go:349:starting container process caused "exec:\"-1\":executable file not found in SPATH":unknown.

# cmd的清理下 -l 替换了CMD["ls","-a"]命令,-l 不是命令所以报错!

测试ENTRPOINT

#编写dockerfi1e文件
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#vim dockerfile-cmd-test
FROM centos 
NTRPOINT ["1s","-a"]

#使用NTRPOINT后允许在运行时追加指令,如:
[root@iZbp1cobq68xtff4clzo6uZ dockerfile]#docker run dd8e4401d72f -l

Docker网络

理解docker0网络

首先清空docker的所有环境(镜像、容器)

ip 测试

在这里插入图片描述

[root@iZbp1cobq68xtff4clzo6uZ ~]# docker exec -it 35b2f6e5a361 ip addr
#使用以上命令可能会报错,原因是:下载的tomcat容器没有该类型的命令,所有需要先下载指令---使用下面的命令
apt update && apt install -y iproute2

#查看容器的内部网络地址 ip addr
[root@iZbp1cobq68xtff4clzo6uZ ~]# docker exec -it 35b2f6e5a361 ip addr
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
66: eth0@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> 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@iZbp1cobq68xtff4clzo6uZ ~]# curl localhost:4915
curl: (7) Failed connect to localhost:4915; Connection refused

#docker容器外ping容器内部
[root@iZbp1cobq68xtff4clzo6uZ ~]# 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.052 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.052 ms
#发现可以ping通容器内部

原理

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

再次查看主机的ip,发现多了一个67:venth00b31bd@if66

在这里插入图片描述

2、再启动一个容器测试

在这里插入图片描述

# 我发现这个容器的网卡,都是一对一对的
# evth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一段连着协议,一端彼此相连
# 正因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备
# OpenStac ,Docker容器的连接,OVS的连接,都是使用 evth-pair技术

3、测试tomcat01和tomcat02

[root@iZbp1cobq68xtff4clzo6uZ ~]# ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1) 56(84) bytes of data.
64 bytes from 172.17.0.1: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 172.17.0.1: icmp_seq=2 ttl=64 time=0.053 ms

#结论:容器和容器之间是可以互相通信的!!!

绘制一个网络模型图:

在这里插入图片描述

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

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

小结

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

在这里插入图片描述

Docker中的所有的网络接口都是虚拟的,虚拟的转发效率高。

只要容器删除,对应的网桥一对就没有了。

容器互联–link

docker容器中如果无法使用ping命令!!!

#先更新apt
apt-get update

#安装ping有关的命令
apt install iputils-ping

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

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

#再运行一个容器并通过--linke连接另一个容易
[root@iZbp1cobq68xtff4clzo6uZ ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat:8

#再一次通过tomca03 ping tomcat02
[root@iZbp1cobq68xtff4clzo6uZ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.123 ms

#反向ping,使用tomcat02 ping tomcat02 
[root@iZbp1cobq68xtff4clzo6uZ home]# docker exec tomcat02 ping tomcat03
ping: tomcat03: Name or service not known   #发现并不能ping通

探究:inspect

在这里插入图片描述

查看tomcat03的host配置文件

在这里插入图片描述

–link就是在hosts的配置文件中增加了一个与之相连的容器的IP地址

自定义网络

查看所有的docker网络

[root@iZbp1cobq68xtff4clzo6uZ home]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8d3e676f2dc9   bridge    bridge    local
17ff3f6e961e   host      host      local
149c99e5d3ac   none      null      local

网络模式

bridge:桥接docker(默认,自己桥接也使用bridge模式)

none:不配置网络

host:和宿主机共享网络

container:容器网路连通!(用的少!局限很大)

测试

#我们直接启动的命令,--net bridge 而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat

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

#自定一个bridge网络
# --driver bridge   模式
# --subnet 网段      定义一个网段
# --gateway ip      定义网关
[root@iZbp1cobq68xtff4clzo6uZ home]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
dcee3b34689e108d0a2528382fd208524cddad0569cd8cd7aee139b1e2d19e6f
[root@iZbp1cobq68xtff4clzo6uZ home]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8d3e676f2dc9   bridge    bridge    local
17ff3f6e961e   host      host      local
dcee3b34689e   mynet     bridge    local
149c99e5d3ac   none      null      local

在这里插入图片描述

#通过自己定义的网络,运行两个容器tomcat01-net-02、tomcat01-net-01
#再查看自定义网络的消息,结果如下:
"ConfigOnly": false,
        "Containers": {
            "8419874cc781dbd857eaa79d7ab739ddfe3be240827907e0100e4ac93ef28b8a": {
                "Name": "tomcat01-net-02",
                "EndpointID": "db00c84a4eda1a5ba0ac60d62bb17b70b417e29b0804fd4b9c8c6bc96bddb815",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "b38602b97407d5d09d18fa9df9858d08841a211002e003cb0fe2b3c19b1e8ec0": {
                "Name": "tomcat01-net-01",
                "EndpointID": "2e4aa45d3217a5894fc2a14bc6ce829a5cccee5a8ece16f28a8a5e50388d13e0",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]


#再次测试ping连接
[root@iZbp1cobq68xtff4clzo6uZ home]# docker exec -it tomcat01-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.097 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.069 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.073 ms
64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.078 ms
^C
--- 192.168.0.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.069/0.079/0.097/0.010 ms

#不使用--link也可以使用”ping 名字“去连接测试了
[root@iZbp1cobq68xtff4clzo6uZ home]# docker exec -it tomcat01-net-01 ping tomcat01-net-02
PING tomcat01-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.080 ms
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.081 ms
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.103 ms
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=5 ttl=64 time=0.070 ms
64 bytes from tomcat01-net-02.mynet (192.168.0.3): icmp_seq=6 ttl=64 time=0.078 ms

自定义的网络docker都已经维护了加入该网段容器的对应关系,推荐使用这个方法!!!

网络连通

连接一个容器到一个网络

在这里插入图片描述

#命令:
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

#测试命令
[root@iZbp1cobq68xtff4clzo6uZ home]# docker network connect mynet tomcat01
#使用命令查看mynet的网络详情
[root@iZbp1cobq68xtff4clzo6uZ home]# docker network inspect mynet

#连通之后,就是将tomcat01放到了自定义网络mynet网络下
#这个一个容器就有两个IP地址

在这里插入图片描述

# 测试 tomcat01 ping tomcat01-net-01
[root@iZbp1cobq68xtff4clzo6uZ home]# docker exec -it tomcat01 ping tomcat01-net-01
PING tomcat01-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.061 ms

#由于tomcat02并没有加入自定义网络,所以不能ping通该网络中的容器
[root@iZbp1cobq68xtff4clzo6uZ home]# docker exec -it tomcat02 ping tomcat01-net-01
ping: tomcat01-net-01: Name or service not known

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值