03 . Docker数据资源管理与网络
1|0Docker数据卷
在容器中管理数据主要有两种方式
# 数据卷(Data volumes) # 数据卷容器(Data volume containers) # 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: # 1. 数据卷可以在容器之间共享和重用 # 2. 对数据卷的修改会立即生效 # 3. 对数据卷的更新,不会影响镜像 # 4. 卷会一直存在,知道没有容器使用 # 数据卷的使用类似于Linux下对目录或文件进行mount.
1|1创建一个数据卷
在用 docker run 命令的时候,使用 -v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用
可以挂载多个数据卷。Dockerfile中使用VOLUME也能实现一样效果.
下面创建一个 web 容器,并加载一个数据卷到容器的 /webapp 目录。
docker run -itd --name nginx_web -v /nginx_web:/usr/share/nginx/html nginx:latest docker exec -it d4d bash echo 1 > /usr/share/nginx/html/index.html cat /nginx_web/index.html 1 echo 4 > /nginx_web/index.html docker inspect --format=‘{{.NetworkSettings.IPAddress}}‘ d4d 172.17.0.2 curl 172.17.0.2 4 # Docker挂载数据卷默认权限是读写,用户可以通过:ro指定为只读. docker run -d --name web -v /nginx_web:/usr/share/nginx/html:ro nginx:latest docker exec -it web /bin/bash echo 5 > /usr/share/nginx/html/index.html bash: /usr/share/nginx/html/index.html: Read-only file system echo 5 > /nginx_web/index.html curl 172.17.0.2 5
1|2数据卷容器
- 如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。
- 数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
- 首先,创建一个命名的数据卷容器:
dbdata
docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres # 发现创建好的数据卷容器是出于停止运行的状态,因为使用 --volumes-from 参数 # 所挂载数据卷的容器自己并不需要保持在运行状态。 # 然后我们再创建容器挂载这个数据卷。 docker run -d --volumes-from dbdata --name db1 training/postgres docker run -d --volumes-from dbdata --name db2 training/postgres # 还可以使用多个 --volumes-from 参数来从多个容器挂载多个数据卷。 # 也可以从其他已经挂载了数据卷的容器来挂载数据卷。 # 如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。 # 如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时, # 要使用 docker rm -v 命令来指定同时删除关联的容器。 # 这可以让用户在容器之间升级和移动数据卷。
1|3利用数据卷容器来备份、恢复、迁移数据卷
# 首先使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器, # 并从本地主机挂载当前到容器的 /backup 目录。命令如下: docker run -itd --volumes-from dbdata -v /dbdata:/backup centos:7.7.1908 /bin/bash docker exec -it 7456 /bin/bash # 将此处的etc数据假设是重要的应用程序数据,防止容器宕机丢失,我们先备份. tar -zcf /dbdata/etc.tar.gz /etc/ [ ~]# ll -h /dbdata/ total 660K -rw-r--r-- 1 root root 660K Dec 13 08:04 etc.tar.gz # 突然有一天容器坏了进不去了,我们可以去查看一些容器数据卷.看到里面有我们之前挂载的数据. docker exec -it db1 /bin/bash :/# ls -lh /dbdata/etc.tar.gz -rw-r--r-- 1 root root 660K Dec 13 08:04 /dbdata/etc.tar.gz # 接下来我们只需要再创建一个跟以前一样的容器,挂载此数据卷容器,就可以数据恢复了.
2|0资源配置
2|1内存资源
# 设置内存我们可以有四种方式: # 默认的方式设置最低值,容器可以使用大于此最低值的内存数 # 设置memory不能使用超过L的值 # memory不能超过L,swap+memory总使用量不能超过S
第一种情况(默认不做任何限制)
docker run -ti -m 300M --memory-swap -1 centos:7.7.1908 /bin/bash
第二种情况(memory最多使用300M,swap没有限制)
docker run -itd -m 500m centos:7.7.1908 /bin/bash
第三种情况 (我们只设置了memory限制时300M,swap没有指定,默认被设置为与memory一样的值。memory+swap一共是600M)
docker run -ti -m 300M --memory-swap 1G centos:7.7.1908 /bin/bash
第四种情况
如果发生内存溢出错误,内核讲kill掉容器中的进程。如果你想控制,可以配合使用- -oom-kill-disable参数。如果没有制定-m参数,可能导致当内存溢出时内核会杀死主机进程。 例子: 设置容器内存限制100M,并且阻止 OOM killer
docker run -ti -m 100M --oom-kill-disable centos:7.7.1908 /bin/bash
2|2CPU资源限制
默认情况下,所有容器获得CPU周期的比例相同。可以通过改变容器的CPU加权占有率相对于其他正在运行容器的加权占有率的比例来调整。
修改1024的比例,使用-c或--cpu-sharesflag的权重设置为2或更高。 该比例只适用在CPU密集型进程运行时。当在一个容器中的任务处于空闲状态,其他容器可以使用剩余空闲CPU时间。实际CPU时间将根据在系统上运行的容器的数目而变化。
例如,考虑三个容器的情况,一个拥有cpu的1024和另外两个有512 CPU共享时间,三个容器进程都尝试使用100%的CPU,第一个容器将获得的50%总的CPU时间。如果您添加CPU值为1024的第四个容器中,第一个容器只得到了CPU的33%。剩余的容器将分别占用CPU的16.5%,16.5%和33%。
在多核心系统中,CPU时间的份额分布在所有CPU核心。即使容器被限制为CPU时间小于100%时,它可以使用每个单独的CPU核心的100%。例如,在一个拥有超过三个核心的系统中,
如果启动一个容器设置-c=512跑一个进程,另外一个设置-c=1024,跑2个进程,内存分配将会如下配置:
PID container CPU CPU share 100 {C0} 0 100% of CPU0 101 {C1} 1 100% of CPU1 102 {C1} 2 100% of CPU2
--cpu-period参数
# 默认设置为100ms,当然我们也可以自己设置cpu周期,限制容器CPU用量。通常该参数伴随--cpu-quota参数使用。 --cpu-quota参数 # 限制CPU用量。默认值0,意味着允许容器获得1个CPU的100%的资源量。设置50000限制CPU资源的50%。 docker run -ti --cpu-period=50000 --cpu-quota=25000 centos /bin/bash # 如果是单核心系统,将意味着容器将每50ms获得50%运行周期。
--cpuset参数
# 设置容器允许运行的cpu号(在多核心系统中): # 设置容器在CPU1和CPU3上运行 $ sudo docker run -ti --cpuset-cpus="1,3" centos /bin/bash # 设置容器在CPU0、CPU1、CPU2上运行 docker run -ti --cpuset-cpus="0-2" centos /bin/bash # 设置容器在指定mems上执行(只在NUMA系统中有效): # 容器只能在memory nodes 1和2上运行 docker run -ti --cpuset-mems="1,3" centos /bin/bash
2|3网络限制
--bkio-weight参数
默认情况下,所有容器获得相同比例的blokIO带宽,这个比例值是500。要修改此比例,使用--blkio-weight设置容器的blkio相对于其他运行容器权重。它的取值范围是10~1000。 下面的例子中,设置了两个不同blkio:
docker run -ti --name c1 --blkio-weight 300 centos /bin/bash docker run -ti --name c2 --blkio-weight 600 centos /bin/bash 如果同时设置两个容器blockIO,利用如下指令: time dd if=/mnt/zerofile of=test.out bs=1M count=1024 oflag=direct
3|0Docker网络
4|0外部访问容器
Docker允许通过外部访问容器或容器互联的方式来提供网络服务.
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过-P或-p参数来指定端口映射.
当使用-P标记时,Docker会随机映射一个49000-49900的端口到内部容器开放的网络端口.
docker run -d -P nginx:latest docker ps CONTAINER ID IMAGE CREATED STATUS PORTS NAMES 853b948aa479 nginx:latest 4 seconds ago Up 3 seconds 0.0.0.0:1025->80 /tczealous_booth # 此时1025就可以通过公网IP加端口访问了
当使用-p(小写的)则可以指定要映射的端口,并且在一个指定端口上只可以绑定一个容器,支持可是有ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort.
docker run -d -p 5000:80 nginx:latest
映射到指定地址的指定端口
docker run -d -p 127.0.0.1:5000:80 nginx:latest # 还可以使用udp标记来指定udp端口 docker run -d -p 5000:80/udp nginx:latest # -p标记可以多次使用来绑定多个端口 docker run -d -p 5000:80 -p 1314:3306 nginx:latest
查看映射端口配置
docker port 10b0bc0 80/tcp -> 0.0.0.0:5000
5|0容器的互联
容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式
该系统会在源和接受容器之间创建一个隧道,接受容器可以看到源容器指定的信息.
5|1自定义容器命名
连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。
虽然当创建容器的时候,系统默认会分配一个名字。自定义命名容器有2个好处:
# 1 . 自定义的命名,比较好记,比如一个web应用容器我们可以给它起名叫web # 1 . 当要连接其他容器时候,可以作为一个有用的参考点,比如连接web容器到db容器
使用 --name标记可以为容器自定义命名
docker run -d -P --name web nginx:latest 5597113c7667403419cdf395747c526463e0feeb62af27d8214f66fb782905da docker port 5597 80/tcp -> 0.0.0.0:1026 docker inspect -f "{{ .Name}}" 5597 /web # 注意: # --rm和 -d参数不能同时使用 # 容器的名称是唯一的。如果已经命名了一个叫`web`的容器,当你要再次使用web 这个名称的时候, # 需要先用docker rm来删除之前创建的同名容器。 # 在执行docker run的时候如果添加 --rm标记,则容器在终止后会立刻删除。
5|2容器互联
使用--link参数可以让容器之间安全的进行交互
下面创建一个新的数据库容器 docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=youmen mariadb # 接下来我们创建一个新的web容器,并将它连接到db容器. docker run -d -P --name nginx --link mysql1:mysql1 nginx:latest # 我们从下面的hosts文件看到,web容器链接到db容器,web容器将允许访问db容器的信息. docker exec -it web bash cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 mysql1 fa014ed6cd71 172.17.0.3 e43d7916f5b1 # Docker在两个互联的容器创建了一个安全隧道,而且不用映射他们的端口到宿主主机上, # 在启动mariadb的时候并没有使用-p和-P标记,从而避免了暴露数据库端口到外部网络上. # Docker使用2中方式为容器公开链接信息 1. 环境变量 2. 更新/etc/hosts文件 # 用户可链接多个父容器到子容器,比如连接多个web到db容器上, # 可以用Busybox镜像关联然后ping一下,说明是能互通的。
6|0高级网络配置
当Docker启动时,会自动在主机上创建一个docker0虚拟网桥,实际上是Linux 的一个bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。
同时,Docker随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0接口。比如典型的 172.17.42.1,掩码为 255.255.0.0。此后启动的容器内的网口也会自动分配一个同一网段(172.17.0.0/16 )的地址。
当创建一个Docker容器的时候,同时会创建了一对 veth pair接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0 ;另一端在本地并被挂载到docker0网桥,名称以 veth开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。
7|0快速配置指南
# 下面是一个跟Docker网络相关的命令列表. # 其中有些命令选项只有在Docker服务启动的时候才能配置,而且不能马上生效. -b BRIDGE or --bridge=bridge # 指定容器挂载的网桥 --bip=CIDR # 定制docker0的掩码 -H SOCKET...or --host=SOCKET... # docker服务接受命令的通道 --icc=true | false # 是否支持容器之间进行通信. --ip-forward=true|false # 请看下文容器之间的通信 --iptables=true|false # 禁止Docker添加iptables规则 --mtu=BYTES # 容器网络中的MTU # 下面2个命令选项既可以在启动服务时指定,也可以在Docker服务启动(docker run)时候指定, # 在Docker服务启动时候会成为默认值,后面执行docker run时可以覆盖设置的默认值。 --dns=IP_ADDRESS ... # 使用指定的DNS服务器 --dns=search=DOMAIN... # 指定DNS搜索域 # 最后这些选项只有在docker run执行时使用,因为他是针对docker容器的特性内容 -h HOSTNAME or --hostname=HOSTNAME # 配置容器主机名 --link=CONTAINER_NAME:ALIAS # 添加到另一个容器的连接 --net=bridge |none|container:NAME_or_ID |host # 配置容器的桥接模式 -P SPEC or --publish=SPEC # 映射容器端口到宿主主机 -P or --publish-all=true |false # 映射容器所有端口到宿主主机.
8|0容器访问控制
容器访问外部网络
容器的访问控制,主要通过Linux上的iptables防火墙来进行管理和实现,iptables是linux上默认的防火墙,且大多数发行版都自带.
# 容器要想访问外部网络,则需要本地系统的转发支持,在linux系统中,检查转发是否打开: sysctl -p|grep ipv4.ip_forward net.ipv4.ip_forward = 0 # 如果为0说明没有开启转发,需要手动打开,到这个/etc/sysctl.conf配置文件加上并sysctl -p刷新生效即可.
容器之间访问
容器之间相互访问,需要两方面的支持
容器的网络拓扑是否已经失联,默认情况下,所有容器都会被连接到docker0网桥上.
本地系统的防火墙软件iptables是否允许通过.
8|1访问所有端口
当启动docker服务的时候,默认会添加一条转发策略到iptables的FORWARD链上,策略为通过(ACCEPT)还是禁止(DROP)取决于配置--icc=true(缺省值)还是--icc=false,当然,如果手动指定--iptables=false则不会添加iptables规则.
可见,默认情况下,不同容器之间是允许网络互通的,为了安全考虑,可以在/etc/default/docker文件配置DOCKER_OPTS=--icc=false来禁止它。
8|2访问指定端口
在通过-icc=false关闭网络访问后,还可以通过--link=CONTAINER_NAME:ALIAS选项来访问容器的开放端口.
例如,在启动Docker服务时,可以同时使用icc=false --iptables=true参数关闭允许相互的网络访问,并让Docker可以修改系统中的iptables规则.之后,启动容器(docker run)时使用--link=CONTAINER_NAME:ALIAS选项,docker会在iptable中为两个容器分别添加一条ACCEPT规则,允许相互访问开放的端口(取决于Dockerfile中的EXPOSE行),当添加了--link=CONTAINER_NAME:ALIAS选项后,添加了iptables规则.
注意: --link=CONTAINER_NAME:ALIAS中的CONTAINER_NAME目前必须是Docker分配的名字,或使用--name参数指定的名字,否则主机名不会被识别.
映射容器端口到宿主机的实现
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。
外部访问容器实现容器允许外部访问可以通过-P或者-p来启用,但不管哪种办法,其实是在本地的iptable的nat表添加相应的规则。
如果希望永久绑定到某个固定的IP地址,可以在Docker配置文件/etc/default/docker中指定 DOCKER_OPTS="--ip=IP_ADDRESS",之后重启Docker服务即可生效.
__EOF__
本文链接:https://www.cnblogs.com/you-men/p/13124941.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【】一下。您的鼓励是博主的最大动力!