1、Docker存储
1.1、镜像如何存储
1.1.1、Images and layers
Docker映像由一系列层组成。 每层代表图像的Dockerfile中的一条指令。 除最后一层外的每一层都是只读的。 如以下Dockerfile:
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
- 该Dockerfile包含四个命令,每个命令创建一个层。
- FROM语句从ubuntu:15.04映像创建一个图层开始。
- COPY命令从Docker客户端的当前目录添加一些文件。
- RUN命令使用make命令构建您的应用程序。
- 最后,最后一层指定要在容器中运行的命令。
- 每一层只是与上一层不同的一组。 这些层彼此堆叠。
- 创建新容器时,可以在基础层之上添加一个新的可写层。 该层通常称为“容器层”。 对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此薄可写容器层。
1.1.2、Container and layers
- 容器和镜像之间的主要区别是可写顶层。
- 在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。
- 删除容器后,可写层也会被删除。 基础图像保持不变。 因为每个容器都有其自己的可写容器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础映像的访问,但具有自己的数据状态。
下图显示了共享同一Ubuntu 15.04映像的多个容器。
1.1.3、磁盘容量预估
docker ps -s
size:用于每个容器的可写层的数据量(在磁盘上)。
virtual size:容器使用的用于只读图像数据的数据量加上容器的可写图层大小。
多个容器可以共享部分或全部只读图像数据。
从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的两个容器(具有相同的层)共享这些公共
层。 因此,不能只对虚拟大小进行总计。这高估了总磁盘使用量,可能是一笔不小的数目。
1.1.4、镜像如何挑选
- busybox:是一个集成了一百多个最常用Linux命令和工具的软件。linux工具里的瑞士军刀
- alpine:Alpine操作系统是一个面向安全的轻型Linux发行版经典最小镜像,基于busybox,功能比
Busybox完善。 - slim:docker hub中有些镜像有slim标识,都是瘦身了的镜像。也要优先选择
无论是制作镜像还是下载镜像,优先选择alpine类型.
1.1.5、Copy On Write
- 写时复制是一种共享和复制文件的策略,可最大程度地提高效率。
- 如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件。
- 另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。 这样可以将I / O和每个后续层的大小最小化。
1.2、容器如何挂载
- Volumes(卷) :存储在主机文件系统的一部分中,该文件系统由Docker管理(在Linux上是“ / var /lib / docker / volumes /”)。 非Docker进程不应修改文件系统的这一部分。 卷是在Docker中持久存储数据的最佳方法。
- Bind mounts(绑定挂载) 可以在任何地方 存储在主机系统上。 它们甚至可能是重要的系统文件或目录。 Docker主机或Docker容器上的非Docker进程可以随时对其进行修改。
- tmpfs mounts(临时挂载) 仅存储在主机系统的内存中,并且永远不会写入主机系统的文件系统
1.2.1、volume(卷)
匿名卷使用
docker run -dP -v :/etc/nginx nginx
#docker将创建出匿名卷,并保存容器/etc/nginx下面的内容
具名卷使用
docker run -dP -v nginx:/etc/nginx nginx
#docker将创建出名为nginx的卷,并保存容器/etc/nginx下面的内容
如果将空卷装入存在文件或目录的容器中的目录中,则容器中的内容(复制)到该卷中。
如果启动一个容器并指定一个尚不存在的卷,则会创建一个空卷。
1.2.2、bind mount
如果将绑定安装或非空卷安装到存在某些文件或目录的容器中的目录中,则这些文件或目录会被安装遮盖,就像您将> 文件保存到Linux主机上的/ mnt中一样,然后 将USB驱动器安装到/ mnt中。
在卸载USB驱动器之前,/ mnt的内容将被USB驱动器的内容遮盖。 被遮盖的文件不会被删除或更改,但是在安装绑> 定安装或卷时将无法访问。
总结:外部目录覆盖内部容器目录内容,但不是修改。所以谨慎,外部空文件夹挂载方式也会导
致容器内部是空文件夹
docker run -dP -v /my/nginx:/etc/nginx nginx
# bind mount和 volumes 的方式写法区别在于
# 所有以/开始的都认为是 bind mount ,不以/开始的都认为是 volumes.
警惕bind mount 方式,文件挂载没有在外部准备好内容而导致的容器启动失败问题
1.2.3、管理卷
docker volume create xxx:创建卷名
docker volume inspect xxx:查询卷详情
docker volume ls: 列出所有卷
docker volume prune: 移除无用卷
1.2.4、docker cp
cp的细节
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- :把容器里面的复制出来
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH:把外部的复制进去
- SRC_PATH 指定为一个文件
- DEST_PATH 不存在:文件名为 DEST_PATH ,内容为SRC的内容
- DEST_PATH 不存在并且以 / 结尾:报错
- DEST_PATH 存在并且是文件:目标文件内容被替换为SRC_PATH的文件内容。
- DEST_PATH 存在并且是目录:文件复制到目录内,文件名为SRC_PATH指定的名字
- SRC_PATH 指定为一个目录
- DEST_PATH 不存在: DEST_PATH 创建文件夹,复制源文件夹内的所有内容
- DEST_PATH 存在是文件:报错
- DEST_PATH 存在是目录
- SRC_PATH 不以 /. 结束:源文件夹复制到目标里面
- SRC_PATH 以 /. 结束:源文件夹里面的内容复制到目标里面
自动创建文件夹不会做递归。把父文件夹做好
docker cp index.html mynginx4:/usr/share/nginx/html
docker cp mynginx4:/etc/nginx/nginx.conf nginx.conf
2、Docker网络
2.1、端口映射
docker create -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name hello-mysql mysql:5.7
2.2、容器互联
--link name:alias ,name连接容器的名称,alias连接的别名
场景:我们无需暴露mysql的情况下,让web应用使用mysql;
docker run -d -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
docker run -d --link mysql01:mysql --name tomcat tomcat:7
docker exec -it tomcat bash
cat /etc/hosts
ping mysql
2.3、自定义网络
2.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
2.3.2、网络模式
网络模式 | 配置 | 说明 |
---|---|---|
bridge模式 | --net=bridge | 默认值,在Docker网桥docker0上为容器创建新的网络栈 |
none模式 | --net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container模式 | --net=container:name/id | 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Networknamespace。 |
host模式 | --net=host | 容器和宿主机共享Network namespace |
用户自定义 | --net=自定义网络 | 用户自己使用network相关命令定义网络 |
自建网络测试
#1、docker0网络的特点。,
默认、域名访问不通、--link 域名通了,但是删了又不行
#2、可以让容器创建的时候使用自定义网络
1、自定义创建的默认default "bridge"
2、自定义创建一个网络网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.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 中的网络默认就是自定义网络方式。