目录
一 简介
二 Docker与OS。
三 dockerfile与镜像制作
四 镜像管理
五 容器管理
六 docker网络
①、HOST模式
②、pass-through模式
六 docker原理
6.1 cgroupe
6.2 存储引擎
6.2.1 overlay2
Docker本身并不是容器,它是创建容器的工具,是应用容器引擎。
内核支持:
Docker需要内核支持,3.10+。
Docker进程:
'/usr/bin/docker'既是server端也是client
docker进程:/usr/bin/docker daemon --storage-driver=overlay -H fd://
docker不制定dameon参数时作为客户端
docker的server和client使用rest进行交互
docker进程的日志:/var/log/message中
dockerfile用来创建一个自定义的image,大概如下
FROM:基于哪个镜像
COPY/ADD:添加文件到镜像中,其中ADD可自动解压压缩包
RUN:执行命令
镜像分层:
1、首先拉取系统Ubuntu基础镜像,可以看到镜像分为一层和一个l目录
[root]# ll
total 8
drwx------ 3 root root 4096 Nov 20 12:26 71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4
drwx------ 2 root root 4096 Mar 21 16:36 l
[root]# ll l
total 4
lrwxrwxrwx 1 root root 72 Nov 20 12:26 6PQV4UADR2JBJWM7UICFYOQ24U -> ../71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/diff
[root]# ls
71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4 l
[root]# cd 71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/
[root]# ls
diff link
[root]# cat link
6PQV4UADR2JBJWM7UICFYOQ24U
可以看到l目录中是一个软连接,把一些较短的随机串链接到镜像层的diff文件夹下,这样做的目的是为了避免达到mount命令参数的长度限制,link文件为随机串的内容。
通过docker image inpect命令查看基础镜像,没有LowerDir表示为基础镜像,MergedDir代表当前镜像层在overlay2存储下的目录
"GraphDriver": {
"Data": {
"MergedDir": "/var/lib/docker/overlay2/71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/merged",
"UpperDir": "/var/lib/docker/overlay2/71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/diff",
"WorkDir": "/var/lib/docker/overlay2/71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/work"
},
"Name": "overlay2"
},
2、下面我们制作一个容器
docker run --name=basecontain -d centos sleep 3600
通过docker inspect命令查看容器的工作目录
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a-init/diff:/var/lib/docker/overlay2/71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/diff",
"MergedDir": "/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/merged",
"UpperDir": "/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/diff",
"WorkDir": "/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/work"
},
"Name": "overlay2"
},
MergeDir的内容即为容器层的工作目录,LowerDir为容器所依赖的镜像层目录,然后我们查看overlay2目录下内容:
[root@ecs-262232 overlay2]# ll -l
total 16
drwx------ 3 root root 4096 Nov 20 12:26 71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4
drwx------ 5 root root 4096 Mar 21 17:12 debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a
drwx------ 4 root root 4096 Mar 21 17:12 debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a-init
drwx------ 2 root root 4096 Mar 21 17:12 l
[root@ecs-262232 overlay2]# ll l
total 12
lrwxrwxrwx 1 root root 77 Mar 21 17:12 2GWJTBKWM6PAJ2SJWGZLLO5ZKZ -> ../debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a-init/diff
lrwxrwxrwx 1 root root 72 Mar 21 17:12 3MUS5ZHYSPFXOFHHHVCMZM2UC7 -> ../debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/diff
lrwxrwxrwx 1 root root 72 Nov 20 12:26 6PQV4UADR2JBJWM7UICFYOQ24U -> ../71f61a313a0bc153763a7f6f0bdfec10599b34afccacde6e900aab7bd54b00b4/diff
[root@ecs-262232 overlay2]# cd debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a
[root@ecs-262232 debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a]# ls
diff link lower merged work
[root@ecs-262232 debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a]# cd diff/
[root@ecs-262232 diff]# ls
[root@ecs-262232 diff]# mount | grep overlay
overlay on /home/wyk/docker/overlay2/merge type overlay (rw,relatime,lowerdir=./lowerdir,upperdir=./upperdir,workdir=./work)
overlay on /var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/2GWJTBKWM6PAJ2SJWGZLLO5ZKZ:/var/lib/docker/overlay2/l/6PQV4UADR2JBJWM7UICFYOQ24U,upperdir=/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/diff,workdir=/var/lib/docker/overlay2/debb541edb112d3847f1c77771903c0a5c8f95537bbcd9060ea325feaea2af2a/work)
可以看到多了一层容器层目录,link文件同镜像层的link文件(为当前层的随机串3MUS5ZHYSPFXOFHHHVCMZM2UC7),但多了一个lower文件内容为镜像层目录(l/2GWJTBKWM6PAJ2SJWGZLLO5ZKZ:l/6PQV4UADR2JBJWM7UICFYOQ24U)。
我们也可以看到多了一个init层,结构如下图,原因:init 层是一个以“-init”结尾的层,夹在只读层和读写层之间。Init 层是 Docker 项目单独生成的一个内部层,专门用来存放 /etc/hosts、/etc/resolv.conf 等信息。需要这样一层的原因是,这些文件本来属于只读的 Ubuntu 镜像的一部分,但是用户往往需要在启动容器时写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改。可是,这些修改往往只对当前的容器有效,我们并不希望执行 docker commit 时,把这些信息连同可读写层一起提交掉。所以,Docker 做法是,在修改了这些文件之后,以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层,所以是不包含这些内容的。
[root]# tree -L 2
.
├── diff
│ ├── dev
│ └── etc
├── link
├── lower
└── work
└── work
制作镜像,大概如下:
①、创建dockerfile并准备相关文件及脚本
②、加载基础镜像
③、运行docker build命令制作镜像
docker build -t [image name] [dockerfile path]
④、镜像制作完成后会自动加载(docker images查看)
⑤、保存镜像:docker save [image name] > [target path]
FROM ubuntu:15.4
COPY . /app
RUN make /app
CMD python /app/app.py
//上述dockerfile代表了四个命令,每一个命令创建一个分层,每一个分层都是前一个分层的增量,
//即不同的地方,不是完整的复制上一个分层,而是相比上一层多的内容。
//当从镜像创建一个容器,就会在底层创建一个可以修改的分层,即容器分层,在容器中的改变只会
//作用在容器分层。
//容器和镜像最大的不同就是顶部的容器分层,所有对容器的修改都保存在容器分层中,一个容器删除
//后,对应的容器分层也会删除,底层镜像保存不变。
装载镜像 :
docker load < [image name]
查看镜像:
docker images有以下信息
REPOSITORY:镜像仓库名称
TAG:镜像标签
IMAGE ID:镜像uuid
CREATE:镜像创建时间
SIZE:镜像大小
docker inspect //查看docker对象的底层基础信息。包括容器的id、创建时间、运行状态、启动参数、目录
//挂载、网路配置等等。另外,该命令也可以用来查看docker镜像的信息
//特例化的两个命令
docker image inspect
docker container inspect
删除镜像:
docker rmi [image name]/[image id]
创建容器:
docker create/run --privileged=true --net=[docker net mode] -m 16g --device /dev/mem --name [docker container name] -tid [docker images name] [command]
:create与run命令的参数几乎一致,其中run为create并运行
:--privileged=true 特权模式
:-tid,t为tty、i为交互、d为detach后台运行,create命令中不能使用-d参数
:[command]为容器启动时执行的命令,若该命令的生命周期结束容器停止运行
启动/停止容器:
docker start/stop [container]/[container id]
进入容器:
docker attach [container name]/[container id]
docker exec -ti [container name]/[container id] /bin/bash
//本质是在容器里面创建一个新的bash进程,可以使用exit命令退出。
容器与宿主机的目录映射:
可用于宿主机与容器之间文件共享或容器中文件固化,使用‘-v'参数
DOCKER_DIR_MAPS="\
-v /opt/host/mnt:/mnt\
-v /xbin:/xbin\
查看容器占用磁盘大小:
使用命令docker ps -s去查看运行的容器的大小,容器的占用分为两大类
1、size容器分层的大小
2、virtual size底层分层+容器分层的大小
多个容器可以共享一些只读镜像数据,如两个容器从一个镜像启动,那么久共享了100%
的只读数据,如果是从不同镜像启动,但是有共同的底层分层,也是共享的。
退出容器:
attach方式:谨慎使用exit命令,使用ctrl+p+q
exec方式:跟传统方式一样
删除容器:
docker rm [container name]/[container id]
docker rm -f [container name]/[container id]//删除运行中的容器
特点:host模式对应容器创建时的"--net=host"参数,这种模式下容器不会拥有独立的Network Namespace,而是与宿主机公用一个Network Namesapce,通过配置容器与宿主机的网络配置文件目录映射,达到公用相同网络配置的目的。
docker create/run --privileged=true -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts --net=host -m 16g --device /dev/mem --name [docker container name] -tid [docker images name] [command]
特点:passthrough模式对应容器创建时的"--net=none"参数,在这种模式下容器拥有独立的Network Namesapce,能实现与宿主机的网络隔离。此时容器直接使用主机的真实网卡,这些网卡划归容器后宿主机不能再使用。
docker create/run --privileged=true -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts --net=none -m 16g --device /dev/mem --name [docker container name] -tid [docker images name] [command]
添加网卡:
pid=`docker inspect --type container -f '{{.State.PId}}' $container`
ip link set $hostveth netns $pid
ip netns exec $pid ip link set dev $hostveth name $containereth
③、bridge模式
特点:在bridge独模式下容器拥有立的Network Namespace,容器内的网络需要自行创建。
docker create/run --privileged=true -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts --net=brigde -m 16g --device /dev/mem --name [docker container name] -tid [docker images name] [command]
可以参考链接:Linux 虚拟网络设备详解之 Bridge 网桥 - 云+社区 - 腾讯云
相关概念:
任务(task):在cgroup中,任务就是一个进程。
控制组(control group):cgroup的资源控制是以控制组的方式实现的,控制组指明了资源的配额限制。进程可以加入到某个控制组,也可以迁移到另一个控制组。
层级(hierarchy):控制组有层级关系,类似树的结构,子节点的控制组继承父控制组的属性(资源配额、限制等)。
子系统(subsystem):一个子系统其实就是一种资源的控制器,比如memory子系统可以控制进程的内存使用。子系统需要加入到某个层级,然后该层级的所有控制组,均受到整个子系统的控制。
概念间的关系:
子系统可以依赖多个层级,当且仅当这些层级没有其他的的子系统,比如两个层级同时只有一个cpu子系统。
一个层级可以附件多个子系统。(一对多的关系,但反过来一对多,需要层级是干净的)
一个任务可以是多个cgroup的成员,但这些cgroup必须位于不同的层级。
子进程自动成为父进程cgroup的成员,可按照需求将子系统移到不同的cgroup。
可以参考如下图:
cpu子系统
cpuacct子系统
cpuset子系统
memory子系统
blkio子系统-block io
基本概念:overlay是一种文件系统,包含两个文件系统,一个upper文件系统,一个是lower文件系统以及两个文件系统合并后的merge。在overlay2,文件lower只是可读的,而upper是可读写的,所有的修改都只会在upper目录中生效,不管文件是来自于upper还是lower。
挂载前目录结构:
├── lowerdir
│ └── fruit
│ ├── apple
│ ├── grape
│ └── mango
├── merge
├── upperdir
│ ├── dairy
│ │ └── milk
│ └── fruit
│ ├── apple
│ └── mango
└── work
使用命令:
mount -t overlay -o lowerdir=./lowerdir,upperdir=./upperdir,workdir=./work overlay ./merge
执行后目录:
├── lowerdir
│ └── fruit
│ ├── apple
│ ├── grape
│ └── mango
├── merge
│ ├── dairy
│ │ └── milk
│ └── fruit
│ ├── apple
│ ├── grape
│ └── mango
├── upperdir
│ ├── dairy
│ │ └── milk
│ └── fruit
│ ├── apple
│ └── mango
└── work
└── work
可以看到,upperdir和lowerdir的文件都出现在merge目录中,当我们在merge目录中进行删除时,删除的如果是lower目录中的文件,实际上并不会真正删除,因为lowerdir只是可读的,而是会在upperdir中创建一个字符文件,文件名为被删除的文件名,即"without"文件,用于忽略被我们删除的文件,此时文件就不会出现在merge目录中。当我们删除只存在于upperdir中文件时,就会直接删除,并不会创建"without"文件。
当我们队merge目录中文件进行读、写时,遵循以下规则: