docker基础学习总结
抽时间从网上找资料学习了docker基本知识,做了这个总结,总结有点乱,仅作为啥时忘了什么操作看看这篇文章温习一下之目的。
一:容器基本知识
1 容器隔离:UTS隔离,mount隔离,IPC隔离,PID隔离,用户用户组隔离,网络隔离。容器里边的进程PID彼此也是隔离的。容器IPC在内核里实现,容器里边的进程可以彼此通信,容器与容器之前的进程不能同喜。这些隔离通过namespace实现,setns()这个系统调用,把内核的线程放到容器里
2 LXC:linux container,容器引擎,把完整的容器技术用一组简易工具和模板,极大简化了容器使用的一个方案,否则得手动执行serns()进行UTS隔离,mount隔离,IPC隔离,PID隔离,用户用户组隔离,网络隔离,LXC把这些全做了
3 LXC 有个缺点,把容器迁移到其他宿主机上很难,批量部署容器也很难。早期docker的出现为了弥补这个缺点,是LXC的二次封装(1-52),把一个容器需要文件系统打包成镜像,直接使用,基于镜像启动容器,docker极大简化了容器的使用难度。大部分用到的容器镜像在docker仓库都有,直接下载,run就能用。一个容器只运行一个业务进程,LXC把一个容器当成一个独立的用户空间
4 容器就是启动一个进程,容器停止了,进程就没了,容器不需要持久
5 新版的容器引擎是libcontainer,即runC ,遵循容器运行时的标准,OCI
二:容器安装
下载 docker ce开源版
yum repolist 看到的extras 这个仓库中有docker
vim /etc/yum.repos.ddocker-ce.repo
%s@https://download.docker.com/@https://mirrors.tuna.tsinghua.edu.cn/docker-ce/@
dokcer默认下载源替换为清华大学yum源,加快下载速度
修改完后 yum repolist可以看到
docker-ce-stable/x86_64 Docker CE Stable - x86_64 79
之后运行yum install docker-ce一次性自动安装完成了
docker-ce.x86_64 3:19.03.12-3.el7
container-selinux.noarch 2:2.119.2-1.911c772.el7_8
containerd.io.x86_64 0:1.2.13-3.2.el7
docker-ce-cli.x86_64 1:19.03.12-3.el7
下载完成后,执行systemctl start docker.service 启动docker服务
手动下载安装的话,登录,非常麻烦,破事特别多
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/Packages/docker-ce-17.12.1.ce-1.el7.centos.x86_64.rpm
为了提高从docker hub来去镜像的速度,要用镜像加速器 docker cn
/etc/docker/ daemon.json 文件"registry-mirrors":必须是空格,否则导致systemctl start docker失败
{
“registry-mirrors”: [“https://registry.docker-cn.com”,“http://hub-mirror.c.163.com”]
}
配置 https://registry.docker-cn.com 这样从docker官网拉镜像网速很快
codker hub上docker tag有alpine,说明这是精简的docker镜像
三:docker基本操作命令
docker search busybox 搜索docker官网的busybox容器
docker image pull busybox 拉最新镜像
docker image pull busybox:1.14 指定版本
docker image ls 显示当前已有的镜像
docker image rm busybox
docker image ls --no-trunc 显示docker镜像的完整sha值
docker container 创建/删除/启动/停止/运行/查看/暂停 容器
docker run –-name busybox_hu -it -rm busybox 启动busybox容器,it交互模式
docker ps 查看运行的容器
docker inspect busybox_hu 查看容器更详细的信息
exit 停止容器
docker ps –a 查看停止的busybox容器
docker start -i –a busybox_hu 启动停止的容器
docker kill busybox_hu 强制容器停止,沙雕,stop退出容器
docker rm busybox_hu 彻底删除容器
docker image pull redis:5.0.9-alpine
docker run --name redis_hu -d redis:5.0.9-alpine 后台运行redis容器里的redis_server,这种容器没有shell吧,所以不能直接-it指定交互???,reids容器只是一个简单的进程,没有shell,需要指定shell才能交互。
docker inspect busybox 后可以看到容器的启动命令
“Cmd”:
[
“sh”
],
docker inspect redis
“Cmd”:
[
“/bin/sh”,
“-c”,
“$STI_SCRIPTS_PATH/usage”
],
docker exec -it redis_hu /bin/sh 与正在运行的redis容器开始交互,交互shell是/bin/sh
docker rm redis_hu //删除容器后才能重新run
docker run --name redis_hu -d redis:5.0.9-alpine
docker logs redis_hu 查看容器运行日志
四:容器文件系统
容器最底层的文件系统称为bootfs,lxc、aufs、averlayfs,devicemapper,bootfs引导完容器会被卸载移除系统
在bootfs之上,是rootfs,这个就是容器的根文件系统。容器的根文件系统始终只读,可以通过联合挂载额外挂载一个读写层。好像Centos启动时,先是把rootfs挂载成只读,自检后重新挂载成读写吧。
容器里文件系统分了多层,最上一层的可写层,才允许写。为了支持多层文件系统,必须用分层文件系统,多用overlay2fs,这是一个抽象文件系统,需要建立在ext4之上。
除了docker hub,还有其他的站点下载docker镜像,比如quay,此时需要特别指明站点,因为默认站点是docker hub
Docker pull quay.io/coreos/flannel:v0.10.0-armd64
quay.io: redistry站点
coreos:命名空间
flannel:仓库
五:制作容器镜像
启动进去busybox那个docker,然后mkdir /data/hu –p和touch /data/hu/test,
busybox_hu 要保持运行,不能停止
Docker commit -p busybox_hu制作新镜像
docker image ls
Docker tag 51c3a825e088 busybox/tag:0.1.1 打标签
Docker tag busybox/tag:0.1.1 busybox/tag:latest 再打标签
如果标签错了,还可以docker image rm busybox/tag:latest 然后再重新制作
docker run --name busybox_b2 -it busybox/tag:latest 运行自己制作的镜像,即可看到自己创建的目录,注意
docker comit –c ‘CMD [“/bin/http”,”-f”,”/data/test”]’ –p busybox_hu
这样制作的容器,默认的启动命令CMD不再是shell
Docker container ls 可以查看每个容器的CMD,即默认启动命令
镜像制作后,可以传到网上
在docker hub创建于新的容器一致的标签,标签要一致
Docker login -u mag…
Docker push busybox:… 把镜像推送到了仓库
还可以镜像的导入和导出
docker save -o image.gz busybox/tag:v1.1.0 busybox:latest
把过个容器打包压缩,拷贝到另外的机器上
docker load –i image.gz
docker image ls 就可以看到导入的两个镜像
六:容器存储卷
docker run --name busybox_hu --rm -it -v /data busybox
-v指定docker运行时的一个目录,–rm指定docker运行停止后就删除,一定要这样操作
并且busybox 一定要放到最后边,否则会报错docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused “exec: “-v”: executable file not found in $PATH”: unknown. 也是服了
docker image rm -f busybox_hu 容器有关联关系时,强制删除
之后容器与物理机共享目录,是docker自动在物理机上创建的,如这个宿主机目录
/var/lib/docker/volumes/d81d8bdb34dd24ebc3331c46053b147c24b465d8d9bbf92ef86c480897da9bef/_data/
docker inspect busybox_hu “Mounts” 能看到容器和物理目录映射的详细信息
这是特别指定物理机和容器的绑定目录
docker run --name busybox_hu --rm -it -v /home/docker_test/:/data busybox
这是新创建一个容器,但是存储卷复制了busybox_hu的
docker run --name busybox_hu2 -it --rm --volumes-from busybox_hu busybox
这是新创建一个容器,但是网络和存储卷都复制了busybox_hu的
docker run --name busybox_hu3 -it --rm --network container:busybox_hu --volumes-from busybox_hu busybox
docker ps –a 退出的容器也能看到
docker inspect 只查看一项信息
[root@localhost _data]# docker inspect -f {{.Mounts}} busybox_hu
[{bind /home/docker_test /data true rprivate}]
ocalhost _data]# docker inspect -f {{.NetworkSettings.IPAddress}} busybox_hu
172.17.0.2
七:存储卷的补充
Docker存储卷,说白了就是容器中的一个或者多个目录,绕开docker本身根文件系统,与宿主机之上的目录建立绑定关系。
Docker 存储卷,默认在容器删除时,实现数据持久化。但是通过特定的命令,也可以删除data valume
Docker存储卷有两种类型:
与物理机目录bind形成的volume, 如docker run –it --name busybox –v /home/test:data busybox;
docker manage volume,由docker自动管理的,只用指定容器中的目录,dockker自动在/var/lib/docker/指定一个随机目录,用户无法指定目录,docker run –it --name busybox –v data busybox. /var/lib/docker/volumes/4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee/_data busybox 就是docker随机选择的,4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee 是卷ID
“Mounts”: [
{
“Type”: “volume”,
“Name”: “4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee”,
“Source”: “/var/lib/docker/volumes/4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee/_data”,
“Destination”: “data”,
“Driver”: “local”,
“Mode”: “”,
“RW”: true,
“Propagation”: “”
}
],
[root@localhost ~]# docker inspect -f {{.Mounts}} ea367ab53172
[{volume 4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee /var/lib/docker/volumes/4e2086eafe9894b489d69f74cc0580c32a3cc7062cce2ffc3e77322b584927ee/_data data local true }]
直接查看mount信息
06-40
docker inspect -f {{.NetworkSetting.IPAddress}} ea367ab53172
docker inspect只接获取IP地址
Joined Containers,一个基础容器,其他容器在它基础上赋值基础容器的存储卷,网络
docker run –it --name busybox –network container:busybox_hu --volumes-from busybox_hu busybox
赋值busybox_hu的网络和存储卷
八:设置容器中进程cpu使用率
–cpu-shared 两个进程1024:512分配一个 CPU,按照2:1的比例分配,在两个进程争抢CPU时才按照2:1的比例分配一个CPU,如果后一个进程不用CPU了,另一个进程则可以使用100%的CPU。如果有2个核心,则这个进程可以使用200%的CPU。Cpu-shared只有进程争抢CPU时才生效。总的CPU资源要看分配的CPU个数,2个CPU,就是把200%的CPU按照比例分配。
–cpus 指定容器最多使用的CPU个数,可以半个CPU
–cpuset-cpus 0,1 限制容器只能在CPU0和CPU1上运行
docker pull lorel/docker-stress-ng //获取stresss CPU性能测试工具
docker run lorel/docker-stress-ng -–help //这样直接获取容器的帮助
docker top busybox_hu //查看容器资源
docker stats //查看所有容器资源使用
docker run --name stress -it --rm -m 256m lorel/docker-stress-ng stress -vm 5 //内存使用进行压测
//限制只有两个CPU,256M内存,但是stress使用8个进程,6*256M的虚拟内存,这样使CPU和内存使用超出限制
docker run --name stress -it --rm -m 256m --cpus 2 lorel/docker-stress-ng stress --cpu 8 --vm 6
找到压测进程ID是13048
13048 root 20 0 6908 996 256 R 57.1 0.0 0:38.71 stress-ng-cpu
cat /proc/13048/cgroup 找到 容器ID,也可以inspect看到
4:memory:/docker/bb4cf4e4b2238ff9c24eaaacdacfea711cc92f2fe6abce97a70b16f2e063fc9e
3:cpuset:/docker/bb4cf4e4b2238ff9c24eaaacdacfea711cc92f2fe6abce97a70b16f2e063fc9e
2:cpuacct,cpu:/docker/bb4cf4e4b2238ff9c24eaaacdacfea711cc92f2fe6abce97a70b16f2e063fc9e
根据容器ID找出容器的内存限制
cat /sys/fs/cgroup/memory/docker/bb4cf4e4b2238ff9c24eaaacdacfea711cc92f2fe6abce97a70b16f2e063fc9e/memory.limit_in_bytes
根据容器ID找出容器cgroup限制的进程
cat /sys/fs/cgroup/cpuset/docker/bb4cf4e4b2238ff9c24eaaacdacfea711cc92f2fe6abce97a70b16f2e063fc9e/tasks
docker run -it --name stress --cpus 1 lorel/docker-stress-ng stress --cpu 6 启动CPU测试,只使用一个核,6个线程
stress的CPU使用率是50%
根据进入容器ID cpuset目录
cd /sys/fs/cgroup/cpuset/docker/ca3720b10d18b47ab618a9846ffd504db44b7c51f16712b74fa11ed4a06986fc/
cat cpuset.cpus
0-3
echo 0-1 > cpuset.cpus
0-1
[root@localhost ca3720b10d18b47ab618a9846ffd504db44b7c51f16712b74fa11ed4a06986fc]# cat cpu.cfs_period_us
100000
[root@localhost ca3720b10d18b47ab618a9846ffd504db44b7c51f16712b74fa11ed4a06986fc]# cat cpu.cfs_quota_us
100000
cpu.cfs_period_us是运行周期(微秒),默认为100000,即百毫秒,即100ms。cpu.cfs_quota_us就是在这期间内可使用的cpu时间(微秒),默认-1,即无限制。现在是100ms。
echo 50000 >cpu.cfs_quota_us 后
stress 容器 CPU使用率变为50%
echo 200000 > cpu.cfs_quota_us
stress容器 CPU使用率变为200%
echo 200000 > cpu.cfs_period_us
stress容器 CPU使用率变为100%
echo 100000 > cpu.cfs_quota_us
stress容器 CPU使用率变为50%
echo 500000 > cpu.cfs_period_us
echo 500000 > cpu.cfs_quota_us
stress容器 CPU使用率变为200%,看来最多只能使用两个CPU
top显示stress里的容器均分这200%的CPU,容器中的进程均分分配的总的CPU资源
8775 root 20 0 6908 2144 252 R 33.2 0.1 36:23.54 stress-ng-cpu
8776 root 20 0 6908 2144 252 R 33.2 0.1 36:29.90 stress-ng-cpu
8777 root 20 0 6908 2144 252 R 33.2 0.1 35:44.76 stress-ng-cpu
8778 root 20 0 6908 2144 252 R 33.2 0.1 35:49.92 stress-ng-cpu
8779 root 20 0 6908 2144 252 R 33.2 0.1 36:19.20 stress-ng-cpu
8780 root 20 0 6908 2144 252 R 33.2 0.1 35:21.24 stress-ng-cpu
echo 0 > /sys/fs/cgroup/cpuset/docker/ca3720b10d18b47ab618a9846ffd504db44b7c51f16712b74fa11ed4a06986fc/cpuset.cpus
设置只能使用1个CPU后,stress容器CPU使用率是100%,毕竟限制了最多只能使用1个CPU,最多只有100%
如果我想让stress容器CPU使用率大于200%,该怎么设置
docker run -it --name stress2 --cpus 2 lorel/docker-stress-ng stress --cpu 6
设置可以最大2核,6个线程
[root@localhost 225097c88d3bd08c6d52950f04c2fba3218969d1dffc7295837864e5489e4c19]# top
top - 16:37:41 up 5:30, 7 users, load average: 1.59, 3.18, 3.81
Tasks: 236 total, 8 running, 228 sleeping, 0 stopped, 0 zombie
%Cpu0 : 47.2 us, 0.9 sy, 0.0 ni, 51.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 48.1 us, 0.9 sy, 0.0 ni, 50.0 id, 0.0 wa, 0.0 hi, 0.9 si, 0.0 st
%Cpu2 : 47.2 us, 0.9 sy, 0.0 ni, 50.9 id, 0.0 wa, 0.0 hi, 0.9 si, 0.0 st
%Cpu3 : 48.1 us, 0.0 sy, 0.0 ni, 51.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
由于没有cpuset限制在哪些CPU上,所以是4个CPU集合下来总CPU达到200%
有一个更神奇的发现
cd /sys/fs/cgroup/cpu,cpuacct/docker/a4310e21800ec7f6fa2f888fa06d5b79fbfee86e124034b0826cce17a0ec3d0b
cat cpu.cfs_period_us
100000
cat cpu.cfs_quota_us
200000
如果运行busybox不设置cpuset和cpus,那cpu.cfs_quota_us是-1。如果只指定cpus=1,那cpu.cfs_quota_us是100000,如果cpus=2,则cpu.cfs_quota_us就是现在看到的200000。原来docker cpus=2 这些是通过cpu.cfs_quota_us 实现的使用多少个CPU呀?
docker run -it --rm --name stress3 --cpus 3 lorel/docker-stress-ng stress --cpu 6 指定3个cpu
[root@localhost a61d822725900f8e196d1c2067eb0f10b143bb5ac5e31d23211690293ad9857f]# cat cpu.cfs_period_us
100000
[root@localhost a61d822725900f8e196d1c2067eb0f10b143bb5ac5e31d23211690293ad9857f]# cat cpu.cfs_quota_us
300000
看来真是这样了
top
top - 16:49:26 up 5:42, 7 users, load average: 3.19, 2.80, 3.30
Tasks: 237 total, 7 running, 230 sleeping, 0 stopped, 0 zombie
%Cpu0 : 72.9 us, 0.3 sy, 0.0 ni, 26.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 74.9 us, 0.0 sy, 0.0 ni, 25.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 74.5 us, 0.7 sy, 0.0 ni, 24.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 74.0 us, 0.3 sy, 0.0 ni, 25.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 3871288 total, 2871840 free, 469328 used, 530120 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 3097544 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15114 root 20 0 6908 3924 252 R 66.8 0.1 1:42.18 stress-ng-cpu
15113 root 20 0 6908 3924 252 R 52.5 0.1 1:39.64 stress-ng-cpu
15109 root 20 0 6908 3924 252 R 49.8 0.1 1:35.08 stress-ng-cpu
15110 root 20 0 6908 3924 252 R 49.2 0.1 1:40.63 stress-ng-cpu
15111 root 20 0 6908 3924 252 R 41.2 0.1 1:40.43 stress-ng-cpu
15112 root 20 0 6908 3924 252 R 40.2 0.1 1:42.55 stress-ng-cpu
echo 100000 > cpu.cfs_quota_us
echo 200000 > cpu.cfs_quota_us
echo 300000 > cpu.cfs_quota_us
echo 400000 > cpu.cfs_quota_us
设置不同的cpu.cfs_quota_us,docker stress的CPU使用率跟着变化。
[root@localhost a61d822725900f8e196d1c2067eb0f10b143bb5ac5e31d23211690293ad9857f]# cat cpuset.cpus
0-3
echo 400000 > cpu.cfs_quota_us 后
[root@localhost a61d822725900f8e196d1c2067eb0f10b143bb5ac5e31d23211690293ad9857f]# echo 0-2 > cpuset.cpus
Docker stress的CPU使用率由400%变为300%,因为最多只能使用3个CPU
[root@localhost a61d822725900f8e196d1c2067eb0f10b143bb5ac5e31d23211690293ad9857f]# echo 0-1 > cpuset.cpus
Docker stress的CPU使用率由300%变为200%,因为最多只能使用2个CPU
总结
1 cpuset.cpus 限制容器总的CPU个数,配置3个CPU,那容器最多进程使用率只有300%
2 cpu.cfs_period_us 设置容器进程总的运行周期,一般是100000,即100ms。cpu.cfs_quota_us 是容器进程实际运行时间,可以大于cfs_period_us,如果200000,那容器进程CPU使用率达到200%。
3 如果cpuset.cpus配置2个CPU,cfs_period_us是300000,那容器进程CPU使用率是200%,最多两个CPU。