此文档为翻阅cloudman的每天5分钟玩转docker技术的读书笔记。
基础
容器不关有docker还有core os的rkt、
容器runtime是真正运行容器的地方,runtime需要跟操作系统kernel紧密协作,为容器提供运行环境
,docker曾经的runtime是linux上的lxc,后面docker自己开发了runc,目前runc是docker默认的runtime
rkt是coreos开发的容器runtime.
容器管理工具
lxd是lxc对应的管理工具
runc的管理工具是docker engine,docker engine包含daemon和cli两个部分
rkt的管理工具rkt cli
容器定义工具
docker image是docker容器的模板,runtime依据docker image创建容器
docker file是包含若干命令的文本文件,可以通过这些命令创建出docker image aci与docker image类似,它是coreos开发的rkt容器image格式。
容器仓库
私有仓库:registry
公共仓库:docker hub,Quay.io
容器os
coreos 、atomic、ubuntu core
容器平台技术
容器编排引擎:docker swarm、kubernetes、mesos+mariathon
容器管理平台:rancher、containership、
基于容器的pass:deis、flynn、dokku
容器支持技术
容器网络:docker network、flannel、weave、calico
服务发现:etcd、consul、zookeeper
数据管理:rex-ray
日志管理:docker logs、logspout
安全性:openscap
docker镜像
linux发行版都是由内核空间和用户空间组成,内核空间是kernel,用户空间的文件系统是rootfs,可以简单的说不同linux发行版的主要区别都是rootfs
base镜像:1,不依赖其他镜像,其他应用镜像可以在base镜像的基础上进行扩展,base镜像通常是各linux发行版的docker镜像,如centos、ubuntu、Debian,大部分应用镜像都是在base镜像的基础上进行扩展的。
下载镜像
docker pull centos
查看镜像
docker images centos
正如上面所说base镜像这么小,因为base镜像只有一个rootfs,kernel它是和宿主机共享的,base镜像只是在用户空间和发行版是一致的,内核版本是共享宿主机的kernel的,ubuntu14.04 kernel版本是4.x,但centos7.3kernel版本是3.10,当在ubuntu14.04上跑centos7.3的docker镜像时,centos7.3的内核版本也会变成4.x因为它是共享宿主机内核。
容器只能使用宿主机kernel,不能更改,不能升级,如果应用要求高内核,建议使用虚拟机。
docker镜像采用分层的结构。基于docker file文件,你每做的操作其实都是在base镜像上加一层,每安装一个软件就是在现有镜像基础上增加一层,这样做的好处时,一个共享资源
比如:有多个镜像都从相同的base镜像构建出来,那宿主机只需要一个base_image,多个镜像共享一个base镜像当某个容器镜像修改基础镜像内容时,会将基础镜像的内容像copy一份到应用镜像内,然后在修改应用镜像内的数据,这根前面说的ceph的快照和clone是一样的,都是使用的cow(copy on write)技术
当容器启动时,会有一层可写层在容器顶部叫容器层,所有对容器的改动,无论添加、删除,修改文件都会发生的容器层中,容器层下面是镜像层,镜像层是只读的。
构建镜像
docker commit
在对原镜像做修改后使用docker commit将生成一个新镜像。
docker commit 原镜像名 新镜像名
Dockerfile
Dockerfile是一个文本文件记录镜像构件的步骤
如Dockerfile为
FROM centos
RUN yum install vim -y
docker build
-t 为新镜像名字
.为指定当前目录为build context,docker 会从build context中寻找Dockerfile
-f可以手动指定Dockerfile的文件
如果Dockerfile不在本地
可以看见启动一个3d799f4的临时容器,然后在临时容器中安装vim,安装成功后将临时容器保存为镜像,最后删除临时容器。
查看容器分层
docker history 镜像名
镜像的缓存特性
docker会缓存已有的镜像的镜像层,如果镜像存在就直接使用,不用创建,如果不希望使用缓存镜像则在docker build时加上–no-cache参数
docker镜像的上层是依赖下层的,只要下层发生变化,上层也会根着变。
如果在build某一步中出错了,可以通过docker run -it 先进上一步生成临时镜像进行调试。
搭建docker私有镜像仓库
从docker hub上下载registryv2.3.1的私有仓库镜像
docker pull registry:2.3.1
使用htpasswd配置docker私有仓库验证
[root@wan_test /]# mkdir /root/auth/
生成验证admin:admin为用户名和密码
1 | docker run --entrypoint htpasswd registry:2.3.1 -Bbn admin admin > /root/auth/htpasswd |
启动私有仓库容器
1 | docker run -d -p 5000:5000 -v /myregistry/:/var/lib/registry -v /root/auth/:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd registry:2.3.1 |
测试登录
先用个错误的帐号密码测试
在用对的
认证以后无法直接在服务器查看curl 127.0.0.1:5000/v2/_catalog
仓库的镜像,会出现报错,但是可以用浏览器输入帐号密码访问。
测试上传镜像
命名要规范格式为
1 | [registry_host]:[port]/[username]/[封装的应用]:[版本] |
docker push上传镜像
默认client是打开ssl的,但Server端没有配置证书,所以先关闭
/usr/lib/systemd/system/docker.service
关闭ssl安全认证
1 | ExecStart=/usr/bin/dockerd --insecure-registry 10.211.55.5:5000 |
systemctl restart docker
测试下载
将本地10.211.55.5:5000/wan/hello-wolrd:v1删除
重新从服务器上pull下来
查看镜像
1 | curl http://10.211.55.5:5000/v2/_catalog |
web页面版的私有镜像管理软件
Portus
harbor
https://www.linuxea.com/1557.html
两种进入容器的方法
docker attach image_id
docker exec -it image_id
区别是,attach进去的还是之前的终端,不会启用新的终端,exec进去是启动一个新的终端。
运行容器的最佳实践
服务类型的容器通过-d以后台的方式启动这类容器
工具类型的直接docker run -it的方式,用完就exit掉
容器的操作
容器在docker host中实际就是一个进程,docker stop命令实际就是向中国进程发送一个SIGKILL信号
docker run –restart=always 表示无论容器因何种原因退出(含正常退出)都立刻重启,–restart=on-failure:3意思是如果启动进程退出代码非0,则重启容器,最多重启3次。
pause/unpause 挂起容器/解除挂起
查看所有exited状态的容器
docker ps -aq -f status=exited
容器资源的限制
docker run时指定
-m或–memory 设置内存的使用限额
–memory-swap设置内存+swap的使用限额。
1 | docker run -m 200M --memory-swap=300M centos |
其含义是该容器最多使用200M内存和100M swap,因为–memory-swap是memory+swap所以前面指定的-m后面swap等于300-200, 默认情况下这两组参数都是-1,不是不限制。
只指定定了-m没指定–memory-swap时默认–memory-swap是-m的两倍。
使用progrium/stress镜像测试,只要线分配给线程的内存大小在可分配范围(300M)内,镜像就会一直工作
1 | docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 180M |
如果超过了,容器马上回报错退出
cpu限额
cpu限额限制的不是实际cpu的使用量,资源的优先级,也就是,在cpu资源紧张时,优先级高的获的的cpu时间片要长一些
docker cpu限制参数
–cpuset-cpus=”” 允许使用的 CPU 集,值可以为 0-3,0,1
-c,–cpu-shares=0 CPU 共享权值(相对权重)
cpu-period=0 限制 CPU CFS 的周期,范围从 100ms~1s,即[1000, 1000000]
–cpu-quota=0 限制 CPU CFS 配额,必须不小于1ms,即 >= 1000
–cpuset-mems=”” 允许在上执行的内存节点(MEMs),只对 NUMA 系统有效
cpu-shares
通过–cpu-shares设置容器cpu配额,默认为一个core为1024,二个为2048,依次类推,设置为0,系统将会按默认值配置,假定一个1core的运行3个container,其中一个cpu-shares为1024,另外两个为512则,当cpu忙碌时,1024的占用50%cpu时间,512的分别占用25%,当增加一个1024的contain时,占用比为1024+1024+512+512 =3072 每个container占用cpu时间比为 1024/3072=33% 1024/3072=33% 512/3027=17% 512/3072=17%
比如在host上启用两个容器
1 | docker run --name container_a -it --cpu-shares 2048 progrium/stress --cpu 2 |
1 | docker run --name container_b -it --cpu-shares 1024 progrium/stress --cpu 2 |
–cpu 有多少核,就写多少 ,这里设置为2
可以看见container_a的cpu资源消耗是container_b的两倍
paush container_a,此时container_b又会将cpu整格cpu占满
block io限制
block io是用来限制容器的磁盘的读写,针对bps(每秒读写的数据量)和iops(每秒IO的次数),控制容器的读写磁盘的带宽。
限制block io的参数
目前block io限额只对dicectIO(不使用文件缓存)有效。
测试
先在容器内使用dd测试bps
run一个centos的镜像
docker run -itd centos
限制前
进入centos镜像
docker exec -it 15643e5ec7d9 /bin/bash
限制io为30M后
1 | docker run -itd --device-write-bps /dev/sda:300MB centos |
实现容器的底层技术
曾经docker的runtime是linux内核自带的lxc,后面docker重新开发了自己的runtime,runc,目前docker通过cgroup实现资源限制,如上面的限制cpu资源、限制memory资源、限制blockIO资源大都是通过linux底层的cgroup实现,namespace实现资源隔离,每个容器独立的文件系统,网卡资源等是通过linux底层的namespace,openstack neutron的 多租户隔离qroute和qdhcp也是通过namespace去实现的。
linux下6种namespace资源
docker存储
容器镜像的分层结构
容器镜像
1、镜像由一个base镜像+若干个只读镜像+一个可写的容器层,这种分层架构最大的特性建设copy-on-write。
2、对数据的修改都是在容器层完成的,新修改的数据都会放在最上层容器层。
3、修改数据时,如果容器层没有,会先从其他层将数据copy到容器层,然后在修改。此时镜像层数据保持不变。
4、如果有多个层有命名相同的文件,用户只能看见最上层中的文件。
分层结构是由linux store driver提供,docker支持多种storage driver 如 AUFS、Device Mapper、Btrfs、OverlayFs、VFS、ZFS,ubuntu默认是AUFS、centos7默认是OverlayFs , docker默认使用linux 发行版的storage driver
docker info可以看见
有些容器创建和销毁,不依赖原有数据,有些容器创建时需要加载已有数据,销毁时希望保留之前产生的数据,这类容器就需要用到容器持久化存储
Data volume
Data volume 本质是 Docker Host 文件系统中的目录或文件,能够直接被mount到容器的文件系统中
特点:
1、Data volume是目录或文件,不是块设备
2、容器可以读写volume中的数据
3、volume的数据因为在host上,但容器被销毁时,不会影响数据,所以它是可以持久保存的。
在使用上,软件放在镜像层内,软件的数据如web Server的网页,数据库的数据这些放在Data volume上
因为data volume是宿主机的一部分,所以目前volume无法设置容量。
docker提供两种类型volume
bind mount:宿主机上已经存在的目录或文件mount到容器。
优点:使用起来直观、高效、可以控制目录的读写权限,支持单个文件的mount
缺点:需要指定host 文件系统路径,限制了容器的可移值性,当需要将容器迁到其他host上,如果其他host上没有要mount的数据或数据不在相同目录时,操作会失败。
docker managed volume:与bind mount最大区别是不需要指定mount 源,只需要指定容器内mount的目录。
优点:容器申请 mount docker manager volume时会自动在/var/lib/docker/volumes下生成一个目录,这样的话,容器移值性更好。
缺点:不支持控制读写权限,不支持单个文件mount。
bind mount
在宿主机上创建http目录
mkdir /root/http
echo “My test bind mount” > /root/http/index.html
1 | docker run -d -p 80:80 -v /root/http/:/usr/local/apache2/htdocs httpd |
1 | -v <host path>:<container path> |
1 | curl http://127.0.0.1 |
My test bind mount
将host的index.html更新看看,container内的是否也会根着改变
1 | echo "My test bind mount test_2 " > /root/http/index.html |
1 | curl http://127.0.0.1 |
My test bind mount test_2
设置只读权限,这样就不能在container内对该目录进行修改了。
1 | docker run -d -p 80:80 -v /root/http/:/usr/local/apache2/htdocs:ro httpd |
docker manged volume
manged volume最大特点是不需要指定源,只需要指定mount point就可以了
查看挂载的源
1 | docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd |
告诉docker需要一个volume并将其挂载到/usr/local/apache2/htdocs,这个但这个volume会从哪里来,inspect一下就知道了
manged volume最大特点是不需要指定源,只需要指定mount point就可以了。
1 | docker inspect 79af2997ca68 |
关注mounts信息
1 | 当容器申请 manged volume时docker会在/var/lib/docker/volumes/下生成一个目录xxx/_data这个就是mount源。mount point指向以有的目录,容器内原有的数据会被复制到这个目录中 |
我们可以直接更新宿主机上的数据。
docker managed volume创建过程
1、容器启动时,简单告诉docker 我需要一个volume存放数据,帮我mount到容器xxx目录。
2、docker在/var/lib/docker/volumes/中生成一个随机目录作为mount源。
3、如果内mount的目录已经存在,则将数据复制到mount源。
4、将host上生成的目录挂载的container中。
通过docker volume ls 查看 docker manged volume的容器
docker inspect 查看volume
bind mount和docker managed volume比较
数据共享
容器和宿主机共享数据
1、两种类型的data volume它们均可以实现容器与host之间数据共享。
2、docker cp 或linux的cp命令将host数据cp到容器中。
容器和容器间的数据共享
方法一:
将共享数据放到bind mount的源中然后mount到多个容器中。
如搭建web集群
将宿主机目录共享到3个容器上,curl访问数据都一致 .
修改宿主机文件,3个容器会同时更新。
方法二:
volume container
专门为其他容器提供volume的容器。
专门create出一个容器用来提供volume,volume container的卷可以是bind mount 也可以是docker manged volume。
如创建个容器 将/root/http通过bind mount或docker manged volume的方式挂上去,然后其他容器只需要挂这个容器即可。
创建 volume container
1 | docker create --name vc_data -v /root/http/:/usr/lolca/apache2/htdocs httpd |
因为volume container的作用只是提供数据,它本身不需要处于运行状态
其他容器 volume 使用volume container
查看
[root@wan_test http]# docker inspect web1
1 | "Mounts": [ |
volume container的特点:
(1)与bind mount相比,不必为每一个容器指定host path,所有path都在volume contain 中定义好了,容器只需要与volume container关联,实现了容器与host解偶。
(2)使用 volume container的容器,其mount point是一致的,有利于配置规范的和标准,但也带来一定局限行,使用使要综合考虑。
data-packed volume container
volume container,数据还是在host上 data-packed volume container数据,将数据完全放到volume container中的称为data-packed volume container 。
原理
先将文件ADD 或cp到镜像中,然后在创建docker manged volume
使用Dockerfile build镜像
vim Dokerfile
1 | FROM centos |
查看volume
在dockerfile中指定了读取volume的数据,所以这里就不需要指定volume的mount point了
启动http容器使用 data-packed volume container
docker run -d -p 80:80 –volumes-from vc_data httpd
容器能正确读取volume中的数据,data-packed volume container是自包含的不依赖host提供数据,具有很强移值性,非常合适静态数据的场景,比如应用的配置信息,web Server的静态文件等.
data volume 生命周期
备份
1、备份host上对应的目录。
2、使用一个临时容器挂载目标容器备份。
如创建一个managerd-volume容器
1 | docker run -itd --name App-container1 -v /var/volume1 -v /var/volume2 ubuntu |
编辑些数据
1 | docker exec -it data_volume bash |
1 | cd /var/volume1/ && touch {1..100} |
在宿主机上创建个目录用于存储备份的数据
1 | mkdir /backup |
这条命令启动一个临时容器,这个容器有挂载两个volume一个的宿主机的/backup一个是映射App-container1的目录,这样这个临时容器就有了App-container1和宿主机backup目录,然后将App-container1目录的/var/volume1和/var/volume2目录备份到backup目录。因为backup目录和宿主机是映射的,这样宿主机就有了备份文件。
将本地backup目录和容器内backup目录进行映射然后将/var/volume1和/var/volume2打包备份到backup目录。
可以查看宿主机上目录
[root@wan_test /]# ll /backup/
总用量 112
-rw-r–r– 1 root root 112640 10月 6 19:34 data_volume_2017_10_01.tar
恢复
启动个App-container2将App-container-1的数据恢复 到App-container2中
1 | docker run -itd --name App-container2 -v /var/volume1 -v /var/volume2 ubuntu |
此时App-container2中的/var/volume1和/var/volume2目录是空的
开始恢复
1 | docker run -it --rm --volumes-from App-container2 -v /backup:/backup ubuntu tar -xvf /backup/data_volume_2017_10_01.tar -C / |
查看App-container2的/var/volume1和/var/volume2,数据恢复。
迁移
1、stop原用容器
2、将原目录mount到新容器
销毁
销毁容器不会销毁bind mount
data managed volume销毁需要docker rm -v 或docker volume rm xxx
批量删除
docker volume rm $(docker volume ls -q)
https://yeasy.gitbooks.io/docker_practice/content/network/linking.html