【云原生 | Docker篇】网络和存储原理【与云原生的故事】
【摘要】 Docker的网络和存储原理,针对命令去深入讲解,让每个读者都能看懂,深知docker核心的存储原理。
网络和存储原理
前言
博主语录:一文精讲一个知识点,多了你记不住,一句废话都没有
经典语录:勇者愤怒,抽刃向更强者;怯者愤怒,却抽刃向更弱者
文末惊喜
一、Docker存储
1、镜像如何存
1.0、自己探索
截取的nginx的分层
nginx这个镜像怎么存的使用:docker image inspect nginx
如图指示了镜像怎么存的
- LowerDir :底层目录; diw (只是存储不同);包含小型linux和装好的软件
/var/lib/docker/overlay2/67b3802c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e631f7f2/diff:用户文件;/var/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd9bb077bdb4c7524b4/diff: nginx的启动命令放在这里/var/lib/docker/overlay2/0e569a134838b8c2040339c4fdb1f3868a7118dd7f4907b40468f5fe60f055e5/diff: nginx的配置文件在这里/var/lib/docker/overlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb1424953207166e/diff: 小linux系统
- 倒着看
"LowerDir":"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462c862f1e9a0562de2384dbc-init/diff:/var/lib/docker/overlay2/e3b8bdbb0cfbe5450696c470994b3f99e8a7942078e2639a788027529c6278f7/diff:/var/lib/docker/overlay2/67b3802c6bdb5bcdbcccbbe7aed20faa7227d584ab37668a03ff6952e631f7f2/diff:/var/lib/docker/overlay2/f56920fac9c356227079df41c8f4b056118c210bf4c50bd9bb077bdb4c7524b4/diff:/var/lib/docker/overlay2/0e569a134838b8c2040339c4fdb1f3868a7118dd7f4907b40468f5fe60f055e5/diff:/var/lib/docker/overlay2/2b51c82933078e19d78b74c248dec38164b90d80c1b42f0fdb142495320766e/diff","MergedDir":"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462c862f1e9a0562de2384dbc/merged","UpperDir": (镜像的上层可以感知变化)"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462c862f1e9a0562de2384dbc/diff",【容器的修改后的文件,保存在宿主机哪里呀。容器删除后,那些容器目录还存在吗?一定不再】"WorkDir":"/var/lib/docker/overlay2/41e4fa41a2ad1dca9616d4c8254a04c4d9d6a3d462c862f1e9a0562de2384dbc/work"
- MergedDir :合并目录;容器最终的完整工作目录全内容都在合并层;数据卷在容器层产生;所有的增删改都在容器层;
- UpperDir :上层目录;
- WorkDir :工作目录(临时层),PID;
LowerDir(底层)\UpperDir(上层)\MergedDir\WorkDir(临时东西)
docker底层的 storage driver完成了以上的目录组织结果;
1.1、Images and layers
Docker映像由一系列层组成。 每层代表图像的Dockerfile中的一条指令。 除最后一层外的每一层都是只读的。 如以下Dockerfile:
FROM ubuntu:15.04COPY . /appRUN make /appCMD python /app/app.py# 每一个指令都可能会引起镜像改变,这些改变类似git的方式逐层叠加。
- 该Dockerfile包含四个命令,每个命令创建一个层。
- FROM语句从ubuntu:15.04映像创建一个图层开始。
- COPY命令从Docker客户端的当前目录添加一些文件。
- RUN命令使用make命令构建您的应用程序。
- 最后,最后一层指定要在容器中运行的命令。
- 每一层只是与上一层不同的一组。 这些层彼此堆叠。
- 创建新容器时,可以在基础层之上添加一个新的可写层。 该层通常称为“容器层”。 对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此薄可写容器层。
1.2、Container and layers
- 容器和镜像之间的主要区别是可写顶层。
- 在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。
- 删除容器后,可写层也会被删除。 基础图像保持不变。 因为每个容器都有其自己的可写容器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础映像的访问,但具有自己的数据状态。
下图显示了共享同一Ubuntu 15.04映像的多个容器。
1.3、磁盘容量预估
docker ps -ssize:用于每个容器的可写层的数据量(在磁盘上)。virtual size:容器使用的用于只读图像数据的数据量加上容器的可写图层大小。多个容器可以共享部分或全部只读图像数据。从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的两个容器(具有相同的层)共享这些公共层。 因此,不能只对虚拟大小进行总计。这高估了总磁盘使用量,可能是一笔不小的数目。
1.4、镜像如何挑选
Busybox:是一个集成了一百多个最常用Linux命令和工具的软件。Linux工具里的瑞士军刀Alpine:Alpine操作系统是一个面向安全的轻型Linux发行版经典最小镜像,基于busybox,功能比 Busybox完善。Slim:docker hub中有些镜像有slim标识,都是瘦身了的镜像。也要优先选择无论是制作镜像还是下载镜像,优先选择Alpine类型.
1.5、Copy On Write
- 写时复制是一种共享和复制文件的策略,可最大程度地提高效率。
- 如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件。
- 另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。 这样可以将I / O和每个后续层的大小最小化。
2、容器如何挂载
每一个容器里面的内容,支持三种挂载方式:
- docker自动在外部创建文件夹自动挂载容器内部指定的文件夹内容【Dockerfile VOLUME指令的作用】
- 自己在外部创建文件夹,手动挂载
- 可以把数据挂载到内存中
--mount 挂载到 linux宿主机,手动挂载(不用了)
-v 可以自动挂载,到linux'主机或者docker自动管理的这一部分区域
- Volumes(卷) :存储在主机文件系统的一部分中,该文件系统由Docker管理(在Linux上是“ / var / lib / docker / volumes /”)。 非Docker进程不应修改文件系统的这一部分。 卷是在Docker中持久存储数据的最佳方法。
- Bind mounts(绑定挂载) :可以在任何地方 存储在主机系统上。 它们甚至可能是重要的系统文件或目录。 Docker主机或Docker容器上的非Docker进程可以随时对其进行修改。
- tmpfs mounts(临时挂载) :仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统
上面三种挂载方法可以参照官网
2.1、volume(卷)
- 匿名卷使用
docker run -dP -v :/etc/nginx nginx# docker将创建出匿名卷,并保存容器/etc/nginx下面的内容# -v 宿主机:容器里的目录
- 具名卷使用
docker run -dP -v nginx:/etc/nginx nginx# docker将创建出名为nginx的卷,并保存容器/etc/nginx下面的内容
如果将空卷装入存在文件或目录的容器中的目录中,则容器中的内容(复制)到该卷中。
如果启动一个容器并指定一个尚不存在的卷,则会创建一个空卷。
-v 宿主机绝对路径:Docker容器内部绝对路径:叫挂载;这个有空挂载问题-v 不以/开头的路径:Docker容器内部绝对路径:叫绑定(docker会自动管理,docker不会把他当前目录,而把它当前卷)
以上用哪个比较好?
- 如果自己开发测试,用 -v 绝对路径的方式
- 如果是生产环境建议用卷
- 除非特殊 /bin/docker 需要挂载主机路径的则操作 绝对路径挂载
nginx测试html挂载几种不同情况:
- 不挂载 效果:访问默认欢迎页
- -v /root/html:/usr/share/nginx/html 效果:访问forbidden
- -v html:/usr/share/nginx/html:ro 效果:访问默认欢迎页
- -v /usr/share/nginx/html 效果:匿名卷 (什么都不写也不要加冒号,直接写容器内的目录)
原因:
方式一 :-v html:/usr/share/nginx/html; # 这种方式称为docker自动管理的方式
docker inspect 容器的时候
# -v不以绝对路径方式;# 1、先在docker底层创建一个你指定名字的卷(具名卷) html# 2、把这个卷和容器内部目录绑定# 3、容器启动以后,目录里面的内容就在卷里面存着;
# -v nginxhtml:/usr/share/nginx/html 也可以以下操作# 1、 docker create volume nginxhtml 如果给卷里面就行修改,容器内部的也就改了。# 2、 docker volume inspect nginxhtml# 3、docker run -d -P -v nginxhtml:/usr/share/nginx/html --name=nginx777 nginx# 可以看到"Mounts": [{"Type": "volume", //这是个卷"Name": "html", //名字是html"Source": "/var/lib/docker/volumes/html/_data", //宿主机的目录。容器里面的哪两个文件都在"Destination": "/usr/share/nginx/html", //容器内部"Driver": "local","Mode": "z","RW": true, //读写模式"Propagation": ""}]
# 卷:就是为了保存数据docker volume # 可以对docker自己管理的卷目录进行操作; /var/lib/docker/volumes(卷的根目录)
# 一行命令启动nginx,并且配置文件和html页面。需要知道卷的位置才能改docker run -d -P -v nginxconf:/etc/nginx/ -v nginxpage:/usr/share/nginx/html nginx# 想要实现 docker run -d -P -v /root/nginxconf:/etc/nginx/ -v /root/nginxhtml:/usr/share/nginx/html --name=nginx999 nginx# 1、提前准备好东西 目录nginxconf,目录里面的配置we年都放里面,,再调用命令# 2、docker cp nginxdemo:/etc/nginx /root/nginxconf #注意/的使用# 3、docker run -d -P -v /root/nginxconf:/etc/nginx/ -v /root/nginxhtml:/usr/share/nginx/html --name=nginx999 nginx
2.2、bind mount
如果将绑定安装或非空卷安装到存在某些文件或目录的容器中的目录中,则这些文件或目录会被安装遮盖,就像您将文件保存到Linux主机上的/ mnt中一样,然后 将USB驱动器安装到/ mnt中。在卸载USB驱动器之前,/ mnt的内容将被USB驱动器的内容遮盖。 被遮盖的文件不会被删除或更改,但是在安装绑定安装或卷时将无法访问。总结:外部目录覆盖内部容器目录内容,但不是修改。所以谨慎,外部空文件夹挂载方式也会导致容器内部是空文件夹
docker run -dP -v /my/nginx:/etc/nginx:ro nginx# bind mount和 volumes 的方式写法区别在于# 所有以/开始的都认为是 bind mount ,不以/开始的都认为是 volumes.
警惕bind mount 方式,文件挂载没有在外部准备好内容而导致的容器启动失败问题
3、管理卷
docker volume create xxx:创建卷名docker volume inspect xxx:查询卷详情docker volume ls: 列出所有卷docker volume prune: 移除无用卷
4、docker cp
cp的细节
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- :把容器里面的复制出来
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH:把外部的复制进去
案例:
二、Docker网络
1、端口映射
2、容器互联
--link name:alias ,name连接容器的名称,alias连接的别名
场景:我们无需暴露mysql的情况下,让web应用使用mysql;
3、自定义网络
3.1、默认网络原理
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);
Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
原理:
1、每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。桥接网卡
2、每启动一个容器linux主机多了一个虚拟网卡。
3、docker run -d -P --name tomcat --net bridge tomcat:8
3.2、网络模式
3.3、自建网络测试
# 1、docker0网络的特点。,默认、域名访问不通、--link 域名通了,但是删了又不行
#2、可以让容器创建的时候使用自定义网络1、自定义创建的默认default "bridge"2、自定义创建一个网络网络docker network create --driver bridge --subnet 192.168.0.0/16 --gateway192.168.0.1 mynet所有东西实时维护好,直接域名ping通docker network connect [OPTIONS] NETWORK CONTAINER
# 3、跨网络连接别人就用。把tomcat加入到mynet网络docker network connect mynet tomcat效果:1、自定义网络,默认都可以用主机名访问通2、跨网络连接别人就用 docker network connect mynet tomcat
# 4、命令1、容器启动,指定容器ip。 docker run --ip 192.168.0.3 --net 自定义网络2、创建子网。docker network create --subnet 指定子网范围 --driver bridge 所有东西实时维护好,直接域名ping同3、docker compose 中的网络默认就是自定义网络方式。
文末惊喜:
马东:随着时间的流逝我们终究会原谅那些曾经伤害过我们的人
蔡康永:那不是原谅,那是算了
【与云原生的故事】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/345260
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)