Docker存储与网络


一、Docker存储

 

docker存储volume
#环境 centos7.4 , Docker version 17.12.0-ce
docker volume创建、备份、nfs存储

#docker volume
数据存容器内,删容器即销毁全部数据
要保留的数据(数据持久化),需存储在容器外
docker volume是文件或目录,mount到docker容器中使用

docker volume
bind muount #挂载任意目录或文件
Volumes #固定路径的目录,docker管理
tmpfs mounts #存放宿主机内存中
image

docker volume 官网文档地址 https://docs.docker.com/storage/volumes/

#bind muount实例
 #docker挂载文件或目录到容器
 #创建目录及文件
mkdir -p /data/test1
echo 'docker volume'>/data/test1/test.txt
 #创建容器,-v 挂载目录(默认读写权限)
docker run -dit --name busybox1 -v /data/test1:/data/test1 busybox

 #查看
docker exec busybox1 cat /data/test1/test.txt
 #修改文件后,在查看本地是否更改
docker exec busybox1 echo my files>>/data/test1/test.txt
docker exec busybox1 cat /data/test1/test.txt
cat /data/test1/test.txt
为保证Dockerfile可移植,构建镜像不能使用bind muount

#tmpfs mounts
# 使用--tmpfs
docker run -dit --name tmpfs-test --tmpfs /app busybox
#Volumes
#不指定挂载目录,默认目录/var/lib/docker/volumes//_data/
#docker volumes可管理,官方推荐

#使用Volumes

#不指定挂载目录,自动创建 volumes/<ID号>/_data/
docker run -dit --name busybox2 -v /data/test busybox
#在容器创建目文件
docker exec busybox2 touch /data/test/test2.txt
#在宿主机查看文件路径
find /var/lib/docker/volumes -name test2.txt
docker inspect busybox2 |grep  Source
#docker volume命令管理

 #创建volume
docker volume create volume-test1
 #查看参数
docker inspect volume-test1
 #使用volume
docker run -dit --name busybox3 -v volume-test1:/volume busybox
 #查看
docker inspect -f {{.Mounts}} busybox3

 #查看docker数据卷
docker volume ls
 #删除没使用的数据卷(谨慎使用)
docker volume prune
Bind mounts和volumes都通过-v或--volume挂载,tmpfs使用--tmpfs
三种都可以使用--mount挂载,格式更清晰,官方推荐使用

#docker volume 数据共享
挂载相同目录
使用volume container
#数据卷容器 volume container

# --volumes-from 容器名,就会传递容器的挂载目录(volume参数传递)

 #创建容器busybox4(不需要启动)
mkdir -p /data/test2
echo 'busybox4'>/data/test2/test.txt
docker create --name busybox4 -v /data/test2:/data/test2 busybox

 # --volumes-from 使用其它容器的volume
docker run -dit --name busybox5 --volumes-from busybox4 busybox
 #查看
docker exec busybox5 cat /data/test2/test.txt

 #挂载多个 数据卷容器
docker run -dit --name busybox6 --volumes-from busybox4 --volumes-from busybox1 busybox
docker exec busybox6 ls /data/  #查看
#docker volume 备份
备份volume挂载目录
使用容器--volumes-from备份
#使用数据卷容器备份busybox4的volumes

docker run --rm --volumes-from busybox4 -v $(pwd):/backup busybox \
  tar cvf /backup/backup.tar /data/test2/
.

以上docker volume实例,全部在单台docker主机
docker集群环境,需要使用共享存储、分布式存储

#docker volume使用NFS存储
 #NFS服务端,配置nfs共享
yum install nfs-utils rpcbind -y
mkdir -p /data/nfs/docker
echo "/data/nfs *(rw,no_root_squash,sync)">>/etc/exports
exportfs -r
systemctl start rpcbind nfs-server
systemctl enable rpcbind nfs-server
showmount -e localhost


 #nfs客户端
yum install -y nfs-utils rpcbind

 #创建volume 连接 172.16.50.43:/data/nfs
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=172.16.50.43,rw \
  --opt device=:/data/nfs \
  volume-nfs

 #查看
docker volume ls
docker volume inspect volume-nfs

 #容器使用volume-nfs
docker run -dit --name busybox7 -v volume-nfs:/nfs busybox
 #查看
docker inspect -f {{.Mounts}} busybox7
df -h |grep /data/nfs
 #volume目录/var/lib/docker/volumes/volume-nfs/_data自动挂载到了nfs服务上

 #容器创文件测试
docker exec busybox7 touch /nfs/testfiles.txt
#使用volume driver 可实现更多的backend

#删除测试容器,volume

docker rm -f -v tmpfs-test busybox{1,2,3,4,5,6,7}    
 #-f 强制删除,-v 删除volume  
docker volume prune  
docker volume创建、备份、nfs存储
[root@localhost ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1fb916fb0e13        6a                  "sh"                2 hours ago         Created                                 hello2
9fb1ff8de577        6a                  "sh"                2 hours ago         Up 7 minutes                            hello
[root@localhost ~]# docker start 1
1
[root@localhost ~]# docker stats
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9fb1ff8de577        0.00%               56KiB / 993MiB      0.01%               648B / 0B           0B / 0B             0
^C
[root@localhost ~]# docker update -m 500m --memory-swap -1 9f
9f
[root@localhost ~]# docker stats
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9fb1ff8de577        0.00%               56KiB / 500MiB      0.01%               648B / 0B           0B / 0B             0
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9fb1ff8de577        0.00%               56KiB / 500MiB      0.01%               648B / 0B           0B / 0B             0
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9fb1ff8de577        0.00%               56KiB / 500MiB      0.01%               648B / 0B           0B / 0B             0
CONTAINER           CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
9fb1ff8de577        0.00%               56KiB / 500MiB      0.01%               648B / 0B           0B / 0B             0

 ———————————————— 
版权声明:本文为CSDN博主「cakincqm」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chengqiuming/article/details/78987167
docker update可以动态资源限制

 

1.停止正在运行的docker: systemctl stop docker 

2.创建文件夹:mkdir -p /xxx/disk  (xxx/disk为新磁盘目录名)

3.移动/var/lib/docker/目录到新目录中: mv /var/lib/docker /xxx/disk/  ###(假设新磁盘空间多的话  先copy -r /var/lib/docker . 一份)

4.软连接/disk/docker到/var/lib/里: ln -s /xxx/disk/docker /var/lib/

5.启动docker: systemctl start docker
docker容器存放目录磁盘空间满了,转移数据修改Docker默认存储位置

 

1.将数据从宿主机挂载到容器中的三种方式


Docker提供三种方式将数据从宿主机挂载到容器中:
•volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes 会在这个目录下创建相应的存储目录)。保存数据的最佳方式。(默认模式)
•bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
•tmpfs:挂载存储在主机系统的内存中,而不会写入主机的文件系统。如果不希望将数据持久存储在任何位置,可以使用tmpfs,同时避免写入容器可写层提高性能。

 

 2.Volume

步骤一:管理卷:
# docker volume create nginx-vol   创建一个名为nginx-vol的存储卷
# docker volume ls       查看所有的逻辑卷
# docker volume inspect nginx-vol     查看该卷的详细信息
步骤二:用卷创建一个容器:
# docker run -d --name=nginx-test --mount type=volume(默认是volume,可以省略),src=nginx-vol,dst=/usr/share/nginx/html nginx  #新版 建议使用 ,更通用
# docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx  #老版本使用
步骤三 清理:
# docker stop nginx-test  停容器
# docker rm nginx-test    删容器
# docker volume rm nginx-vol  删除卷
注意:
1.如果没有指定卷,自动创建。
2.建议使用--mount,更通用。
参考网址:https://docs.docker.com/engine/admin/volumes/volumes/#start-a-container-with-a-volume
[root@docker01 docker]# docker volume create nginx-vol
nginx-vol
[root@docker01 docker]# docker volume ls  #/var/lib/docker/volumes/nginx-vol/_data  <---> nginx-vol数据目录
DRIVER              VOLUME NAME
local               nginx-vol
[root@docker01 docker]# docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx:1.15
a332324e37f451cc1ab985546c00d2341230de057cddee036f37ed4c6e94bc8f
[root@docker01 docker]# docker ps -l  #查看最近一个产生的容器
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
a332324e37f4        nginx:1.15          "nginx -g 'daemon of…"   18 seconds ago      Up 12 seconds       80/tcp              nginx-test
[root@docker01 docker]# 
[root@docker01 docker]# docker  container inspect a332324e37f4 | grep -C 3  _data #查看匹配语句的前后三行
            {
                "Type": "volume",
                "Name": "nginx-vol",
                "Source": "/var/lib/docker/volumes/nginx-vol/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode":
                
                
                
[root@docker01 docker]# ls /var/lib/docker/volumes/nginx-vol/_data  
50x.html  index.html         #/usr/share/nginx/html下面的数据 挂载到了宿主机
[root@docker01 docker]#
[root@docker01 docker]# docker  container inspect a332324e37f4 | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.4",
                    "IPAddress": "172.17.0.4",
[root@docker01 docker]# curl 172.17.0.4
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@docker01 docker]# vim /var/lib/docker/volumes/nginx-vol/_data/index.html 
[root@docker01 docker]# cat /var/lib/docker/volumes/nginx-vol/_data
cat: /var/lib/docker/volumes/nginx-vol/_data: 是一个目录
[root@docker01 docker]# cat /var/lib/docker/volumes/nginx-vol/_data/index.html 
hello world
[root@docker01 docker]# curl 172.17.0.4
hello world
[root@docker01 docker]# 
Volume示例

 

 

3.Bind Mounts

用卷创建一个容器:
# docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx  #新版本
# docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx  #老版本  
/app/wwwroot 宿主机的目录,会用/app/wwwroot的内容覆盖掉/usr/share/nginx/html

验证绑定:
# docker inspect nginx-test

清理:
# docker stop nginx-test
# docker rm nginx-test
注意:
1.如果源文件/目录(宿主机上没有这个目录)没有存在,不会自动创建,会抛出一个错误。
2.如果挂载目标在容器中非空目录,则该目录现有内容将被隐藏。 #src=/app/wwwroot里面的内容 将覆盖 dst=/usr/share/nginx/html的内容
https://docs.docker.com/engine/admin/volumes/bind-mounts/#start-a-container-with-a-bind-mount

 

 

 

4.小结

Volume特点:
多个运行容器之间共享数据。
当容器停止或被移除时,该卷依然存在。
多个容器可以同时挂载相同的卷。
当明确删除卷时,卷才会被删除。
将容器的数据存储在远程主机或其他存储上
将数据从一台Docker主机迁移到另一台时,先停止容器,然后备份卷的目录(/var/lib/docker/volumes/Bind Mounts特点:
从主机共享配置文件到容器。默认情况下,挂载主机/etc/resolv.conf到每个容器,提供DNS解析。
在Docker主机上的开发环境和容器之间共享源代码。例如,可以将Maven target目录挂载到容器中,每次在Docker主机上构建Maven项目时,容器都可以访问构建的项目包。
当Docker主机的文件或目录结构保证与容器所需的绑定挂载一致时

 

 

二、Docker网络 

我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下5种网络模式:

 

下面分别介绍一下Docker的各个网络模式。

1 host模式

格式:

docker run -it --name myubuntu --net=host ubuntu /bin/bash

众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
例如,我们在10.10.101.105/24的机器上用host模式启动一个含有web应用的Docker容器,监听tcp80端口。当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.101.105:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

•-–net=host容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。
[root@docker01 docker]# docker run -it --net=host busybox 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:0c:29:56:32:aa brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.10/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::8f4:8fc3:786b:527f/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:ec:33:a2:25 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:ecff:fe33:a225/64 scope link 
       valid_lft forever preferred_lft forever
5: veth7a3a6c5@if4: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether a6:d1:6f:39:28:8b brd ff:ff:ff:ff:ff:ff
    inet6 fe80::a4d1:6fff:fe39:288b/64 scope link 
       valid_lft forever preferred_lft forever
7: veth3d53b29@if6: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether ba:f7:ab:f4:e9:33 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b8f7:abff:fef4:e933/64 scope link 
       valid_lft forever preferred_lft forever
9: vethc841c0a@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether 1e:48:38:75:54:ee brd ff:ff:ff:ff:ff:ff
    inet6 fe80::1c48:38ff:fe75:54ee/64 scope link 
       valid_lft forever preferred_lft forever
/ # 
示例

 

 

2 container模式

格式:

docker run -it --name myubuntu --net=container:NAME_OR_ID ubuntu /bin/bash

在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

•container–net=container:Name/ID与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的。

[root@docker01 docker]# docker run -it --name bs1 busybox 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 

开另一个窗口
[root@docker01 ~]# docker ps  -l
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
61af36f47fbf        busybox             "sh"                31 seconds ago      Up 25 seconds                           bs1
[root@docker01 ~]# docker run -it --name bs2 --net=container:61af36f47fbf  busybox  #网络一样
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
示例

 

 

 

3 none模式

格式:

docker run -it --name myubuntu --net=none ubuntu /bin/bash

这个模式和前两个不同。在这种模式下,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

•-–net=none获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
[root@docker01 docker]# docker run -it --net=none busybox 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
/ # 
示例

 

 

 

4 bridge模式

bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。下面着重介绍一下此模式。

4.1 bridge模式的拓扑

当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。接下来就要为容器分配IP了,Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,连接到docker0的容器就从这个子网中选择一个未占用的IP使用。如一般Docker会使用172.17.0.0/16这个网段,并将172.17.42.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。单机环境下的网络拓扑如下,主机地址为10.10.101.105/24。

 

 

[root@docker01 ~]# ifconfig
br-36766c64e493: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:37ff:fea2:3f9d  prefixlen 64  scopeid 0x20<link>
        ether 02:42:37:a2:3f:9d  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 1231 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29  bytes 2108 (2.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

br-9cdfea34f9cd: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.0.1  netmask 255.255.0.0  broadcast 172.19.255.255
        inet6 fe80::42:63ff:fe56:f9b9  prefixlen 64  scopeid 0x20<link>
        ether 02:42:63:56:f9:b9  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:ecff:fe33:a225  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ec:33:a2:25  txqueuelen 0  (Ethernet)
        RX packets 46244  bytes 2600005 (2.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49929  bytes 173907794 (165.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.10  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::8f4:8fc3:786b:527f  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:56:32:aa  txqueuelen 1000  (Ethernet)
        RX packets 440988  bytes 602710620 (574.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 244878  bytes 22083517 (21.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 124  bytes 21089 (20.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 124  bytes 21089 (20.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth3d53b29: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::b8f7:abff:fef4:e933  prefixlen 64  scopeid 0x20<link>
        ether ba:f7:ab:f4:e9:33  txqueuelen 0  (Ethernet)
        RX packets 22  bytes 3316 (3.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 36  bytes 2954 (2.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth523916d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::d8a5:7aff:fe29:bc3e  prefixlen 64  scopeid 0x20<link>
        ether da:a5:7a:29:bc:3e  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16  bytes 1312 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth7a3a6c5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::a4d1:6fff:fe39:288b  prefixlen 64  scopeid 0x20<link>
        ether a6:d1:6f:39:28:8b  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 1231 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 29  bytes 2108 (2.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethc841c0a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::1c48:38ff:fe75:54ee  prefixlen 64  scopeid 0x20<link>
        ether 1e:48:38:75:54:ee  txqueuelen 0  (Ethernet)
        RX packets 13  bytes 1901 (1.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 28  bytes 1996 (1.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethca5575e: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::c057:f1ff:fe10:aed7  prefixlen 64  scopeid 0x20<link>
        ether c2:57:f1:10:ae:d7  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16  bytes 1312 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethe529e61: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::70f0:1eff:fed8:344d  prefixlen 64  scopeid 0x20<link>
        ether 72:f0:1e:d8:34:4d  txqueuelen 0  (Ethernet)
        RX packets 2666  bytes 180649 (176.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3300  bytes 19520939 (18.6 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


[root@docker01 docker]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
Image docker.io/library/busybox:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
e2334dd9fee4: Downloading 
latest: Pulling from library/busybox
e2334dd9fee4: Pull complete 
Digest: sha256:a8cf7ff6367c2afa2a90acd081b484cbded349a7076e7bdf37a05279f276bc12
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
[root@docker01 docker]# docker run -it busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
-–net=bridge 示例

 

 

 

 

 

 

 

Docker完成以上网络配置的过程大致是这样的:

1. 在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。

2. Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。

3. 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
网络拓扑介绍完后,接着介绍一下bridge模式下容器是如何通信的。

 

 

4.2 bridge模式下容器的通信

在bridge模式下,连在同一网桥上的容器可以相互通信(若出于安全考虑,也可以禁止它们之间通信,方法是在DOCKER_OPTS变量中设置--icc=false,这样只有使用--link才能使两个容器通信)。
容器也可以与外部通信,我们看一下主机上的Iptable规则,可以看到这么一条

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

这条规则会将源地址为172.17.0.0/16的包(也就是从Docker容器产生的包),并且不是从docker0网卡发出的,进行源地址转换,转换成主机网卡的地址。这么说可能不太好理解,举一个例子说明一下。
假设主机有一块网卡为eth0,IP地址为10.10.101.105/24,网关为10.10.101.254。从主机上一个IP为172.17.0.1/16的容器中ping百度(180.76.3.151)。
IP包首先从容器发往自己的默认网关docker0,包到达docker0后,也就到达了主机上。然后会查询主机的路由表,发现包应该从主机的eth0发往主机的网关10.10.105.254/24。接着包会转发给eth0,并从eth0发出去(主机的ip_forward转发应该已经打开)。
这时候,上面的Iptable规则就会起作用,对包做SNAT转换,将源地址换为eth0的地址。这样,在外界看来,这个包就是从10.10.101.105上发出来的,Docker容器对外是不可见的。 那么,外面的机器是如何访问Docker容器的服务呢?我们首先用下面命令创建一个含有web应用的容器,将容器的80端口映射到主机的80端口。 docker run -d --name web -p 80:80 fmzhen/simpleweb 然后查看Iptable规则的变化,发现多了这样一条规则: -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.5:80 此条规则就是对主机eth0收到的目的端口为80的tcp流量进行DNAT转换,将流量发往172.17.0.5:80,也就是我们上面创建的Docker容器。所以,外界只需访问10.10.101.105:80就可以访问到容器中得服务。 除此之外,我们还可以自定义Docker使用的IP地址、DNS等信息,甚至使用自己定义的网桥,但是其工作方式还是一样的。

 

[root@docker01 docker]# docker run -it --name bs4 busybox 
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 

容器 ---> 外网
eth0@if18 ---> 宿主机vethxxx(随机字符串) ---> 宿主机docker0 ---SNAT---> 宿主机ens33 --->外界
容器 <---- 外网
eth0@if18 <--- 宿主机vethxxx(随机字符串) <--- 宿主机docker0 <---DNAT--- 宿主机ens33 <---外界

[root@docker01 ~]# ifconfig
br-36766c64e493: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:37ff:fea2:3f9d  prefixlen 64  scopeid 0x20<link>
        ether 02:42:37:a2:3f:9d  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 1231 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 1982 (1.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:ecff:fe33:a225  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ec:33:a2:25  txqueuelen 0  (Ethernet)
        RX packets 41  bytes 5874 (5.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 57  bytes 4586 (4.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.10  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::8f4:8fc3:786b:527f  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:56:32:aa  txqueuelen 1000  (Ethernet)
        RX packets 145613  bytes 201043013 (191.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 71781  bytes 6554643 (6.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 124  bytes 21089 (20.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 124  bytes 21089 (20.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth3d53b29: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::b8f7:abff:fef4:e933  prefixlen 64  scopeid 0x20<link>
        ether ba:f7:ab:f4:e9:33  txqueuelen 0  (Ethernet)
        RX packets 22  bytes 3316 (3.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 33  bytes 2828 (2.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth523916d: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::d8a5:7aff:fe29:bc3e  prefixlen 64  scopeid 0x20<link>
        ether da:a5:7a:29:bc:3e  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 16  bytes 1312 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth5a8ff4b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::6854:20ff:fec2:43fa  prefixlen 64  scopeid 0x20<link>
        ether 6a:54:20:c2:43:fa  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth7a3a6c5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::a4d1:6fff:fe39:288b  prefixlen 64  scopeid 0x20<link>
        ether a6:d1:6f:39:28:8b  txqueuelen 0  (Ethernet)
        RX packets 6  bytes 1231 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 26  bytes 1982 (1.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

vethc841c0a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::1c48:38ff:fe75:54ee  prefixlen 64  scopeid 0x20<link>
        ether 1e:48:38:75:54:ee  txqueuelen 0  (Ethernet)
        RX packets 13  bytes 1901 (1.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 25  bytes 1870 (1.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@docker01 ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    100    0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-36766c64e493
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 ens33
[root@docker01 ~]# 
[root@docker01 ~]# yum -y install bridge-utils
[root@docker01 ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
br-36766c64e493        8000.024237a23f9d    no        veth523916d
docker0        8000.0242ec33a225    no        veth3d53b29
                            veth5a8ff4b
                            veth7a3a6c5
                            vethc841c0a
[root@docker01 ~]# 



[root@docker01 ~]# iptables-save  #NAT转发规则
# Generated by iptables-save v1.4.21 on Sat May  2 16:33:20 2020
*filter
:INPUT ACCEPT [521:43254]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [393:50826]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o br-36766c64e493 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-36766c64e493 -j DOCKER
-A FORWARD -i br-36766c64e493 ! -o br-36766c64e493 -j ACCEPT
-A FORWARD -i br-36766c64e493 -o br-36766c64e493 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i br-36766c64e493 ! -o br-36766c64e493 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o br-36766c64e493 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sat May  2 16:33:20 2020
# Generated by iptables-save v1.4.21 on Sat May  2 16:33:20 2020
*nat
:PREROUTING ACCEPT [9:1909]
:INPUT ACCEPT [9:1909]
:OUTPUT ACCEPT [8:602]
:POSTROUTING ACCEPT [8:602]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.18.0.0/16 ! -o br-36766c64e493 -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i br-36766c64e493 -j RETURN
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 88 -j DNAT --to-destination 172.17.0.3:80
COMMIT
# Completed on Sat May  2 16:33:20 2020
[root@docker01 ~]# 
容器网络访问原理

 

 

5.用户自定义模式

用户可以通过Docker网络驱动器或其他的网络驱动器自定义网络。你可以将许多容器连接到同一个网络上,一旦连接到了自定义的网络上,容器之间就可以通过对方的IP地址和主机名来进行通信了。
如果容器连接到了用户自定义的网络上,容器的/etc/hosts文件会加入在同一个网络中的其他所有容器的IP地址。 
由于容器有可能随时改变/etc/hosts文件,容器中的程序可能会读取到不完整的甚至空的/etc/hosts文件。通常重新读取可以解决这个问题。

重要:自定义网络与默认的bridge原理一样,但自定义网络具备内部DNS发现,可以通过容器名或者主机名容器之间网络通信。后面介绍的lnmp就用到了该模式

[root@docker01 ~]# docker network ls #常用的网络模式查看
NETWORK ID          NAME                DRIVER              SCOPE
dcfaf483d096        bridge              bridge              local
884bc10989a5        host                host                local
30612ce6f04d        none                null                local
[root@docker01 ~]# docker network create test_net #创建一个自定义的网络
36766c64e4930212b3e1eeff0df8417f930b28140619720b5d87c9e393695d25
[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
dcfaf483d096        bridge              bridge              local
884bc10989a5        host                host                local
30612ce6f04d        none                null                local
36766c64e493        test_net            bridge              local
[root@docker01 ~]# docker run -it --name bs3 --net=test_net busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
示例

 

posted @ 2019-08-23 10:20  冥想心灵  阅读(322)  评论(0编辑  收藏  举报