03 . Docker数据资源管理与网络
Docker数据卷
在容器中管理数据主要有两种方式
# 数据卷(Data volumes)
# 数据卷容器(Data volume containers)
# 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
# 1. 数据卷可以在容器之间共享和重用
# 2. 对数据卷的修改会立即生效
# 3. 对数据卷的更新,不会影响镜像
# 4. 卷会一直存在,知道没有容器使用
# 数据卷的使用类似于Linux下对目录或文件进行mount.
创建一个数据卷
在用 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
数据卷容器
- 如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。
- 数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
- 首先,创建一个命名的数据卷容器:
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 命令来指定同时删除关联的容器。
# 这可以让用户在容器之间升级和移动数据卷。
利用数据卷容器来备份、恢复、迁移数据卷
# 首先使用 --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/
[root@745690bc3a7c ~]# 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
root@45f97c29e5b3:/# ls -lh /dbdata/etc.tar.gz
-rw-r--r-- 1 root root 660K Dec 13 08:04 /dbdata/etc.tar.gz
# 接下来我们只需要再创建一个跟以前一样的容器,挂载此数据卷容器,就可以数据恢复了.
资源配置
内存资源
# 设置内存我们可以有四种方式:
# 默认的方式设置最低值,容器可以使用大于此最低值的内存数
# 设置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
CPU资源限制
默认情况下,所有容器获得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
网络限制
--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
Docker网络
外部访问容器
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
容器的互联
容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式
该系统会在源和接受容器之间创建一个隧道,接受容器可以看到源容器指定的信息.
自定义容器命名
连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。
虽然当创建容器的时候,系统默认会分配一个名字。自定义命名容器有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标记,则容器在终止后会立刻删除。
容器互联
使用--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一下,说明是能互通的。
高级网络配置
当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 就创建了在主机和所有容器之间一个虚拟共享网络。
快速配置指南
# 下面是一个跟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 # 映射容器所有端口到宿主主机.
容器访问控制
容器访问外部网络
容器的访问控制,主要通过Linux上的iptables防火墙来进行管理和实现,iptables是linux上默认的防火墙,且大多数发行版都自带.
# 容器要想访问外部网络,则需要本地系统的转发支持,在linux系统中,检查转发是否打开:
sysctl -p|grep ipv4.ip_forward
net.ipv4.ip_forward = 0
# 如果为0说明没有开启转发,需要手动打开,到这个/etc/sysctl.conf配置文件加上并sysctl -p刷新生效即可.
容器之间访问
容器之间相互访问,需要两方面的支持
容器的网络拓扑是否已经失联,默认情况下,所有容器都会被连接到docker0网桥上.
本地系统的防火墙软件iptables是否允许通过.
访问所有端口
当启动docker服务的时候,默认会添加一条转发策略到iptables的FORWARD链上,策略为通过(ACCEPT)还是禁止(DROP)取决于配置--icc=true(缺省值)还是--icc=false,当然,如果手动指定--iptables=false则不会添加iptables规则.
可见,默认情况下,不同容器之间是允许网络互通的,为了安全考虑,可以在/etc/default/docker文件配置DOCKER_OPTS=--icc=false来禁止它。
访问指定端口
在通过-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服务即可生效.
03 . Docker数据资源管理与网络的更多相关文章
- Docker进阶-资源管理Swarm+Portainer
Docker Swarm资源管理 Docker Swarm是Docker官方三剑客项目之一,提供Docker容器集群服务,是Docker官方对容器云生态进行支持的核心方案. 使用它,用户可以将多个Do ...
- Docker进阶一:网络篇
理解Docker0 查看本地ip ip addr [root@VM-0-6-centos ~]# ip addr #本机回环地址 1: lo: <LOOPBACK,UP,LOWER_UP> ...
- Docker的4种网络模式
我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: · host模式,使用--net=host指定. · container ...
- docker学习3-虚拟网络模式
一.虚拟机网络模式 在理解docker网络隔离前,先看下之前虚拟机里对网络的处理,VirtualBox中有4中网络连接方式: NAT Bridged Adapter Internal Host-onl ...
- Docker容器资源管理
本文作者是Red Hat的软件工程师 - Marek Goldmann,这篇文章详细介绍了Docker容器的资源管理,总共分了三大部分:CPU.内存以及磁盘IO.作者通过实践举例给读者勾勒出一幅清晰明 ...
- 【05】循序渐进学 docker:系统资源和网络
写在前面的话 在上一篇学习 Dockerfile 的时候其实还有几个相当重要得关键中没有谈到,但没关系,在后面的内容会单独提出来一个一个的学习.这里就先谈谈关于资源的控制个容器的网络~ 资源限制 其实 ...
- Docker数据持久化及实战(Nginx+Spring Boot项目+MySQL)
Docker数据持久化: Volume: (1)创建mysql数据库的container docker run -d --name mysql01 -e MYSQL_ROOT_PASSWORD= my ...
- Docker底层架构之网络实现
前言 Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备(特别是 vethpair). 基本原理 首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来 ...
- 记录 Docker 的学习过程 (网络篇)
打开2个会话,分别运行以下命令 # docker run -it -P --name nginx2 nginx #-P 端口随机映射 再打开一个会话查看 运行中的容器 # docker ps -aCO ...
随机推荐
- akka-grpc - 应用案例
上期说道:http/2还属于一种不算普及的技术协议,可能目前只适合用于内部系统集成,现在开始大面积介入可能为时尚早.不过有些项目需求不等人,需要使用这项技术,所以研究了一下akka-grpc,写了一篇 ...
- Python最火的第三方开源测试框架 ——pytest
一.介绍 本篇文章是介绍的是Python 世界中最火的第三方单元测试框架:pytest.它有如下主要特性: assert 断言失败时输出详细信息(再也不用去记忆 self.assert* 名称了) 自 ...
- include标签—引用文件路径
今天给大家讲解的是include标签,在打代码的时候总会出现一些重复的样式,这个时候就可以用include标签来减少打代码的次数. 文件名index.html,代码: {% from 'macros/ ...
- vim编辑器 与etc目录
第1章 目录结构 1.1 vim vim故障 vim 是vi的升级版本 vi类似于文本文档 vim类似于notepad++ 编辑 必须先安装vim命令 yum -y insta ...
- java工具类去掉字符串String中的.点。android开发java程序员常用工具类
下面是工具类详细代码: package com.qq986945193.david; /** * qq986945193 Project * ============================= ...
- Photon PUN 三 RPCs & RaiseEvent
官方文档地址 https://doc.photonengine.com/en-us/pun/current/manuals-and-demos/rpcsandraiseevent 一, RPC P ...
- 【基础知识】Unity查漏补缺
最近发现了一些平时不太注重的知识点,特此建立个专题,把零散的东西.疏忽的东西临时记录下来. Mecanim动画系统: 1)设置AnimatorController时,如果某个动作播放不正常. 首先打开 ...
- 白嫖码云Pages,两分钟的事,就能搭个百度能搜到的个人博客平台
为了攒点钱让女儿做个富二代(笑),我就没掏钱买服务器,白嫖 GitHub Pages 搭了一个博客平台.不过遗憾的是,GitHub Pages 只能被谷歌收录,无法被百度收录,这就白白损失了一大波流量 ...
- [bash] 获取linux主机名,检视内中是否有特定字符串
代码: #!/bin/bash hostname=$(hostname) #调用hostname命令获取主机名放入变量hostname中 #echo $hostname if [ `echo ${ho ...
- leetcode刷题-74搜索二维矩阵
题目 编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值.该矩阵具有如下特性: 每行中的整数从左到右按升序排列.每行的第一个整数大于前一行的最后一个整数.示例 1: 输入:matrix ...