docker安装及优化详解
- 一、部署20版的docker
- 二、linux 系统中的命令 记10条(cd ls pwd mv cp )
- 三、容器操作
- 四、docker 网络模式-
- 五、如何管理docker容器中的数据
- 六、数据卷容器【容器之间相互挂载】
- 七、⭐⭐dockerfile⭐⭐
- 八、私有仓库建立
- 8.1 在docker 引擎终端设置
- 8.2 Cgroup 资源配置方法
- 8.2.1 使用 Dockerfile 来创建一个基于 Centos 的 stress 工具镜像。
- 报错信息解决方案:unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /opt/stress/Dockerfile: no such file or directory
- 8.2.2 CPU 周期限制
- 8.2.3查询容器的资源限制参数
- 8.2.4 --CPU Core 控制-
- 8.2.5 CPU 配额控制参数的混合使用
- 8.2.6 内存限额
- 8.2.7 Block IO 的限制
- 8.2.8 bps 和 iops 的限制
- 小结:
- 九、 compose部署
一、部署20版的docker
1.1 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
1.2 设置阿里云镜像源
cd /etc/yum.repos.d/
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
1.3 安装docker-ce 社区版
yum install -y docker-ce
#环境配置
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
1.4 关闭增强机制
vim /etc/selinux/config
SELINUX=disabled
1.5 前体准备(开启服务)
systemctl start docker
systemctl enable docker
1.6 设置镜像加速
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://jqqwsp8f.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
#镜像加速注册地址
https://help.aliyun.com/document_detail/60750.html
1.7 网络优化
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
sysctl -p
systemctl restart network
systemctl restart docker
1.7-docker 镜像操作
1.7.1 运行一个容器
运行一个hello-world容器【hello-world在docker仓库里面】
docker run hello-world
run :
① pull dockerhub 仓库中 项目/库/镜像
② start hello-world-image
1、docker client
客户端连接到了服务端
(服务端是以一个守护进程的形式跑在操作系统里面的)restful api
典型的C/S架构。
2、由docker服务端的守护进程
从docker hub 上下载了镜像(PS:服务端会先检查本地系统是否有这个镜像)3、服务端
创建了一个新的容器
,然后从拉去的这个镜像启动了一个容器,容器执行了脚本/可执行程序让我们可以查看/使用(client)4、docker
服务端把这些信息流(传递)返回到客户端并展示出来,
(展示在终端上)
-
docker client 可以是多种形式,比如"docker"命令工具所在的终端
-
yum 仓库,如何开启缓存,软件包保存在哪
二、linux 系统中的命令 记10条(cd ls pwd mv cp )
docker 十条管理命令(运维常用的命令)
2.1 查询docker 版本
docker version && docker info
2.2 搜索镜像
docker search nginx
docker search centos:7
——》自己制作镜像,然后上传到docker hub 上
优化
有效减少镜像大小(dockerfile 优化面试题)
2.3 面试技能点
PS Linux 发行版:
alpine centos redhat Debian(apt包管理,centos 是rpm) 生产环境可能会用的
2.4 下载镜像(默认是从docker hub)
docker pull 镜像名称,例如:
docker pull nginx
2.5 查看镜像列表
docker images——查看当前docker下的下载镜像信息
2.6 获取镜像信息
docker inspect 镜像ID
2.7 添加镜像标签
docker tag nginx:latest nginx:lnmp
2.8 删除
docker rmi 镜像名称
docker rmi 镜像标签
docker rmi `docker images -q`
2.9 镜像导出
docker save -o 文件名 镜像名
示例:
docker save -o nginx_docker nginx:latest
2.10 镜像导入
docker load < nginx
使用场景,有的生产环境,企业不直接使用docker 私有仓库,而是存放在一个ftp服务器中,按需上传下载
应用场景
ftp winscp ssh 登陆VPN
三、容器操作
3.1查询容器
docker ps -a
3.2 创建容器
docker create -it nginx:latest /bin/bash
-i 让容器的标准输入保持打开
-t 分配一个伪终端
-d 后台守护进程的方式运行
3.3 面试题:
容器状态有哪些,分别是什么场景?
up exsit(0 137) created
0:是正常退出
137:是异常退出
3.4 启动容器
docker start 容器id
#启动容器(一次性执行)
docker run centos:7 /usr/bin/bash -c ls /
-c:后面加 调用命令
3.5 停止容器
docker stop 容器ID
3.6 持台后台运行 (一般不停的情况下,磁盘会占满,别做!)
docker run -d centos:7 /bin/bash -c “while true;do echo hello;done”
#进入容器
① 使用run 【一次性进入】(临时使用的)
docker run -it nginx:latest /bin/bash
② exec(容器必须为开启状态)
docker exec -it 容器ID /bin/bash
exec 和shell 是两种运行模式
使用这个方式的,他的退出状态使用:exit 或者ctrl+d 来退出状态
法二:用exec(容器必须要是开启状态)
如果这个容器是关闭状态,n那么就进不去!!!
PS:
docker run -it 会创建前台进程,但是会在输入exit后终止进程。
docker attach 会通过连接stdin,连接到容器内输入输出流,会在输入exit后终止容器进程.
docker exec -it 会连接到容器,可以像SSH一样进入容器内部,进行操作,可以通过exit退出容器,不影响容器运行。【这个方式不是特别常用,因为ssh不安全】
3.7 容器导出
docker export 容器ID > 文件名
示例:
docker export 容器ID > nginx_a
3.8 容器导入(生成镜像)
docker import 导出的文件名(容器) 指定镜像名称
示例:
docker import nginx_a nginx:latest
cat 文件名(容器) | docker import - nginx:latest
3.9 批量删除容器&&批量删除镜像
3.9.1 删除容器
docker rm 容器ID
3.9.2 强制删除容器(正在运行的)
docker rm -f 容器ID
3.9.3 批量删除容器(正则匹配)
docker ps -a | awk ‘{print "docker rm "$1}’ | bash
3.9.4 删除非up状态的 rm -f : 强制删除所有
docker rm
docker ps -q
3.9.5 批量删除“exit”状态(指定状态)的容器
for i in `docker ps -a | grep -i exit | awk '{print $1}'`; do docker rm -f $i;done
created
3.10容器打包为镜像
docker run -it --name Nginx.01 nginx:latest /bin/bash
docker commit 39eaa5aa7332 nginx-v1beta
四、docker 网络模式-
4.1 容器网络(图)
docker0网络
docker容器的 虚拟网关
loopback :回环网卡、TCP/IP网卡是否生效
virtual bridge:linux 自身继承了一个虚拟化功能(kvm架构),是原生架构的一个虚拟化平台,安装了一个虚拟化平台之后就会系统就会自动安装虚拟网卡
(示例:安装workstation (虚拟化平台)之后,会在网络适配器中会多出VMnet1 VMnet8 VMnet0)
docker 0 : 容器的网关,绑定物理网卡,负责做NAT 地址转换、端口映射
docker 0 本身也是一种容器
4.2 docker 五种网络模式
host模式 | –net=host | 容器和宿主机共享Network namespace |
---|---|---|
container模式 | –net=container:NAME_or_ID | 多个容器共享一个Network namespace。 |
none模式 | –net=none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。 |
bridge模式 | –net=bridge | (默认为该模式) |
Overlay模式 | 一般与docker-swarm结合 | (所以建议以了解的角度来结束) |
以上不需要动手配置,真正需要配置的是自定义网络
4.3 docker自定义网络(画图)
4.3.1 Host模式
host容器将不会虚拟出自己的网卡,配置自己的IP等
,而是使用宿主机的IP和端口范围。如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的 .- NetworkNamespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的Ip地址与外界通信
,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT
,host最大的优势就是网络性能比较好,但是dockerhost 上已经使用的端口就不能再用了,网络的隔离性不好。- 解决了ip地址不固定的情况
4.3.2 Container模式
- 创建的容器不会创建自己的网卡,配置自己的IP,而是**
和一个指定的容器共享IP、端口范围(端口不能一致),只有一个容器有自己的网卡
**,出去还是docker0进行通讯 - 有点像各个服务放在同一个宿主机上面这种情况
- 这个模式指定新创建的容器和**
已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信
**
4.3.3 Bridge模式(默认)
此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主之间的关联
- 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看bridge模式是docker的默认网络模式
,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能
。可以使用iptables -t nat -vnL查看
4.3.4 None模式(躺平)
该模式关闭了容器的网络功能
- 使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等
- 这种网络模式下容器 只有lo回环网络,没有其他网卡。 none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性
- 可以安全的储存数据,不会被攻击,可以用来当个仓库
4.4 查看网络列表
docker network ls
4.5 查看容器信息(包含配置、环境、网关、挂载、cmd等等信息)
docker inspect 容器ID
4.6 指定分配容器IP地址
docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
(以上会报错)
4.7 自定义网络固定IP
docker network create --subnet=172.18.0.0/16 mynetwork
docker run -itd --name test2 --net mynetwork --ip 172.18.0.100 centos:latest /bin/bash
4.8 暴露端口
-p 自定义端口 ( 宿主机端口:容器内端口)
-P 随机端口 (-P 49153起始 49153到65535)
docker run -itd -p 333:80 nginx /bin/bash (docker 0)
docker run -itd -P nginx /bin/bash
解决思路:
这样就好了!!!
/bin/bash 也是一个cmd,如果有多个cmd的话,只会有一个命令 生效,而原本的最初的cmd命令是用来开启nginx服务的;【多条cmd,只会有最后一条cmd会生效】所以这里不能加/bin/bash,这样就会导致冲突了!所以会报错,使用docker inspect +id去查看他的cmd命令有哪些。
4.9 在宿主机环境执行容器内命令
docker exec -it 容器ID /bin/bash -c 'nginx'
docker exec 容器ID/容器name 执行的命令
4.10 面试题
怎么把宿主机的文件传入到容器内部
1、linux 怎么复制
cp 原文件路径 目标文件路径
docker cp /opt/abc 容器id:/opt/abc
4.11 进入容器没有systemctl 命令解决:添加–privileged=true (指定此容器是否为特权容器),使用此参数,则不能用attach
示例:
docker run -itd --name test3 --privileged=true centos /sbin/init
/sbin/init 内核启动时主动呼叫的第一个进程
可以使用docker inspect 容器ID
docker ps -a
docker exec -it 容器id /bin/bash
yum install httpd -y
systemctl status httpd
4.12 如何把脚本传入一个已经运行的容器
#使用cp命令复制进去容器
docker cp start.sh test01:/opt
#使用cp命令从容器复制出来
docker cp test01:/opt/start.sh ./
#使用cp命令复制进去容器
#使用cp命令从容器复制出来
五、如何管理docker容器中的数据
管理Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器( DataVolumes Containers) 。
5.1 Docker 数据卷【docker 容器之间如何实现数据共享:通过数据卷】
原理:将容器内部的配置文件目录,挂载到宿主机指定目录下
作用:
① 修改配置文件例如,nginx.conf /usr/local/nginx/conf/nginx.conf —>
/container_nginx/conf/nginx.conf
② 容器内部产生的日志,如何收集将容器内部存方日志文件的目录挂载到宿主机指定目录下/container_nginx/log/access_log/access_log
③ 传入变量 挂载到宿主机 在宿主机上添加变量内容,将变量放入共享目录,在容器中/etc/profile 直接加载就可以export xxdir=/data/data1/xx.
-
数据卷默认会一直存在,即使容器被删除
-
宿主机和容器是两个不同的名称空间,如果想进行连接需要用ssh,exec和attch也类似于ssh这种方式登录
-
在企业中ssh这种登陆方式会比较危险,安全漏洞很大,尽量减少ssh这种,杜绝了频繁使用exec
-
因此使用数据卷的方式把容器内部的文件目录挂载到宿主机指定目录下进行修改,当容器里的文件频繁需要修改时不需要登陆进去,直接使用数据卷方式在宿主机指定的目录下进行修改即可。方便又安全
5.1 应用场景:
需求:宿主机目录/var/www挂载到容器中的/data1
#注意:宿主机本地目录的路径必须是使用绝对路径。如果路径不存在,Docker会自动创建相应的路径。
#-v选项可以在容器内创建数据卷,是volume的缩写
docker run -it --name test01 -v /var/www:/data1 centos:7 bash
##这句话是挂载的意思:-v:就是挂载的意思volume bash是环境 centos:7是运行环境 :后面根版本号
ls
#返回宿主机进行查看
cd /var/www/
ls
#在容器中创建文件
echo "this is test01 file" > /data1/test.txt
#在宿主机查看是否有内容
cat /var/www/test.txt
六、数据卷容器【容器之间相互挂载】
原理:让两个容器实现数据共享
作用:如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器是一个普通的容器,专门提供数据卷给其他容器挂载使用。
需求:创建数据卷容器
#创建一个容器作为数据卷容器【挂载点来自于这个容器】
docker run -it --name test1 -v /data1 -v /data2 centos:7 /bin/bash #创建并进入容器
-v:指定容器位置【容器内部的位置】,创建一个data1和data2目录并把它暴露出来给指定的网段去使用
echo "this is test02 file" > /data1/test.txt #容器内创建测试文件1
echo "THIS IS TEST2 FILE" > /data2/TEST.txt #容器内创建测试文件2
#使用--volumes-from来挂载test2容器中的数据卷到新的容器【新的容器是去使用的挂载点的】
docker run -it --name test2 --volumes-from test1 centos:7 /bin/bash #创建并进入容器
cat data1/test.txt #查看测试数据是否同步
cat data2/TEST.txt
1、创建一个容器作为数据卷容器并创建文件
2、#使用–volumes-from来挂载test2容器中的数据卷到新的容器
总结
如何实现docker持久化
在生成容器的同时,加上-v选项,指定把当前服务器的目录映射到容器中
6.3 端口映射
docker run -d -p 80:80 httpd -d:提供守护进程【保护容器】 -p:自定义端口
docker ps -a
6d461287c25d httpd:centos "/run.sh" 7 seconds ago Up 7 seconds 0.0.0.0:49280->80/tcp zen_swanson
6.4 容器互联(使用centos镜像)
docker run -itd -P --name w1 centos /bin/bash //创建并运行容器取名w1,端口号自动映射【-P:暴露一个随机端口】
docker run -itd -P --name w2 --link w1:w1 centos /bin/bash //创建并运行容器取名w2,链接到w1和其通信
进w2 容器 ping w1
哨兵 ——》监控 redis
哨兵和redis包括哨兵和哨兵之间相互监控,会使用ping命令
七、⭐⭐dockerfile⭐⭐
7.1 创建容器的几种方式
① 基于已有容器进行创建(docker commit)
② 基于已有的镜像进行创建(docker tag)
③基于 dockerfile创建(docker build)
基于本地模板创建(docker load)
7.1.1 dockerfile 结构(四部分)
- 基础镜像信息(Linux发行版:centos ubantu suse debian alpine redhat)
- 维护者信息(docker search可查看)
镜像操作指令(tar yum make)
- 容器启动时执行指令
(cmd["/root/run.sh"] 、entrypoint
都是系统启动时,第一个加载的程序/脚本/命令
)
7.1.2 dockerfile操作指令
指令 | 含义 |
---|---|
FROM [镜像] | 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令,例如centos:7。from有两层含义:①开启一个新的镜像②必须写的一行指令 |
MAINTAINER [名字] | 说明新镜像的维护人信息(可写可不写) |
RUN命令 | 每一条RUN后面跟一条命令,在所基于的镜像上执行命令,并提交到新的镜像中,RUN必须大写 |
CMD [“要运行的程序”,“参数1”、“参数2”] | 指定启动容器时需要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能执行最后一条,“bin/bash”也是一条CMD,并且会覆盖image镜像里面的cmd。 |
EXPOSE [端口号] | 指定新镜像加载到Docker时要开启的端口**(暴露端口)**,就是这个容器暴露出去的端口号。 |
ENV [环境变量] [变量值] | 设置一个环境变量的值,会被后面的RUN使用。容器可以根据自己的需求创建时传入环境变量,镜像不可以。 |
ADD [源文件/目录] [目标文件/目录] | ①将源文件复制到目标文件,源文件要与Dockerfile位于相同目录中,②或者是一个URL,③若源文件是压缩包则会将其解压缩 |
COPY [源文件/目录] [目标文件/目录] | 将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中,copy只能用于复制,add复制的同时,如果复制的对象是压缩包,ADD还可以解压,copy比add节省资源 |
VOLUME [“目录”] | 在容器中创建一个挂载点,简单来说就是-v,指定镜像的目录挂载到宿主机上。 |
USER [用户名/UID] | 指定运行容器时的用户 |
WORKDIR [路径] | 为后续的RUN、CMD、ENTRYPOINT指定工作目录,相当于是一个临时的"CD",否则需要使用绝对路径,例如workdir /opt。移动到opt目录,并在这下面的指令都是在opt下执行。 |
ONBUILD [命令] | 指定所生成的镜像作为一个基础镜像时所要运行的命令**(是一种优化)** |
HEALTHCHECK | 健康检查 |
7.2 dockerfile分层原理
7.2.1 docker镜像分层(基于AUFS构建):
Docker 镜像位于bootfs之上
每一层镜像的下一层成为父镜像
第一层镜像成为base image(操作系统环境镜像)
容器层(可读可写),在最顶层(writable)
容器层以下都是readonly
contaier 读写层
images (只读)
base image
bootfs + rootfs + aufs (kernel)
7.2.2 涉及技术
7.2.2.1 bootfs(boot file system) 内核空间
-
主要包含
bootloader和kernel
-
bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在
Docker镜像的最底层是bootfs
-
这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
-
在linux操作系统中(不同版本的linux发行版本),
linux加载bootfs时会将rootfs设置为read-only
,系统自检后会将只读改为读写
,让我们可以在操作系统中进行操作
7.2.2.2 rootfs (root file system) 内核空间
在bootfs之上(base images,例如centos 、ubuntu)
包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件
rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等
7.2.2.3 小结:为什么docker的centos镜像只有200M多一点
- **
bootfs + rootfs :
**作用是加载、引导内核程序 + 挂载使用linux 操作系统
(centos ubantu)等等一些关键的目录文件 - 因为docker镜像只有rootts和其他镜像层,共用宿主机的linux内核(bootfs),因此很小
对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。
7.2.3 AUFS 与 overlay/overlay2 (docker 高版本)
-
AUFS是一种
联合文件系统
。它使用同一个Linux host上的多个目录,逐个堆叠起来,对外呈现出一个统一的文件系统。AUFS使用该特性,实现了Docker镜像的分层 -
而docker 使用了overlay/overlay2存储驱动来
支持分层结构
-
OverlayFS将单个Linux主机上的两个目录合并成一个目录。这些目录被称为层,统一过程被称为联合挂载
overlay 结构:
overlayfs在linux主机上只有两层,一个目录在下层,用来保存镜像(docker),另外一个目录在上层,用来存储容器信息
1、rootfs 基础镜像
2、lower 下层信息 (为镜像层,只读)
3、upper 上层目录 (容器信息,可写)
4、worker 运行的工作目录(copy-on-write写时复制 -》准备容器环境)
5、mergod “视图层”(容器视图)
通俗理解:
就好像创建一个杯子,你首先设计一个杯子,你先需要有一个模型出来,而
镜像就相当于一个模型
,然后通过这个模型你去设计出这个杯子,杯子这个实体就是容器
。
所以一个镜像可以由多个容器去使用。【一个模型可以设计出n个杯子】
然后我到达容器层的时候其实就是这个被子的模型已经设计出来了,已经开始进行封装了!!
然后我worker层其实就是用来记录我设计的杯子的设计原则的,里面的数据不要修改,基本已经确定好形状了。容器层会把数据拷贝一份到worker层。
7.2.4 容器之间相互通信的方式
docker 0 、 数据卷容器 、
--link 隧道
、 container 模式(直连接口,同一个network namespaces里,通过同一个网卡的方式,在同一个名称空间里 共有一个IP,通过localhost交互/自己的ip或端口交互
)
- docker 0
- 数据卷容器
- link隧道
- container模式
7.2.5 docker 镜像层次结构小结
① base image :基础镜像
② image:固化了一个标准运行环境,镜像本身的功能-封装一组功能性的文件,通过统一的方式,文件格式提供出来
(只读)
③ container:容器层(读写)
④ docker-server 端
⑤ 呈现给docker-client (视图)
在修改时,若upper层没有,则会将lower层有的文件复制到upper层进行修改并保存结果
“小”demon (联合挂载):
[root@node1 mnt]# echo “lower.aaaa” > lower/aaaa
[root@node1 mnt]#
[root@node1 mnt]# echo “lower.bbbb” > lower/bbbb
[root@node1 mnt]#
[root@node1 mnt]# echo “upper.bbbb” > upper/bbbb
[root@node1 mnt]#
[root@node1 mnt]# echo “upper.cccc” > upper/cccc
[root@node1 mnt]# mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged
[root@node1 mnt]# df -hT
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/sda3 xfs 37G 4.2G 33G 12% /
devtmpfs devtmpfs 896M 0 896M 0% /dev
tmpfs tmpfs 911M 0 911M 0% /dev/shm
tmpfs tmpfs 911M 19M 893M 3% /run
tmpfs tmpfs 911M 0 911M 0% /sys/fs/cgroup
/dev/sda1 xfs 1014M 165M 850M 17% /boot
tmpfs tmpfs 183M 12K 183M 1% /run/user/42
tmpfs tmpfs 183M 0 183M 0% /run/user/0
overlay overlay 37G 4.2G 33G 12% /var/lib/docker/overlay2/d00640d71009bfb6bb39562ff5a707bb59775a90fde92bc86aca3985fe1aae4a/merged
overlayfs:/overlay overlay 37G 4.2G 33G 12% /mnt/merged
[root@node1 mnt]# tree .
.
├── lower
│ ├── aaaa
│ └── bbbb
├── merged
│ ├── aaaa
│ ├── bbbb
│ └── cccc
├── upper
│ ├── bbbb
│ └── cccc
└── work
└── work
5 directories, 7 files
GB 大的镜像()
PS:
每次推送到docker hub 只推送增量部分(底包毕竟大,增量推送给/更新部分比较小)
所以生产上,只要你执行的镜像再推送的时候增量部分控制到比较小的一个范围就可以
7.2.6 dockerfile 编写组成
Dockerfile是由一组指令组成的文件
Dockerfile结构四部分
1.基础镜像信息 (指定操作系统镜像是什么镜像、什么版本)
2.【维护者信息】 ()
3.镜像操作指令 ()
4.容器启动时执行指令 (启动容器的时候,执行的脚本/命令参数等等)
Dockerfile每行支持一条指令,每条指令可携带多个参数,通过&&;支持使用以“#“号开头的注释
7.2.6.1 构建镜像命令(ps:可在构建镜像时指定资源限制)
示例:
docker build -t nginx:test .
-t : tag 打标签
-f : 指定dockerfile 目录
. : 指构建镜像时使用的环境(当前)目录,构建镜像时使用的上下文环境
7.2.7 面试题:
7.2.7.1 CMD 【不可以传参】与entrypoint【可以传参】区别
:都是容器启动时要加载的命令; 容器启动时,先启动exec在使用shell
exec 模式 与shell模式
exec: 容器加载时使用的启动的第一个任务进程pid
shell: 容器加载时使用的第一个bash环境(/bin/bash /bin/sh /bin/init)
自检完成后,加载第一个pid = 1 进程
shell 翻译官/解释器,解析
echo $PATH
dockerfile里面的指令都是要大写的
;多个cmd只有第一条会生效
小demon示例:
[root@node1 test]# vim Dockerfile
FROM centos:7
CMD ["top"] #容器只要启动好,就执行top
[root@node1 test]# docker build -t centos:test001 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM centos:7
---> f3f09806d529
Step 2/2 : CMD ["top"]
---> Running in 780cc8c73a3b
Removing intermediate container 780cc8c73a3b
---> ec98bd6ee8ef
Successfully built ec98bd6ee8ef
Successfully tagged centos:test001
[root@node1 test]# docker run -itd --name test centos:test001 [/bin/bash]
fa24189908f772bbad3f19cbe5438adbeb69c27b3160bebb33a4d4967584db50
[root@node1 test]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fa24189908f7 centos:test001 "top" 2 seconds ago Up 2 seconds test
938f257a5dae nginx:latest "/docker-entrypoint.…" 8 hours ago Up 8 hours 80/tcp thirsty_hofstadter
[root@node1 test]# docker exec test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.4 0.1 56156 1948 pts/0 Ss+ 11:59 0:00 top
root 8 0.0 0.0 51732 1704 ? Rs 11:59 0:00 ps aux
#而使用exec模式是无法输出环境变量的
示例:
[root@node1 test01]# cat Dockerfile
FROM centos:7
CMD ["echo","$HOME"]
[root@node1 test01]# docker run --rm centos:v1 ##--rm 一次性运行(删除)
$HOME
##shell模式
[root@node1 test01]# cat Dockerfile
FROM centos:7
CMD ["sh","-c","echo $HOME"]
[root@node1 test01]# docker run --rm centos:v2
/root
/bin/sh -c nginx shell 模式
nginx exec模式
cmd 是容器环境启动时默认加载的命令
entrypoint 是容器环境启动时第一个加载的命令程序/脚本程序 init
init pid 1
7.2.7.2 cmd与entrypoint的区别 小结:
-
如果
ENTRYPOINT 使用了 shell 模式
,CMD 指令会被忽略
。 -
如果
ENTRYPOINT 使用了 exec 模式
,CMD 指定的内容被追加为 ENTRYPOINT 指定命令
的参数。 -
如果
ENTRYPOINT 使用了 exec 模式
,CMD 也应该使用 exec 模式
。
nginx -s reload
nginx -s start 服务器自带的控制方式
exec和shell的区别就是;exec不能识别传参;而shell是可以识别传参的!
Dockfile容器是干嘛的:就是用来制作镜像的
!
相同点: cmd和entrypoint都是容器运行时加载的第一个命令/程序
(pid 1)
不同点: cmd中识别最后一条
;entrypoint识别第一条
;如果cmd和entrypoint同时存在,如果是exec模式,那么cmd的内容会作为参数传给entrypoint;如果是shell模式,那么entrypoint会覆盖cmd;
entrypoint ["sh","-c","echo $HOME"]
#cmd ["restart"] ##只有命令词和参数
nginx restart
#####参数
基于基础镜像 (centos 需小写)
mkdir nginx
cd nginx/
//拷贝nginx-1.12.2源码包到 nginx/中
vim Dockerfile
FROM centos:7 #[from 是一个指令,每个命令构成一个镜像,镜像是分层的,所以这一层是 基础镜像]
#用户信息(可选)【可忽略,选名字的】
MAINTAINER this is nginx image
#添加环境包【如果都分开写,它的镜像层多了,他的占用空间就大了,后期为了优化,那么就写成一条】 [一条指令可以用&& 方式,去写多条指令]
RUN yum -y update # RUN是一个指令,执行后面的命令 【这边就是镜像层】
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make ## gcc是nginx的编译环境
RUN useradd -M -s /sbin/nologin nginx # 给nginx创建一个专属用户
#传入、解压nginx软件包
ADD nginx-1.12.2.tar.gz /usr/local/src # add是用来复制并解压的 ,放到/usr/local/src下
VOLUME ["/usr/local/nginx/html"]
WORKDIR /usr/local/src
#指定工作目录
WORKDIR nginx-1.12.2
RUN ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_stub_status_module && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
#指定http和https端口
EXPOSE 80
RUN echo "daemon off;">>/usr/local/nginx/conf/nginx.conf
CMD nginx
7.2.7.3 ADD和copy区别
Dockerfile中的COPY指令和ADD指令都可以将主机上的资源复制或加入到容器镜像中
,都是在构建镜像的过程中完成的.
-
copy只能用于
复制
(节省资源) -
ADD复制的同时,如果复制的对象时压缩包,
ADD还可以解压
(消耗资源) -
COPY指令和ADD指令的**
唯一区别在于
**是否支持从远程URL获取资源。COPY指令只能
从执行docker build所在的主机上读取资源并复制到镜像中
。而ADD指令还支持通过URL从远程服务器读取资源并复制到镜像中
-
满足同等功能的情况下,推荐
使用COPY指令
。ADD指令更擅长读取本地tar文件并解压缩
7.2.8 基于dockerfile文件构建镜像命令
完整的写发: docker build -f /opt/dockerfile -t nginx:new .
docker build : 基于dockerfile 构建镜像
-f :指定dockerfile 文件(默认不写的话指的是当前目录)
-t :(tag) 打标签 ——》nginx:new
. :专业说法:指的是构建镜像时的上下文环境,简单理解:指的当前目录环境中的文件
docker build -t nginx:v1
.
# 创建镜像docker run -d -P nginx:v1
docker ps -a
7.2.9 小结: 构建nginx 镜像
① 创建一个对应的目录(mkdir nginx)
② 编写Dockerfile 文件(最简单的方式,nginx部署脚本 放进去
每条命令用RUN 执行,环境变量使用ENV,移动到对应 目录使用workdir,最后使用CMD 进行启动设置)
③在nginx目录中上传nginx-1.12.2.tar.gz 软件包 等文件
④ docker build 创建
⑤ docker run运行容器
⑥ 检验
7.2.9.1 dockerfile 优化方式
① dockerfile 编写tomcat 文件
② IT 精英大赛 docker 部分 (写完之后,要求写思路 ——》 ② 优化)
使用dockerfile 编写lnmp +wordprocess
dockerfile 技术 + 数据卷
优化四种方式——》基于docker镜像分层的原理来的
- ① 每一条RUN 指令 都会生成一层新的镜像层
- ② 每一层镜像缓存会继承到下一层中 ——》直接影响到镜像的大小
⭐⭐⭐⭐优化方案 加分项
- ①
减少RUN 指令的使用
RUN yum -y update
RUN yum install -y gcc gcc-c++
整合为yum install -y gcc gcc-c++&&
yum -y update
- ②
将执行后的缓存/不用的输出丢入黑洞 (减少缓存)
yum install -y gcc gcc-c++ && yum -y update > /dev/null
-
③ 多阶段构建
-
④ 使用更小体积的linux 发行版本
首先做准备:
mkdir nginx
mkdir -p nginx/nginx_v1 nginx/nginx_v2 nginx/nginx_v3
#未优化之前
FROM centos:7
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
#关闭debug日志
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
docker build -t "nginx:v1" .
#查看镜像大小 docker images
docker run -d -P nginx:v1
PS 1 : 不要用docker run -d -P nginx:v1 /bin/bash
/bin/bash 指定了shell环境,而我们的dockerfile 已指定CMD,即默认启动时加载的命令/执行程序,使用/bin/bash这种
shell环境会覆盖cmd命令,导致容器运行时nginx 不会加载
PS 2: VOLUME 宿主机的挂载点可使用docker insepct 查看
① 默认会放在var/lib/docker/volumes/容器ID/_data中
② 可以使用docker run -d -P -v /data1:/usr/local/nginx/html 来指定
#运行镜像、查看挂载位置
优化1:不需要输出的指令丢入/dev/null (需要确定命令执行的是正确的)
FROM centos:7
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> **/dev/null** && yum clean all
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
#关闭debug日志
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx &> /dev/null
RUN make &> /dev/null
RUN make install &> /dev/null
RUN rm -rf /mnt/nginx-1.15.9
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx""-g","daemon off;"]
docker build -t nginx:v1 .
优化2:减少RUN构建
FROM centos:7
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && \
yum clean all && \
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --prefix=/usr/local/nginx &> /dev/null && \
make &> /dev/null && make install &> /dev/null &&\
rm -rf /mnt/nginx-1.15.9
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
docker build -f Dockerfile -t nginx:v3 .
优化3:多阶段构建(使用FROM命令生成多个镜像,将指定的镜像做为其他镜像的基础镜像环境来构建
)
FROM centos:7 as build
ADD nginx-1.15.9.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.9
RUN yum install -y gcc pcre pcre-devel devel zlib-devel make &> /dev/null && \
yum clean all &&\
sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && \
./configure --prefix=/usr/local/nginx &> /dev/null && \
make &>/dev/null && \
make install &>/dev/null && \
rm -rf /mnt/nginx-1.15.9
FROM centos:7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY --from=build /usr/local/nginx /usr/local/nginx
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
优化4 使用更为轻量级的linux 发行版本
debian
alpine
实验:编写dockerfile,构建tomcat镜像
mkdir /opt/tomcat
拷贝jdk-8u91-linux-x64.tar.gz
apache-tomcat-9.0.16.tar.gz 到/opt/tomcat下
cd /opt/tomcat
vim Dockerfile
FROM centos:7
MAINTAINER this is tomcat image <chen>
ADD jdk-8u91-linux-x64.tar.gz /usr/local
WORKDIR /usr/local/
RUN mv jdk1.8.0_91 /usr/local/java
ENV JAVA_HOME /usr/local/java
ENV JAVA_BIN /usr/local/java/bin
ENV JRE_HOME /usr/local/java/jre
ENV PATH $PATH:/usr/local/java/bin:/usr/local/java/jre/bin
ENV CLASSPATH /usr/local/java/jre/bin:/usr/local/java/lib:/usr/local/java/jre/lib/charsets.jar
ADD apache-tomcat-9.0.16.tar.gz /usr/local
WORKDIR /usr/local/
RUN mv apache-tomcat-9.0.16 /usr/local/tomcat8
EXPOSE 8080
#CMD ["/usr/local/tomcat8/bin/catalina.sh","run"]
ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh","run"]
docker build -t tomcat:centos .
docker run -d --name tomcat01 -p 1216:8080 tomcat:centos
实验:编写dockerfile,构建mysql 镜像
####dockerfile-mysql
cd /opt
mkdir kiki
cd kiki
mkdir mysql
cd mysql
vim my.cnf
[client]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysql]
port = 3306
default-character-set=utf8
socket = /usr/local/mysql/mysql.sock
[mysqld]
user = mysql
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port = 3306
character-set-server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket = /usr/local/mysql/mysql.sock
server-id = 1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES
:wq
##########上传安装包mysql-boost-5.7.20.tar.gz
vim Dockerfile
FROM centos:7
ADD mysql-boost-5.7.20.tar.gz /usr/local
RUN yum -y install \
ncurses \
ncurses-devel \
bison \
cmake \
gcc \
gcc-c++ \
make
RUN useradd -M -s /sbin/nologin mysql
WORKDIR /usr/local/mysql-5.7.20/
RUN cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_UNIX_ADDR=/usr/local/mysql/mysql.sock \
-DSYSCONFDIR=/etc \
-DSYSTEMD_PID_DIR=/usr/local/mysql \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS=all \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_PERFSCHEMA_STORAGE_ENGINE=1 \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DWITH_BOOST=boost \
-DWITH_SYSTEMD=1 && make && make install
WORKDIR /opt/kiki/mysql
ADD my.cnf /etc
RUN chown -R mysql:mysql /usr/local/mysql/
RUN chown mysql:mysql /etc/my.cnf
ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/lib
WORKDIR /usr/local/mysql/
RUN bin/mysqld \
--initialize-insecure \
--user=mysql \
--basedir=/usr/local/mysql \
--datadir=/usr/local/mysql/data
RUN cp /usr/local/mysql/usr/lib/systemd/system/mysqld.service /usr/lib/systemd/system/
EXPOSE 3306
RUN echo -e "#!/bin/sh \nsystemctl enable mysqld" >/run.sh
RUN chmod 755 /run.sh
RUN sh /run.sh
CMD ["init"]
docker build -t mysql:v1 .
docker run --privileged -d -P mysql:v1
#进入容器
mysql -uroot -p
grant all privileges on *.* to 'root'@'%' identified by '123123';
grant all privileges on *.* to 'root'@'localhost' identified by '123123';
创建库、表示
#测试
宿主机安装mariadb
yum install -y mariadb
mysql -uroot -P 容器端口 -p123123
八、私有仓库建立
【配置私有仓库是为了,把我创建的私有镜像去放到私有仓库里面
,如果我后面把我的镜像删了之后,我可以到私有仓库里面去拖取镜像!】安全快捷,方便下次使用
docker pull registry
-----------以下是显示下载完成信息------------------
Using default tag: latest
latest: Pulling from library/registry
4064ffdc82fe: Pull complete
c12c92d1c5a2: Pull complete
4fbc9b6835cc: Pull complete
765973b0f65f: Pull complete
3968771a7c3a: Pull complete
Digest: sha256:51bb55f23ef7e25ac9b8313b139a8dd45baa832943c8ad8f7da2ddad6355b3c8
## Status: Downloaded newer image for registry:latest
8.1 在docker 引擎终端设置
注意:在这个配置文件里面不能够添加注释语句,不然会报错
vim /etc/docker/daemon.json
{
"insecure-registries": ["192.168.10.26:5000"], //添加 ,27是宿主机的ip;5000是私有仓库的端口
"registry-mirrors": ["https://05vz3np5.mirror.aliyuncs.com"] //阿里云的镜像加速
}
systemctl restart docker.service
docker create -it registry /bin/bash
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f7497fcc8c2 registry "/entrypoint.sh /b..." 59 seconds ago Exited (2) 20 seconds ago musing_turing
#会是异常状态
docker start 6f7497fcc8c2
//宿主机的/data/registry自动创建挂载容器中的/tmp/registry
docker run -d -p 5000:5000 -v /data/registry:/tmp/registry registry
//更改标记为192.168.10.26:5000/nginx
docker tag nginx:latest 192.168.10.26:5000/nginx
//上传
docker push 192.168.10.26:5000/nginx
The push refers to repository [192.168.10.26:5000/nginx]
4fc1aa8003a3: Pushed
5fb987d2e54d: Pushed
831c5620387f: Pushed
latest: digest: sha256:189cce606b29fb2a33ebc2fcecfa8e33b0b99740da4737133cdbcee92f3aba0a size: 948
//获取私有仓库列表
#偏门的面试题: 怎么获取registry的镜像仓库中的镜像信息
curl -XGET http://192.168.10.26:5000/v2/_catalog
//显示上传成功
{"repositories":["nginx"]}
//测试私有仓库下载
docker pull 192.168.10.26:5000/nginx
Using default tag: latest
latest: Pulling from nginx
000eee12ec04: Pull complete
eb22865337de: Pull complete
bee5d581ef8b: Pull complete
Digest: sha256:189cce606b29fb2a33ebc2fcecfa8e33b0b99740da4737133cdbcee92f3aba0a
Status: Downloaded newer image for 192.168.10.26:5000/nginx:latest
192.168.10.26:5000/nginx:latest
8.2 Cgroup 资源配置方法
docker 使用cgroup控制资源
,
K8S 里面也有respones(request limit) (使用上限)
CPU 内存 两个部分进行管理。
eg格式:responses:
request:
CPU:300M
mem:300M
limit:
CPU:500M
mem:500M
Docker通过 Cgroup 来控制容器使用的资源配额,包括 CPU、内存、磁盘三大方面, 基本覆盖了常见的资源配额和使用量控制。
Cgroup 是 Control Groups 的缩写,是Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 CPU、内存、磁盘 IO 等等)的机制
07年谷歌,可以控制资源分配通过操作系统内核,控制应用程序使用内存资源、cpu资源、 文件系统资源等等
cgroup是一种资源控制手段
也是容器隔离的6个名称空间的一种实现手段
每个容器相当于一个进程
#############CPU使用率控制
cpu周期: 1s为一个周期的定律,参数值一般为100000 (CPU衡量单位是秒)
假如需要给此容器分配cpu使用率的20%,则参数需要设置为20000,相当于每个周期分配给这个容器0.2s
cpu在一个时刻,只能给一个进程占用
下面开始利用 stress 压力测试工具来测试 CPU 和内存使用状况。
--------------------使用 stress 工具测试 CPU 和内存------------
8.2.1 使用 Dockerfile 来创建一个基于 Centos 的 stress 工具镜像。
[root@localhost ~]# mkdir /opt/stress # stress本地压缩工具
[root@localhost ~]# vim /opt/stress/Dockerfile
FROM centos:7
RUN yum install -y wget
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install -y stress
[root@localhost ~]# cd /opt/stress/
[root@localhost stress]# docker build -t centos:stress -f Dockfile .
报错信息解决方案:unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /opt/stress/Dockerfile: no such file or directory
使用如下命令创建容器,命令中的--cpu-shares 参数值不能保证可以获得 1 个 vcpu 或 者多少 GHz 的 CPU 资源,它仅是一个弹性的加权值。
[root@localhost stress]# docker run -itd --cpu-shares 100 centos:stress
nginx
upstream tomcat_server {
192.168.10.27:8080 weight=1
192.168.10.27:8080 weight=2
}
说明:默认情况下,每个 Docker容器的CPU份额都是1024。单独一个容器的份额是没有意义的。只有在同时运行多个容器时,容器的 CPU 加权的效果才能体现出来。
例如,两个容 器 A、B 的 CPU 份额分别为 1000 和 500,在CPU进行时间片分配的时候,容器A比容器B多一倍的机会获得 CPU 的时间片。
但分配的结果取决于当时主机和其他容器的运行状态, 实际上也无法保证容器 A一定能获得CPU时间片。比如容器A的进程一直是空闲的,
那么容器B是可以获取比容器A更多的CPU时间片的。极端情况下,例如主机上只运行了一个容器,即使它的 CPU 份额只有 50,它也可以独占整个主机的CPU资源。
一个主机运行一个容器,只运行了一个应用(容器也是虚拟化技术 )
一个主机运行一个应用
- Cgroups 只在容器分配的资源紧缺时,
即在需要对容器使用的资源进行限制时,才会生效
。因此,无法单纯根据某个容器的CPU份额来确定有多少CPU资源分配给它,资源分配 结果取决于同时运行的其他容器的CPU分配和容器中进程运行情况。 - 可以通过
cpu share 可以设置容器使用 CPU 的优先级/权重
,比如启动了两个容器及运行查看 CPU 使用百分比。
[root@localhost stress]# docker run -tid --name cpu512 --cpu-shares 512 centos:stress stress -c 10 //容器产生10个子函数进程
[root@localhost stress]# docker exec -it f4953c0d7e76 bash //进入容器使用top查看cpu使用情况
//再开启一个容器做比较
[root@localhost stress]# docker run -tid --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10
[root@localhost stress]# docker exec -it 5590c57d27b0 bash //进容器使用top对比两个容器的%CPU,比例是1:2
docker stats 查看资源使用
8.2.2 CPU 周期限制
Docker 提供了--cpu-period、--cpu-quota 两个参数控制容器可以分配到的 CPU 时钟周期。
--cpu-period 是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配。
PS:(春儿)
cd /sys/fs/cgroup/cpu/docker容器ID/cpu.cfs_quota_us
8.2.2.1 宿主机怎么提供资源、怎么控制docker容器中的应用的:
CPU> —>VCPU–>以
进程的方式
体现在vorkstation环境(docker环境中)—》docker表现形式是容器
–>Vcpu以进程的方式控制容器
–》容器中的应用需要的是服务进程支持–》宿主机内核中cpu可以被cgroup管理(通过分配资源手段)–》linux 内核中的cgroup可以控制管理docker 容器中的应用
- –cpu-quota 是用来指定在这个周期内,最多可以有多少时间用来跑这个容器。
- 与 --cpu-shares 不同的是,这种配置是指定一个绝对值,容器对 CPU 资源的使用绝对不会超过配置的值。
cpu-period 和 cpu-quota 的单位为微秒(μs)。cpu-period 的最小值为 1000 微秒, 最大值为 1 秒(10^6 μs),默认值为 0.1 秒(100000 μs)。
cpu-quota 的值默认为 -1, 表示不做控制。cpu-period 和 cpu-quota 参数一般联合使用。
redis 中,用来表示的永久 -1
ttl teacher
-1
lrange teacher 0 -1
例如:容器进程需要每 1 秒使用单个 CPU 的 0.2 秒时间,可以将 cpu-period 设置 为 1000000(即 1 秒),cpu-quota 设置为 200000(0.2 秒)。
当然,在多核情况下,如果允许容器进程完全占用两个 CPU,则可以将 cpu-period 设置为 100000(即 0.1 秒), cpu-quota 设置为 200000(0.2 秒)。
[root@localhost stress]# docker run -tid --cpu-period 100000 --cpu-quota 200000 centos:stress
[root@localhost stress]# docker exec -it 98d2aaa50019 bash
8.2.3查询容器的资源限制参数
1、在指定容器目录中
[root@98d2aaa50019 /]# cat /sys/fs/cgroup/cpu/docker/容器ID/cpu.cfs_period_us
100000
[root@98d2aaa50019 /]# cat /sys/fs/cgroup/cpu/docker/容器ID/cpu.cfs_quota_us
200000
2、使用docker inspect 容器ID/容器名
"CpuPeriod": 100000,
"CpuQuota": 200000,
8.2.4 --CPU Core 控制-
对多核 CPU 的服务器,Docker 还可以控制容器运行使用哪些 CPU 内核,即使用--cpuset-cpus 参数。
这对具有多 CPU 的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。
[root@localhost stress]# docker run -tid --name cpu1 --cpuset-cpus 0-1 centos:stress
执行以上命令需要宿主机为双核,表示创建的容器只能用 0、1两个内核。最终生成 的 cgroup 的 CPU 内核配置如下:
[root@localhost /]# cat /sys/fs/cgroup/cpuset/docker/f8481d4957529e5c9ed392d169c3dba0f076399bf46132e3073e8e10c7983ec4/cpuset.cpus
0-1
通过下面指令可以看到容器中进程与 CPU 内核的绑定关系,达到绑定 CPU 内核的目的。
[root@localhost stress]# docker exec 631eea630b21 taskset -c -p 1 //容器内部第一个进程号pid为1被绑定到指定CPU上运行
pid 1's current affinity list: 0,1
1、创建容器时 直接使用参数指定资源限制
2、创建容器后,指定资源分配
修改宿主机对应容器资源控制的文件
/sys/fs/cgroup/*
8.2.5 CPU 配额控制参数的混合使用
-
通过 cpuset-cpus 参数指定容器 A 使用 CPU 内核 0,容器 B 只是用 CPU 内核 1。
-
在主机上只有这两个容器使用对应 CPU 内核的情况,它们各自占用全部的内核资源,cpu-shares 没有明显效果。
-
cpuset-cpus、cpuset-mems 参数只在多核、多内存节点上的服务器上有效,并且必须与实际的物理配置匹配,否则也无法达到资源控制的目的。
-
在系统具有多个 CPU 内核的情况下,需要通过 cpuset-cpus 参数为设置容器 CPU 内核才能方便地进行测试。
//宿主系统修改为4核心CPU
[root@localhost stress]# docker run -tid --name cpu3 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1
[root@localhost stress]# docker exec -it 84598dfadd34 bash
[root@localhost stress]# exit
[root@localhost stress]# top //记住按1查看每个核心的占用
Tasks: 172 total, 2 running, 170 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 :100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 7994072 total, 6394056 free, 450124 used, 1149892 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 7174064 avail Mem
[root@localhost stress]# docker run -tid --name cpu4 --cpuset-cpus 3 --cpu-shares 1024 centos:stress stress -c 1
[root@localhost stress]# docker exec -it 0eed2c8a20df bash
总结: 上面的 centos:stress 镜像安装了 stress 工具,用来测试 CPU 和内存的负载。通过 在两个容器上分别执行 stress -c 1 命令,将会给系统一个随机负载,产生 1 个进程。这个进程都反复不停的计算由 rand() 产生随机数的平方根,直到资源耗尽。
观察到宿主机上的 CPU 使用率,第三个内核的使用率接近 100%, 并且一批进程的 CPU 使用率明显存在 2:1 的使用比例的对比。
8.2.6 内存限额
与操作系统类似,容器可使用的内存包括两部分:物理内存和 Swap。
Docker 通过下面两组参数来控制容器内存的使用量。
-m 或 --memory:设置内存的使用限额,例如 100M、1024M。
--memory-swap:设置 内存+swap 的使用限额。
执行如下命令允许该容器最多使用 200M 的内存和 300M 的 swap。
[root@localhost stress]# docker run -it -m 200M --memory-swap=300M centos:stress --vm 1 --vm-bytes 280M
--vm 1:启动 1 个内存工作线程。
--vm-bytes 280M:每个线程分配 280M 内存。
默认情况下,容器可以使用主机上的所有空闲内存。
与 CPU 的 cgroups 配置类似, Docker 会自动为容器在目录 /sys/fs/cgroup/memory/docker/<容器的完整长 ID>
中创建相应 cgroup 配置文件
如果让工作线程分配的内存超过 300M,分配的内存超过限额,stress 线程报错,容器 退出。
[root@localhost stress]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: dbug: [1] using backoff sleep of 3000us
stress: dbug: [1] --> hogvm worker 1 [6] forked
stress: dbug: [6] allocating 325058560 bytes ...
stress: dbug: [6] touching bytes in strides of 4096 bytes ...
stress: FAIL: [1] (416) <-- worker 6 got signal 9
stress: WARN: [1] (418) now reaping child worker processes
stress: FAIL: [1] (422) kill error: No such process
stress: FAIL: [1] (452) failed run completed in 0s
8.2.7 Block IO 的限制
默认情况下,所有容器能平等地读写磁盘,可以通过设置--blkio-weight 参数来改变 容器 block IO 的优先级。
--blkio-weight 与 --cpu-shares 类似,设置的是相对权重值,默认为 500。
在下面 的例子中,容器 A 读写磁盘的带宽是容器 B 的两倍。
[root@localhost docker]# docker run -it --name container_A --blkio-weight 600 centos:stress
[root@bbb0a299c8fd /]# cat /sys/fs/cgroup/blkio/blkio.weight
600
[root@localhost docker]# docker run -it --name container_B --blkio-weight 300 centos:stress
[root@9f5062a35cec /]# cat /sys/fs/cgroup/blkio/blkio.weight
300
8.2.8 bps 和 iops 的限制
bps 是 byte per second,每秒读写的数据量。
iops 是 io per second,每秒 IO 的次数。
可通过以下参数控制容器的 bps 和 iops:
--device-read-bps,限制读某个设备的 bps。
--device-write-bps,限制写某个设备的 bps。
--device-read-iops,限制读某个设备的 iops。
--device-write-iops,限制写某个设备的 iops。
下面的示例是限制容器写 /dev/sda 的速率为 5 MB/s。
[root@localhost docker]# docker run -it --device-write-bps /dev/sda:5MB centos:stress
[root@96a5d7c68b96 /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct //可以按ctrl+c中断查看
906+0 records in
906+0 records out
950009856 bytes (950 MB) copied, 181.202 s, 5.2 MB/s
通过 dd 命令测试在容器中写磁盘的速度。因为容器的文件系统是在 host /dev/sda 上 的,
在容器中写文件相当于对 host /dev/sda 进行写操作。另外,oflag=direct 指定用 direct IO 方式写文件,
这样 --device-write-bps 才能生效。
结果表明限速 5MB/s 左右。作为对比测试,如果不限速,结果如下。
[root@localhost docker]# docker run -it centos:stress
[root@10531445df8d /]# dd if=/dev/zero of=test bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.928611 s, 1.2 GB/s
构建镜像(docker build)时指定资源限制
--build-arg=[] : 设置镜像创建时的变量;
--cpu-shares : 设置 cpu 使用权重;
--cpu-period : 限制 CPU CFS周期;
--cpu-quota : 限制 CPU CFS配额;
--cpuset-cpus : 指定使用的CPU id;
--cpuset-mems : 指定使用的内存 id;
--disable-content-trust :忽略校验,默认开启;
-f : 指定要使用的Dockerfile路径;
--force-rm : 设置镜像过程中删除中间容器;
--isolation : 使用容器隔离技术;
--label=[] : 设置镜像使用的元数据;
-m : 设置内存最大值;
--memory-swap : 设置Swap的最大值为内存+swap,"-1"表示不限swap;
--no-cache : 创建镜像的过程不使用缓存;
--pull : 尝试去更新镜像的新版本;
--quiet, -q : 安静模式,成功后只输出镜像 ID;
--rm : 设置镜像成功后删除中间容器;
--shm-size : 设置/dev/shm的大小,默认值是64M;
--ulimit : Ulimit配置。
--squash : 将 Dockerfile 中所有的操作压缩为一层。
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
--network: 默认 default。在构建期间设置RUN指令的网络模式
小结:
一、资源限制的主要类型
1、CPU 权重shares、quota、cpuset
2、磁盘 BPS、TPS限制,指定使用哪个磁盘、磁盘分区
3、内存 -m -swap 内存、交换分区
大部分做的是上限的限制
二、资源限制的几种方式
1、build 构建镜像时,可以指定该镜像的资源限制
2、run 将镜像跑为容器的时候,可以指定容器的资源限制
3、容器启动之后, 可以在宿主机对应容器的目录下。修改资源限制,然后重载/sys/fs/cgroup/*(cpu、blk、mem)/docker/容器ID/ --->修改对应的资源限制文件参数就可以
三、资源限制的状态查询
1、docker inspect 镜像ID/容器ID
2、直接查看宿主机对应容器ID资源限制的文件
cgroup 资源 docker 原理之一 ,namespaces 6个名称空间
九、 compose部署
//环境部署所有主机安装docker环境(内容为docker基础)
yum install docker-ce -y
//下载compose(上传docker_compose)
curl -L https://github.com/docker/compose/releases/download/1.21.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
cp -p docker-compose /usr/local/bin/
chmod +x /usr/local/bin/docker-compose
mkdir /root/compose_nginx
[root@consul compose_nginx]# tree ./
./
├── docker-compose.yml //创建模板脚本
├── nginx
├── Dockerfile //创建容器脚本
├── nginx-1.15.9.tar.gz //复制源码包
└── wwwroot
└── index.html //站点
vim /root/compose_nginx/docker-compose.yml
version: '3'
services:
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 1216:80
- 1217:443
networks:
- cluster
volumes:
- ./wwwroot:/usr/local/nginx/html
networks:
cluster:
[root@consul compose_nginx]# docker-compose -f docker-compose.yml up -d
docker 基础操作/常规操作
1、image 容器的管理命令
2、dockerfile
3、docker 网络
4、docker 私有仓库
registry
harbor
docker-compose ————————》资源编排和管理手段 (docker swarm && k8s )
9.1 consul部署
服务器:192.168.10.26 Docker-ce、Compose 3、Consul、 Consul-template
服务器:192.168.10.27 Docker-ce、registrator
template 模板(更新)
registrator(自动发现)
后端每构建出一个容器,会向registrator进行注册,控制consul 完成更新操作,consul会触发consul template模板进行热更新
核心机制:consul :自动发现、自动更新,为容器提供服务(添加、删除、生命周期)
--------consul服务器--------------------------------------------
mkdir /root/consul
cp consul_0.9.2_linux_amd64.zip /root/consul
cd /root/consul
unzip consul_0.9.2_linux_amd64.zip
mv consul /usr/bin
consul agent \
-server \ server模式
-bootstrap \ 前端框架
-ui \ 可被访问的web界面
-data-dir=/var/lib/consul-data \
-bind=192.168.10.26 \
-client=0.0.0.0 \
-node=consul-server01 &> /var/log/consul.log &
consul agent \
-server \
-bootstrap \
-ui \
-data-dir=/var/lib/consul-data \
-bind=192.168.10.26 \
-client=0.0.0.0 \
-node=consul-server01 &> /var/log/consul.log &
##查看集群信息
[root@consul consul]# consul members
Node Address Status Type Build Protocol DC
consul-server01 192.168.10.28:8301 alive server 0.9.2 2 dc1
[root@consul consul]# consul info | grep leader
leader = true
leader_addr = 192.168.10.28:8300
##通过httpd api 获取集群信息
curl 127.0.0.1:8500/v1/status/peers //查看集群server成员
curl 127.0.0.1:8500/v1/status/leader //集群 Raf leader
curl 127.0.0.1:8500/v1/catalog/services //注册的所有服务
curl 127.0.0.1:8500/v1/catalog/nginx //查看 nginx 服务信息
[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/nodes //集群节点详细信息
[{"ID":"ac1937e8-8f21-bbc0-61d6-0a24ea946cee","Node":"consul-server01","Address":"192.168.226.130","Datacenter":"dc1","TaggedAddresses":{"lan":"192.168.226.129","wan":"192.168.226.129"},"Meta":{},"CreateIndex":5,"ModifyIndex":6}]
9.2 容器服务自动加入consul集群
9.2.1 安装 Gliderlabs/Registrator Gliderlabs/Registrator
可检查容器运行状态自动注册,还可注销 docker 容器的服务 到服务配置中心。
目前支持 Consul、Etcd 和 SkyDNS2。
在 192.168.10.27 节点,执行以下操作:
docker run -d \
--name=registrator \
--net=host \
-v /var/run/docker.sock:/tmp/docker.sock \
--restart=always \
gliderlabs/registrator:latest \
-ip=192.168.10.27 \
consul://192.168.10.26:8500
9.2.2 测试服务发现功能是否正常
docker run -itd -p:83:80 --name test-01 -h test01 nginx
docker run -itd -p:84:80 --name test-02 -h test02 nginx
docker run -itd -p:88:80 --name test-03 -h test03 httpd
docker run -itd -p:89:80 --name test-04 -h test04 httpd
9.2.3 验证 http 和 nginx 服务是否注册到 consul
浏览器输入 http://192.168.10.26:8500,“单击 NODES”,然后单击 “consurl-server01”,会出现 5 个服务.
##在consul服务器上查看服务
[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/services
{"consul":[],"httpd":[],"nginx":[]}
9.2.4 安装 consul-template
Consul-Template 是一个守护进程,用于实时查询 Consul 集群信息,
并更新文件系统 上任意数量的指定模板,生成配置文件。更新完成以后,
可以选择运行 shell 命令执行更新 操作,重新加载 Nginx。Consul-Template
可以查询 Consul 中的服务目录、Key、Key-values 等。
这种强大的抽象功能和查询语言模板可以使 Consul-Template 特别适合动态的创建配置文件。
例如:创建 Apache/Nginx Proxy Balancers、Haproxy Backends
9.2.5 准备 template nginx 模板文件
##在consul上操作
vim /root/consul/nginx.ctmpl
upstream http_backend {
{{range service "nginx"}}
server {{.Address}}:{{.Port}}; #此处引用的变量会指向后端的地址和端口(动态变化)
{{end}}
}
server {
listen 83;
server_name localhost 192.168.10.26; #反向代理的IP地址(前端展示的NG服务的IP)
access_log /var/log/nginx/kgc.cn-access.log;
index index.html index.php;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr; #后端真实IP
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #转发地址
proxy_pass http://http_backend;
}
}
9.2.6 编译安装nginx
yum install gcc pcre-devel zlib-devel -y
tar zxvf nginx-1.12.0.tar.gz -C /opt
./configure --prefix=/usr/local/nginx
make && make install
9.2.7 配置 nginx
vim /usr/local/nginx/conf/nginx.conf
http {
include mime.types; #默认存在的
include vhost/*.conf; ####添加虚拟主机目录(consul动态生成的配置文件就会放在这里)
default_type application/octet-stream;
##创建虚拟主机目录
mkdir /usr/local/nginx/conf/vhost
##创建日志文件目录
mkdir /var/log/nginx
##启动nginx
#usr/local/nginx/sbin/nginx
9.2.8配置并启动 template
上传 consul-template_0.19.3_linux_amd64.zip 包到/root 目录下
cp consul-template_0.19.3_linux_amd64.zip /root/
unzip consul-template_0.19.3_linux_amd64.zip
mv consul-template /usr/bin/
##关联nginx 虚拟目录中的子配置文件操作
consul-template -consul-addr 192.168.10.28:8500 \
-template "/opt/consul/nginx.ctmpl:/usr/local/nginx/conf/vhost/benet.conf:/usr/local/nginx/sbin/nginx -s reload" \
--log-level=info
9.2.9 另外打开一个终端查看生成配置文件
[root@consul ~]# cat /usr/local/nginx/conf/vhost/kgc.conf
upstream http_backend {
server 192.168.10.27:83;
server 192.168.10.27:84;
}
server {
listen 83;
server_name localhost 192.168.10.27;
access_log /var/log/nginx/kgc.cn-access.log;
index index.html index.php;
location / {
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://http_backend;
}
}
9.2.10 增加一个nginx容器节点
增加一个 nginx 容器节点,测试服务发现及配置更新功能
//在registrator服务端注册
docker run -itd -p 85:80 --name test-05 -h test05 nginx
//在consul服务器监控装填会有提示自动更新
2019/12/30 14:59:21.750556 [INFO] (runner) initiating run
2019/12/30 14:59:21.751767 [INFO] (runner) rendered "/root/consul/nginx.ctmpl" => "/usr/local/nginx/conf/vhost/kgc.conf"
2019/12/30 14:59:21.751787 [INFO] (runner) executing command "/usr/local/nginx/sbin/nginx -s reload" from "/root/consul/nginx.ctmpl" => "/usr/local/nginx/conf/vhost/kgc.conf"
2019/12/30 14:59:21.751823 [INFO] (child) spawning: /usr/local/nginx/sbin/nginx -s reload
//查看三台nginx容器日志,请求正常轮询到各个容器节点上
docker logs -f test-01
docker logs -f test-02
docker logs -f test-05