用户在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或者 需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这必然会涉及 到容器的数据管理
(1)Data Volume (数据卷)
(2)Data Volume Dontainers --- 数据卷容器
Data Volume ---数据卷
Data Volume 本质上是 Docker Host 文件系统中的目录或文件,使用类似 与 Linux 下对目录或者文件进行 mount 操作。数据卷可以在容器之间共享 和重用,对数据卷的更改会立马生效,对数据卷的更新不会影响镜像,卷会一 直存在,直到没有容器使用
Data Volume 有以下特点:
a)Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)。
b)容器可以读写 volume 中的数据。
c)volume 数据可以被永久的保存,即使使用它的容器已经销毁。
Data Volume的使用:
通过-v 参数格式为 <host path>:<container path>
a)运行一个容器,并创建一个数据卷挂载到容器的目录上 docker run -dti -v /web nginx /bin/bash 利用 nginx的镜像运行一个容器,并在容器内创建一个数据卷挂载到容器 的 /web 目录上
[[email protected] ~]# docker run -dti -v /web nginx:latest /bin/bash d4e002045c2bd022a826dbd2805b121dd43c41443d86eeb6515f616bf52c8549
b)运行一个容器,本地创建/date目录挂载到容器的/var/log/目录上
docker run -dti -v /data:/var/log nginx /bin/bash
docker run -dti -v /data:/var/log centos:latest /bin/bash
25773c239584614e301644db01b7275377887c9bbefe8c54cf5cd6be2917ab54
DataVolumeDontainers --- 数据卷容器
如果用户需要在容器之间共享一些持续更新的数据,最简单的方法就是使用数据 卷容器,其实数据卷容器就是一个普通的容器,只不过是专门用它提供数据卷供 其他容器挂载使用
Data Volume Dontainers使用:
a)创建一个名为 dbdata 的数据卷,并在其中创建一个数据卷挂载到 /dbdata
docker run -dti -v /dbdata --name dbser centos:7.0
--name 参数为给容器指定名字为dbser方便记忆
[[email protected] ~]# docker run -dti -v /dbdata --name dbser centos:latest 82b264b29e56700afebaa7acec8c69309964f27dafd271454048b8b7a113720e
b)其他容器使用--volume-from 去挂载dbdata容器中的/dbdata数据卷 eg :创建 db1&db2 两个容器, 并挂载 /dbdata 数据卷到本地
docker run -dti --volumes-from dbserver --name db1 centos:7.0
docker run -dti --volumes-from dbserver --name db2 centos:7.0
此时,容器 db1 和 db2 同时挂载了同一个数据卷到本地相同 /dbdata 目录。三个容器任何一个目录下的写入,都可以时时同步到另外两个
[[email protected] ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES aff1e64343bf centos:latest "/bin/bash" 4 minutes ago Up 4 minutes db2 893450737ade centos:latest "/bin/bash" 4 minutes ago Up 4 minutes db1 82b264b29e56 centos:latest "/bin/bash" 6 minutes ago Up 6 minutes dbser 在db2中创建jam文件,写入0330 [[email protected] ~]# docker exec -it aff1e64343bf /bin/bash [[email protected] dbdata]# echo "0330" >jam [[email protected] dbdata]# cat jam 0330 在db1中查看是否存在jam文件 [[email protected] ~]# docker exec -it 893450737ade /bin/bash [[email protected] /]# cd dbdata/ [[email protected] dbdata]# ls jam [[email protected] dbdata]# cat jam 0330 在dbser中查看jam文件是否存在 [[email protected] ~]# docker exec -it 82b264b29e56 /bin/bash [[email protected] /]# ls dbdata [[email protected] /]# cd dbdata/ [[email protected] dbdata]# ls jam [[email protected] dbdata]# cat jam 0330
一、docker网络介绍
大量的互联网应用服务需要多个服务组件,这往往需要多个容器之间通过网络 通信进行相互配合
docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络 docker 目前提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务,在启动容器的时候,如果不指定参数,在容器外部是没有办法通过网络来访问容器内部的网络应用和服务的
docker 安装时会自动在host上创建三个网络,我们查看一下docker网络:
docker network ls
[[email protected] ~]# docker network list NETWORK ID NAME DRIVER SCOPE 460b8a01b798 bridge bridge local d4ae07a1372e host host local 63bead0d7ffc none null local
二、docker--none网络
none 网络就是什么都没有的网络。挂在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过 --network=none 指定使用 none 网络。
none 网络的应用
封闭的网络意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。
比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密 码被窃取。
三、docker--host网络
连接到 host 网络的容器,共享 docker host 的网络栈,容器的网络配置与 host 完全一样。可以通过 --network=host 指定使用 host 网络
在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的。host 网络的使用场景又是什么呢?
直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率 有较高要求,就可以选择 host 网络。
当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。
Docker host 的另一个用途是让容器可以直接配置 host 网路。比如某些跨 host 的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进 行配置,比如管理 iptables
四、docker--bridge网络
docker 安装时会创建一个 命名为 docker0 的 linux bridge。如果不指定 --network,创建的容器默认都会挂到 docker0 上
当前 docker0 上没有任何其他网络设备,我们创建一个容器看看有什么变化
[[email protected] docker]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242ec43479a no vethb2a3b02 #以密钥对的形式挂到docker0
一个新的网络接口 vethb2a3b02 被挂到了 docker0 上,vethb2a3b02 就是 新创建容器的虚拟网卡。
进入刚才运行的容器查看网络,容器有一个网卡 [email protected]9
[[email protected] docker]# docker exec -it 5449774b40e5 /bin/sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 8: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
实际上 [email protected] 和 vethb2a3b02是一对 veth pair
veth pair 是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线 连接起来的一对网卡,网卡的一头([email protected])在容器中,另一头 (vethb2a3b02)挂在网桥 docker0 上,其效果就是将 [email protected] 也挂在了 docker0 上
可以看到,[email protected] 已经配置了 IP 172.17.0.3,为什么是这个网段呢?
看一下 bridge 网络的配置信息:
docker network inspect bridge
Config": [ { "Subnet": "172.17.0.0/16"
可以看到bridge 网络配置的 subnet 就是 172.17.0.0/16,并且网关是 172.17.0.1, 在docker0上
容器创建时,docker 会自动从 172.17.0.0/16 中分配一个 IP,这里 16 位的 掩码保证有足够多的 IP 可以供容器使用,(主机位是16位)
五、创建 user--defined网络
我们可通过 bridge 驱动创建类似前面默认的 bridge 网络
1)利用bridge驱动创建名为my-net2网桥(docker会自动分配网段):
docker network create --driver bridge my-net2
可以看到新创建的网络也自动被分配了子网ip。
[[email protected] ~]# docker network create --driver bridge net2 2edd5371dd2fbcb32c9c2b2a9420cb806e406edc011379c7c7c70f53d6c74585 [[email protected] ~]# docker network list NETWORK ID NAME DRIVER SCOPE 460b8a01b798 bridge bridge local d4ae07a1372e host host local 2edd5371dd2f net2 bridge local 63bead0d7ffc none null local [[email protected] ~]# docker network inspect net2。。。Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"
删除网桥:brctl delbr 网桥名
(4)利用bridge驱动创建名为my-net3网桥(user-defined网段及网关)
[[email protected] ~]# docker network create --driver bridge --subnet 172.18.2.0/24 --gateway 172.18.2.1 net3
报错:Error response from daemon: Pool overlaps with other one on this address space
这是因为新创建的网络自定义的子网ip与已有的网络子网ip冲突。
只需要重新定义子网ip段就行
[[email protected] ~]# docker network create --driver bridge --subnet 192.18.2.0/24 --gateway 192.18.2.1 net3 3f028deb3aa0b37ee69e3a04a0edb14c00b1933a415c2d0961a9eec7b4b2ecb1
重新查看网络配置信息:
[[email protected] ~]# docker network inspect net3 "Config": [ { "Subnet": "192.18.2.0/24", "Gateway": "192.18.2.1"
可以看到自定义的网络配置成功。
(5)启动容器使用新建的my-net3网络
docker run -itd --network=net3(网络名) 镜像名 /bin/sh(环境名)
[[email protected] ~]# docker run -itd --network=net3 busybox:latest /bin/sh 632e2d8245ade9e0a8ee9cf13d7105f19a2d28728e3d38b65423eb34ef38ac4c [[email protected] ~]# docker exec -it 632e2d8245ad /bin/sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 18: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:12:02:03 brd ff:ff:ff:ff:ff:ff inet 192.18.2.3/24 brd 192.18.2.255 scope global eth0 valid_lft forever preferred_lft forever
可以看到使用新建网络net3启动的容器会自动分配一个net3子网段内的ip。
(6)启动容器使用net3网络并指定ip(只有使用 --subnet 创建的网络才 能指定静态 IP,如果是docker自动分配的网段不可以指定ip)
[[email protected] ~]# docker run -itd --network=net3 --ip 192.18.2.4 busybox:latest /bin/sh
当然,这个指定的ip也要在net3的子网范围内。
(7)让已启动不同vlan的ningx容器,可以连接到my-net2(其实在nigx中新建了my-net2的网卡)
docker run -itd --network=net3 busybox:latest /bin/sh
docker network connect net2 容器名(id)
[[email protected] ~]# docker run -itd --network=net3 busybox:latest /bin/bash e42da501655faa6e2067a6d9ee6c49016ec49bb0dc750b78a82f2540751840c5
[[email protected] docker]# docker network connect net2 0d3e78d4298c [[email protected] docker]# docker exec -it 0d3e78d4298c /bin/sh / # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 20: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:12:02:04 brd ff:ff:ff:ff:ff:ff inet 192.18.2.4/24 brd 192.18.2.255 scope global eth0 valid_lft forever preferred_lft forever 24: [email protected]: <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 eth1 valid_lft forever preferred_lft forever
可以看到此容器同时拥有了net2和net3的子网ip。
(8)使用--name指定启动容器名字,可以使用docker自带DNS通信,但只能 工作在user-defined 网络,默认的 bridge 网络是无法使用 DNS 的。
[email protected] docker]# docker run -itd --network=net3 --name=b1 busybox 203fc1c4fb19dc1212da8f97dc8654b5b928f9ab1406bed4c39a31f76b686d4c [[email protected] docker]# docker run -itd --network=net3 --name=b2 busybox 5dfabb01d5d718429e382acb4115a1d8c4c7e2e89c302b899bcf5923be1df527 [[email protected] docker]# docker exec -it b1 /bin/sh / # ping b2 PING b2 (192.18.2.7): 56 data bytes 64 bytes from 192.18.2.7: seq=0 ttl=64 time=0.417 ms 64 bytes from 192.18.2.7: seq=1 ttl=64 time=0.110 ms 64 bytes from 192.18.2.7: seq=2 ttl=64 time=0.099 ms
在创建容器时使用相同网络,并且给容器命名的话
意思是给两个容器之间做了域名解析和配置相同网段,所以能ping通
(9)容器之间的网络互联
a). 首先创建一个 db 容器
[[email protected] ~]# docker run -itd --name db busybox
b). 创一个 web 容器,并使其连接到 db
[[email protected] ~]# docker run -itd --name web --link db:dblink busybox /bin/sh
-link db:dblink 实际是连接对端的名字和这个链接的名字,也就是和 db 容器 建立一个叫做 dblink 的链接
c).查看链接的情况
docker ps -a
[[email protected] ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 141e370eea76 busybox "/bin/sh" 8 seconds ago Up 7 seconds web 9f89a1945f6b busybox "sh" 54 seconds ago Up 53 seconds db
d)进入web容器,使用 ping 命令来测试网络链接的情况
[[email protected] ~]# docker exec -it 141e370eea76 /bin/sh/ # ping db PING db (172.17.0.4): 56 data bytes 64 bytes from 172.17.0.4: seq=0 ttl=64 time=0.445 ms
发现可以ping通,连接有效
e)尝试进入db容易,使用ping命令测试
[[email protected] docker]# docker exec -it 9f89a1945f6b /bin/sh / # ping web ping: bad address ‘web‘
发现无法ping通,因此可以推断出容器之间的网络连通是单向的,即哪个容器建立了连接,哪个容易才能连接到另一个容器,反之不行。
(10)容器端口映射 在启动容器的时候,如果不指定参数,在容器外部是没有办法通过网络来访问容 器内部的网络应用和服务的
当容器需要通信时,我们可以使用 -P (大) &&-p (小)来指定端口映射
-P : Docker 会随机映射一个 49000 ~ 49900 的端口到容器内部开放的网络端口
p :则可以指定要映射的端口,并且在一个指定的端口上只可以绑定一个容器。
支持的格式有
iP : HostPort : ContainerPort
IP : : ContainerPort
IP : HostPort :
如果不指定就随机
查看映射
docker port 容器名
拓展:用脚本删除所有容器
[[email protected] docker]# for id in `docker ps -a | grep a | awk -F " +" ‘{print $1}‘` ;do docker rm -f $id ;done
a)映射所有接口地址,此时绑定本地所有接口上的 5000 到容器的 5000 接口, 访问任何一个本地接口的 5000 ,都会直接访问到容器内部
docker run -dti -p 5000:5000 nginx /bin/bash
b)多次使用可以实现多个接口的映射
[[email protected] docker]# docker run -itd -p 5000:22 -p 5001:23 nginx /bin/bash
查看容器信息,发现新容器的的22,23端口都映射到了宿主机的5000和5001端口。
[[email protected] docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea3b9412d96d nginx "/bin/bash" 5 seconds ago Up 5 seconds 80/tcp, 0.0.0.0:5000->22/tcp, 0.0.0.0:5001->23/tcp hardcore_darwin
c)映射到指定地址的指定接口 此时会绑定本地 192.168.4.169 接口上的 5000 到容器的80 接口
docker run -dti -p 192.168.253.9:5000:80 nginx /bin/bash
[[email protected] docker]# docker run -dti -p 192.168.253.9:5000:80 nginx /bin/bash[[email protected] docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 132746ef0996 nginx "/bin/bash" About a minute ago Up About a minute 192.168.253.9:5000->80/tcp practical_lichterman
d) 映射到指定地址的任意接口 此时会绑定本地 192.168.4.169 接口上的任意一个接口到容器的 5000 接口
docker run -dti -p 192.168.4.169::5000 nginx /bin/bash
e) 使用接口标记来指定接口的类型
docker run -dti -p 192.168.4.169::5000/UDP nginx /bin/bash
指定接口位udp类型
(11)实验:通过端口映射实现访问本地的 IP:PORT 可以访问到容器内的 web
a)将容器80端口映射到主机8080端口,注意末尾不要加环境变量
docker run -itd -p 80:80 --name nginx nginx:latest
b) 查看刚运行docker
docker ps -a
[[email protected] docker]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0382dfbbd606 nginx:latest "nginx -g ‘daemon of…" 5 seconds ago Up 4 seconds 0.0.0.0:80->80/tcp nginx
c) 进入容器
docker exec -it nginx /bin/sh,并在 容器内部编辑网页文件 index.html
# cd /usr/share/nginx/ # ls html # cd html # ls 50x.html index.html # echo ‘123‘ > index.html
e)到宿主机上打开浏览器输入 IP:PORT 访问验证
一些报错:
1)[[email protected] /]# docker run -itd --name busy busybox:latest /bin/bash
e105747eb16e52da2637379d75e221f46812955c929696234abbf1321fd56da3
docker: Error stat /bin/bash: no such file or directory": unknown
这是因为环境变量不可用,换成/bin/sh或者不加环境变量
2)[[email protected] /]# docker run -itd --name busy busybox:latest /bin/sh
docker: Error response from daemon: Conflict. The container name "/busy" is already in use by container "e105747eb16e52da2637379d75e221f46812955c929696234abbf1321fd56da3". You have to remove (or rename) that container to be able to reuse that name.
这是因为容器名已经存在,需要删除已经存在的容器名
3)[[email protected] /]# docker network create --driver bridge my-net2
Error networks have overlapping IPv4
这是因为网桥冲突,删除冲突的网桥。
brctl delbr 网桥
systemctl restart docker
4)error:executable file not found in $PATH": unknown
这是因为命令的顺序错误
5)[email protected] /]# docker run -it --network=my-net3 --ip 192.168.253.13 busybox:latest /bin/sh
docker: Error response from daemon: Invalid address 192.168.253.13: It does not belong to any of this network‘s subnets.
这是因为自定义的ip不在可使用ip的范围内。
6)Error No chain/target/match by that name.
这是因为没有重启docker,或者关闭firewalld和iptables(不建议)
7)docker: Error response from daemon: driver failed programming external connectivity on endpoint vibrant_kepler (0838e9c00e2ffcec24bbd333000cc4de9bd0fa2420c1c330ddb77dfd9d1d534f): Bind for 192.168.253.9:5000 failed: port is already allocated.
这是因为宿主机的端口已经被别的服务占用。
8)宿主机映射到容器之后,使用宿主机ip:port来访问容器的httpd或者nginx服务
报错连接被拒绝
这是因为端口映射的时候加入了环境变量,去掉环境变量即可。
网络排查命令:
iptables -t nat -L
ip r
tcpdump -i docker0 -n icmp
tcpdump -i eth0 -n icmp
原文地址:https://www.cnblogs.com/zzzynx/p/11047059.html