一、Docker概述
- Docker是一个开源的应用引擎,基于go语言开发并遵循apache2.0协议开源。
- Docker是在linux容器里运行应用的开源工具,是一种轻量级的虚拟机。
- Docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器‘
Docker的Logo设计为蓝色鲸鱼,拖着许多集装箱
鲸鱼可看作为宿主机,集装箱可理解为相互隔离的容器,每个集装箱中都包含自己的应用程序
1.Docker的设计宗旨:
Build,Ship and Run Any App,Anywhere,
即通过对应用组件的封装、发布、部署、运行等生命周期的管理,达到应用组件级别的“一次封装,到处运行”的目的。这里的组件,既可以是一个应用,也可以是一套服务,甚至是一个完整的操作系统。
2.容器化越来越受欢迎,因为容器是:
- 灵活:即使是最复杂的应用也可以集装箱化。
- 轻量级:容器利用并共享主机内核。
- 可互换:可以即时部署更新和升级。
- 便携式:可以在本地构建,部署到云,并在任何地方运行。
- 可扩展:可以增加并自动分发容器副本。
- 可堆叠:可以垂直和即时堆叠服务。
- 容器是在linux上本机运行,并与其他容器共享主机的内核,它运行的是一个独立的进程,不占用其他任何可执行文件的内存,非常轻量
- 虚拟机运行的是一个完成的操作系统,通过虚拟机管理程序对主机资源进行虚拟访问,相比之下需要的资源更多
3.Docker与虚拟机的区别:
特性 Docker容器 虚拟机 启动速度 秒级 分钟级 计算能力 损耗几乎无损耗 50%左右 性能 接近原生 弱于 系统支持量(单机) 上千个 几十个 隔离性 资源隔离/限制 完全隔离
4.容器在内核中支持2种重要技术:
docker本质就是宿主机的一个进程,docker是通过namespace实现资源隔离,通过cgroup实现资源限制,通过写时复制技术(copy-on-write)实现了高效的文件操作(类似虚拟机的磁盘比如分配500g并不是实际占用物理磁盘500g)
二.Docker核心概念
- 镜像
Docker的镜像是创建容器的基础,类似虚拟机的快照,可以理解为一个面向 Docker 容器引擎的只读模板
通过镜像启动一个容器,一个镜像是一个可执行的包,其中包括运行应用程序所需要的所有内容包含代码,运行时间,库、环境变量、和配置文件
- 容器
Docker的容器是从镜像创建的运行实例,它可以被启动、停止和删除。所创建的每一个容器都是相互隔离、互不可见,以保证平台的安全性
可以把容器看做是要给简易版的linux环境(包括root用户权限、镜像空间、用户空间和网络空间等)和运行在其中的应用程序。
- 仓库
Docker仓库是用来集中保存镜像的地方,当创建了自己的镜像之后,可以使用push命令将它上传到公有仓库(Public)或者私有仓库(Private)。当下次要在另外一台机器上使用这个镜像时,只需从仓库获取
Docker 的镜像、容器、日志等内容全部都默认存储在 /var/lib/docker 目录下。
三.安装 Docker
目前 Docker 只能支持 64 位系统。 systemctl stop firewalld.service setenforce 0 #安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 -------------------------------------------------------------------------------------------- yum-utils:提供了 yum-config-manager 工具。 device mapper: 是Linux内核中支持逻辑卷管理的通用设备映射机制,它为实现用于存储资源管理的块设备驱动提供了一个高度模块化的内核架构。 device mapper存储驱动程序需要 device-mapper-persistent-data 和 lvm2。 -------------------------------------------------------------------------------------------- #设置阿里云镜像源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #安装 Docker-CE并设置为开机自动启动 yum install -y docker-ce systemctl start docker.service systemctl enable docker.service #查看 docker 版本信息 docker version
注:使用在线源安装
四.Docker 镜像操作
#搜索镜像 格式:docker search 关键字 docker search nginx #获取镜像 格式:docker pull 仓库名称[:标签] #如果下载镜像时不指定标签,则默认会下载仓库中最新版本的镜像,即选择标签为 latest 标签。 docker pull nginx #镜像加速下载 浏览器访问 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 获取镜像加速器配置 mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"] } EOF systemctl daemon-reload systemctl restart docker #查看镜像信息 镜像下载后存放在 /var/lib/docker #查看下载的镜像文件信息 cat /var/lib/docker/image/overlay2/repositories.json #查看下载到本地的所有镜像 docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ae2feff98a0c 9 days ago 133MB -------------------------------------------------------------------------------------------- REPOSITORY:镜像属于的仓库; TAG:镜像的标签信息,标记同一个仓库中的不同镜像; IMAGE ID:镜像的唯一ID 号,唯一标识一个镜像; CREATED:镜像创建时间; VIRTUAL SIZE:镜像大小; -------------------------------------------------------------------------------------------- #根据镜像的唯一标识 ID 号,获取镜像详细信息 格式:docker inspect 镜像ID号 docker inspect ae2feff98a0c #为本地的镜像添加新的标签 格式:docker tag 名称:[标签] 新名称:[新标签] docker tag nginx:latest nginx:web docker images | grep nginx #删除镜像 格式: docker rmi 仓库名称:标签 #当一个镜像有多个标签时,只是删除其中指定的标签 或者 docker rmi 镜像ID号 #会彻底删除该镜像 注意:如果该镜像已经被容器使用,正确的做法是先删除依赖该镜像的所有容器,再去删除镜像。 docker rmi nginx:web #存出镜像:将镜像保存成为本地文件 格式:docker save -o 存储文件名 存储的镜像 docker save -o nginx nginx:latest #存出镜像命名为nginx存在当前目录下 ls -lh #载入镜像:将镜像文件导入到镜像库中 格式: docker load < 存出的文件 或者 docker load -i 存出的文件 docker load < nginx #上传镜像 默认上传到 docker Hub 官方公共仓库,需要注册使用公共仓库的账号。https://hub.docker.com 可以使用 docker login 命令来输入用户名、密码和邮箱来完成注册和登录。 在上传镜像之前,还需要先对本地镜像添加新的标签,然后再使用 docker push 命令进行上传。 docker tag nginx:latest nginx:web #添加新的标签 docker login #登录公共仓库 Username: password: docker push wl/nginx:web #上传镜像
注:此步骤 往往也是排查镜像问题的良方
rmi后面加镜像ID号 阿静彻底删除该镜像
五.Docker 容器操作
#容器创建:就是将镜像加载到容器的过程。 新创建的容器默认处于停止状态,不运行任何程序,需要在其中发起一个进程来启动容器。 格式:docker create [选项] 镜像 常用选项: -i:让容器的输入保持打开 -t:让 Docker 分配一个伪终端 docker create -it nginx:latest /bin/bash #查看容器的运行状态 docker ps -a #-a 选项可以显示所有的容器 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8b0a7be0ff58 nginx:latest "/docker-entrypoint.…" 57 seconds ago Created inspiring_swanson 容器的ID号 加载的镜像 运行的程序 创建时间 当前的状态 端口映射 名称 #启动容器 格式:docker start 容器的ID/名称 docker start 8b0a7be0ff58 docker ps -a #创建并启动容器 可以直接执行 docker run 命令, 等同于先执行 docker create 命令,再执行 docker start 命令。 注意:容器是一个与其中运行的 shell 命令共存亡的终端,命令运行容器运行, 命令结束容器退出。 当利用 docker run 来创建容器时, Docker 在后台的标准运行过程是: (1)检查本地是否存在指定的镜像。当镜像不存在时,会从公有仓库下载; (2)利用镜像创建并启动一个容器; (3)分配一个文件系统给容器,在只读的镜像层外面挂载一层可读写层; (4)从宿主主机配置的网桥接口中桥接一个虚拟机接口到容器中; (5)分配一个地址池中的 IP 地址给容器; (6)执行用户指定的应用程序,执行完毕后容器被终止运行。 docker run centos:7 /usr/bin/bash -c ls / docker ps -a #会发现创建了一个新容器并启动执行一条 shell 命令,之后就停止了 #在后台持续运行 docker run 创建的容器 需要在 docker run 命令之后添加 -d 选项让 Docker 容器以守护形式在后台运行。并且容器所运行的程序不能结束。 docker run -d centos:7 /usr/bin/bash -c "while true;do echo hello;done" docker ps -a #可以看出容器始终处于 UP,运行状态 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2592d3fad0fb centos:7 "/usr/bin/bash -c 'w…" 2 seconds ago Up 2 seconds peaceful_chatelet docker run -itd --name test1 centos:7 /bin/bash #终止容器运行 格式:docker stop 容器的ID/名称 docker stop 2592d3fad0fb docker ps -a #容器的进入 需要进入容器进行命令操作时,可以使用 docker exec 命令进入运行着的容器。 格式:docker exec -it 容器ID/名称 /bin/bash -i 选项表示让容器的输入保持打开; -t 选项表示让 Docker 分配一个伪终端。 docker start 2592d3fad0fb #进入容器前,确保容器正在运行 docker exec -it 2592d3fad0fb /bin/bash ls exit #退出容器后,容器仍在运行 docker ps -a #容器的导出与导入 用户可以将任何一个 Docker 容器从一台机器迁移到另一台机器。在迁移过程中,可以使用docker export 命令将已经创建好的容器导出为文件,无论这个容器是处于运行状态还是停止状态均可导出。可将导出文件传输到其他机器,通过相应的导入命令实现容器的迁移。 #导出格式:docker export 容器ID/名称 > 文件名 docker export 2592d3fad0fb > centos7tar #导入格式:cat 文件名 | docker import – 镜像名称:标签 cat centos7tar | docker import - centos7:test #导入后会生成镜像,但不会创建容器 #删除容器 格式:docker rm [-f] 容器ID/名称 docker stop 2592d3fad0fb docker rm 2592d3fad0fb #删除已经终止状态的容器 docker rm -f 2592d3fad0fb #强制删除正在运行的容器 docker ps -a | awk 'NR>=2{print "docker stop "$1}' | bash #批量停止容器 docker ps -a | awk 'NR>=2{print "docker rm "$1}' | bash #批量删除所有容器 docker images | awk 'NR>=2{print "docker rmi "$3}' | bash #批量删除镜像
六.Docker 网络
1.Docker网络的实现原理
- Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
- Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run 创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
docker run -d --name test1 -P nginx #随机映射端口( 从32768开始) docker run -d --name test2 -p 43000:80 nginx #指定映射端口 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9d3c04f57a68 nginx "/docker-entrypoin...." 4 seconds ago Up 3 seconds 0.0.0.0: 43000->80/tcp test2 b04895f870e5 nginx " /docker-entrypoi..." 17 seconds ago Up 15 seconds 0.0.0.0: 49170->80/ tcp test1 浏览器访问: http://192.168.80.10;43000 、 http://192.168.80.10:49170
2.Docker 的网络模式
●Host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。 ●Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。 ●None:该模式关闭了容器的网络功能。 ●Bridge:默认为该模式,此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat 表配置与宿主机通信。 ●自定义网络
Host:
Container:
Bridge:
#使用docker run创建Docker容器时,可以用 --net 或 --network 选项指定容器的网络模式 ●host模式:使用 --net=host 指定。 ●none模式:使用 --net=none 指定。 ●container模式:使用 --net=container:NAME_or_ID 指定。 ●bridge模式:使用 --net=bridge 指定,默认设置,可省略。
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host
docker network ls #查看docker网络列表 NETWORK ID NAME DRIVER SCOPE 2b4359d229c6 bridge bridge local 0fa580365d39 host host local cc13aa84a223 none null local
3.网络模式详解
1.host模式 相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址。 Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。 一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、iptable规则等都与其他的Network Namespace隔离。 一个Docker容器一般会分配一个独立的Network Namespace。 但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace, 而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口。 2.container模式 在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。 docker run -itd --name test1 centos:7 /bin/bash #--name 选项可以给容器创建一个友好的自定义名称 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test1 docker inspect -f '{{.State.Pid}}' 3ed82355f811 #查看容器进程号 25945 ls -l /proc/25495/ns #查看容器的进程、 网络、文件系统等命名空间编号 lrwxrwxrwx 1 root root 0 1月 7 11:29 ipc -> ipc:[4026532572] lrwxrwxrwx 1 root root 0 1月 7 11:29 mnt -> mnt:[4026532569] lrwxrwxrwx 1 root root 0 1月 7 11:27 net -> net:[4026532575] lrwxrwxrwx 1 root root 0 1月 7 11:29 pid -> pid:[4026532573] lrwxrwxrwx 1 root root 0 1月 7 12:22 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 1月 7 11:29 uts -> uts:[4026532570] docker run -itd --name test2 --net=container:3ed82355f811 centos:7 /bin/bash docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff96bc43dd27 centos:7 "/bin/bash" 48 seconds ago Up 46 seconds test2 3ed82355f811 centos:7 "/bin/bash" 58 minutes ago Up 58 minutes test1 docker inspect -f '{{.State.Pid}}' ff96bc43dd27 27123 ls -l /proc/27123/ns #查看可以发现两个容器的 net namespace 编号相同 lrwxrwxrwx 1 root root 0 1月 7 12:27 ipc -> ipc:[4026532692] lrwxrwxrwx 1 root root 0 1月 7 12:27 mnt -> mnt:[4026532690] lrwxrwxrwx 1 root root 0 1月 7 12:27 net -> net:[4026532575] lrwxrwxrwx 1 root root 0 1月 7 12:27 pid -> pid:[4026532693] lrwxrwxrwx 1 root root 0 1月 7 12:27 user -> user:[4026531837] lrwxrwxrwx 1 root root 0 1月 7 12:27 uts -> uts:[4026532691] 3.none模式 使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。 也就是说,这个Docker容器没有网卡、IP、路由等信息。这种网络模式下容器只有lo回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。 4.Bridge模式 bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。 相当于Vmware中的 nat 模式,容器使用独立network Namespace,并连接到docker0虚拟网卡。通过docker0网桥以及iptables nat表配置与宿主机通信,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。 (1)当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。 (2)从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。 (3)Docker将veth pair 设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中, 以veth*这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过 brctl show 命令查看。 (4)使用 docker run -p 时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL 查看。 5.自定义网络 #直接使用bridge,无法支持指定IP运行docker docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash #可以先自定义网络,再使用指定IP运行docker docker network create --subnet=172.18.0.0/24 mynetwork docker run -itd --name test2 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash
七.资源控制
1.CPU 资源控制
cgroups,是一个非常强大的linux内核工具,他不仅可以限制被 namespace 隔离起来的资源, 还可以为资源设置权重、计算使用量、操控进程启停等等。 所以 cgroups( Control groups) 实现了对资源的配额和度量。
2.cgroups四大功能:
- 资源限制:可以对任务使用的资源总额进行限制
- 优先级分配:通过分配的cpu时间片数量以及磁盘IO带宽大小,实际上相当于控制了任务运行优先级
- 资源统计:可以统计系统的资源使用量,如cpu时长,内存用量等
- 任务控制:cgroup可以对任务执行挂起、恢复等操作
(1)设置CPU使用率上限 Linux 通过 CFS(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms。 我们可以设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间。 使用 --cpu-period 即可设置调度周期,使用 --cpu-quota 即可设置在每个周期内容器能使用的 CPU 时间。两者可以配合使用。 CFS 周期的有效范围是 1ms~1s,对应的 --cpu-period 的数值范围是 1000~100000。 而容器的 CPU 配额必须不小于 1ms,即 --cpu-quota 的值必须 >= 1000。 docker run -itd --name test1 centos:7 /bin/bash docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ed82355f811 centos:7 "/bin/bash" 5 days ago Up 6 hours test1 cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/ cat cpu.cfs_quota_us -1 cat cpu.cfs_period_us 100000 --------------------------------------------------------------------------------------------------------- #cpu.cfs_period_us:cpu分配的周期(微秒,所以文件名中用 us 表示),默认为100000。 #cpu.cfs_quota_us:表示该control group限制占用的时间(微秒),默认为-1,表示不限制。 如果设为50000,表示占用50000/100000=50%的CPU。 --------------------------------------------------------------------------------------------------------- #进行CPU压力测试 docker exec -it 3ed82355f811 /bin/bash vim /cpu.sh #!/bin/bash i=0 while true do let i++ done chmod +x /cpu.sh ./cpu.sh exit top #可以看到这个脚本占了很多的cpu资源 #设置50%的比例分配CPU使用时间上限 docker run -itd --name test2 --cpu-quota 50000 centos:7 /bin/bash #可以重新创建一个容器并设置限额 或者 cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/ echo 50000 > cpu.cfs_quota_us docker exec -it 3ed82355f811 /bin/bash ./cpu.sh exit top #可以看到cpu占用率接近50%,cgroups对cpu的控制起了效果 (2)设置CPU资源占用比(设置多个容器时才有效) Docker 通过--cpu-shares 指定 CPU 份额,默认值为1024,值为1024的倍数。 #创建两个容器为 c1 和 c2,若只有这两个容器,设置容器的权重,使得c1和c2的CPU资源占比为1/3和2/3。 docker run -itd --name c1 --cpu-shares 512 centos:7 docker run -itd --name c2 --cpu-shares 1024 centos:7 #分别进入容器,进行压力测试 yum install -y epel-release yum install stress -y stress -c 4 #产生四个进程,每个进程都反复不停的计算随机数的平方根 exit #查看容器运行状态(动态更新) docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS c3ee18e65852 c2 66.50% 5.5MiB / 976.3MiB 0.56% 20.4MB / 265kB 115MB / 14.2MB 4 bb02d3b345d8 c1 32.68% 2.625MiB / 976.3MiB 0.27% 20.4MB / 325kB 191MB / 12.7MB 4 (3)设置容器绑定指定的CPU #先分配虚拟机4个CPU核数 docker run -itd --name test2 --cpuset-cpus 1,3 centos:7 /bin/bash #进入容器,进行压力测试 yum install -y epel-release yum install stress -y stress -c 4 exit #退出容器,执行 top 命令再按 1 查看CPU使用情况。
3.对磁盘IO配额控制(blkio)的限制
--device-read-bps:限制某个设备上的读速度bps(数据量),单位可以是kb、mb(M)或者gb。 例:docker run -itd --name test4 --device-read-bps /dev/sda:1M centos:7 /bin/bash --device-write-bps : 限制某个设备上的写速度bps(数据量),单位可以是kb、mb(M)或者gb。 例:docker run -itd --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash --device-read-iops :限制读某个设备的iops(次数) --device-write-iops :限制写入某个设备的iops(次数) #创建容器,并限制写速度 docker run -it --name test5 --device-write-bps /dev/sda:1mb centos:7 /bin/bash #通过dd来验证写速度 dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct #添加oflag参数以规避掉文件系统cache 10+0 records in 10+0 records out 10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s
原文链接:https://www.cnblogs.com/marshs/p/15371335.html