首页 > 其他 > 详细

docker进阶——数据管理与网络

时间:2019-06-18 20:03:49      阅读:179      评论:0      收藏:0      [点我收藏+]

 

 

 

用户在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或者 需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这必然会涉及 到容器的数据管理

1Data Volume (数据卷)

2Data Volume Dontainers --- 数据卷容器

 

 

Data Volume ---数据卷

 

Data Volume 本质上是 Docker Host 文件系统中的目录或文件,使用类似 与 Linux 下对目录或者文件进行 mount 操作。数据卷可以在容器之间共享 和重用,对数据卷的更改会立马生效,对数据卷的更新不会影响镜像,卷会一 直存在,直到没有容器使用

 

Data Volume 有以下特点   

aData Volume 是目录或文件,而非没有格式化的磁盘(块设备)。   

b容器可以读写 volume 中的数据。   

cvolume 数据可以被永久的保存,即使使用它的容器已经销毁。

 

Data Volume的使用:

通过-v 参数格式为 <host path>:<container path>

a)运行一个容器,并创建一个数据卷挂载到容器的目录上 docker run -dti -v /web nginx /bin/bash 利用 nginx的镜像运行一个容器,并在容器内创建一个数据卷挂载到容器 的 /web 目录上 

[root@localhost ~]# 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方便记忆 

[root@localhost ~]# 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 目录。三个容器任何一个目录下的写入,都可以时时同步到另外两个

 

[root@localhost ~]# 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
[root@localhost ~]# docker exec -it  aff1e64343bf /bin/bash
[root@aff1e64343bf dbdata]# echo "0330" >jam
[root@aff1e64343bf dbdata]# cat jam 
0330

在db1中查看是否存在jam文件
[root@localhost ~]# docker exec -it 893450737ade /bin/bash
[root@893450737ade /]# cd dbdata/
[root@893450737ade dbdata]# ls
jam
[root@893450737ade dbdata]# cat jam
0330

在dbser中查看jam文件是否存在
[root@localhost ~]# docker exec -it 82b264b29e56 /bin/bash
[root@82b264b29e56 /]# ls
  dbdata  
[root@82b264b29e56 /]# cd dbdata/
[root@82b264b29e56 dbdata]# ls
jam
[root@82b264b29e56 dbdata]# cat jam
0330

 

 

 

 

一、docker网络介绍

 

大量的互联网应用服务需要多个服务组件,这往往需要多个容器之间通过网络 通信进行相互配合

docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络 docker 目前提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务,在启动容器的时候,如果不指定参数,在容器外部是没有办法通过网络来访问容器内部的网络应用和服务的

docker 安装时会自动在host上创建三个网络,我们查看一下docker网络:

docker network ls

[root@localhost ~]# 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 上没有任何其他网络设备,我们创建一个容器看看有什么变化

[root@localhost docker]# brctl show
bridge name    bridge id        STP enabled    interfaces
docker0        8000.0242ec43479a    no        vethb2a3b02  #以密钥对的形式挂到docker0

 

一个新的网络接口 vethb2a3b02 被挂到了 docker0 上,vethb2a3b02 就是 新创建容器的虚拟网卡。

 

 

进入刚才运行的容器查看网络,容器有一个网卡 eth0@if9

[root@localhost 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: eth0@if9: <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

 

实际上 eth0@if9 和 vethb2a3b02是一对 veth pair

veth pair 是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线 连接起来的一对网卡,网卡的一头(eth0@if9)在容器中,另一头 (vethb2a3b02)挂在网桥 docker0 上,其效果就是将 eth0@if9 也挂在了 docker0

 

 

可以看到,eth0@if9 已经配置了 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。

 

[root@localhost ~]# docker network create --driver bridge net2 
2edd5371dd2fbcb32c9c2b2a9420cb806e406edc011379c7c7c70f53d6c74585
[root@localhost ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
460b8a01b798        bridge              bridge              local
d4ae07a1372e        host                host                local
2edd5371dd2f        net2                bridge              local
63bead0d7ffc        none                null                local
[root@localhost ~]# docker network inspect net2
。。。
Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1"

 

删除网桥:brctl delbr 网桥名

 

4)利用bridge驱动创建名为my-net3网桥(user-defined网段及网关)

[root@localhost ~]# 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段就行

 

[root@localhost ~]# docker network create --driver bridge --subnet 192.18.2.0/24 --gateway 192.18.2.1 net3
3f028deb3aa0b37ee69e3a04a0edb14c00b1933a415c2d0961a9eec7b4b2ecb1

 

重新查看网络配置信息:

[root@localhost ~]# 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(环境名)

 

[root@localhost ~]# docker run  -itd --network=net3 busybox:latest /bin/sh
632e2d8245ade9e0a8ee9cf13d7105f19a2d28728e3d38b65423eb34ef38ac4c
[root@localhost ~]# 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: eth0@if19: <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

[root@localhost ~]# docker run  -itd --network=net3 --ip 192.18.2.4 busybox:latest /bin/sh

当然,这个指定的ip也要在net3的子网范围内。

 

 

7)让已启动不同vlanningx容器,可以连接到my-net2(其实在nigx中新建了my-net2的网卡)

docker run -itd --network=net3 busybox:latest  /bin/sh

docker network connect net2   容器名(id)

[root@localhost ~]# docker run  -itd --network=net3 busybox:latest /bin/bash
e42da501655faa6e2067a6d9ee6c49016ec49bb0dc750b78a82f2540751840c5
[root@localhost docker]# docker network connect net2 0d3e78d4298c
[root@localhost 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: eth0@if21: <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: eth1@if25: <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 的。

 

root@localhost docker]# docker run -itd --network=net3 --name=b1 busybox
203fc1c4fb19dc1212da8f97dc8654b5b928f9ab1406bed4c39a31f76b686d4c
[root@localhost docker]# docker run -itd --network=net3 --name=b2 busybox
5dfabb01d5d718429e382acb4115a1d8c4c7e2e89c302b899bcf5923be1df527
[root@localhost 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 容器 

 

[root@localhost ~]# docker run -itd --name db busybox

 

b). 创一个 web 容器,并使其连接到 db   

 

[root@localhost ~]# docker run -itd --name web --link db:dblink busybox /bin/sh

-link db:dblink 实际是连接对端的名字和这个链接的名字,也就是和 db 容器 建立一个叫做 dblink 的链接  

 

c).查看链接的情况 

docker ps -a

[root@localhost ~]# 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 命令来测试网络链接的情况

[root@localhost ~]# 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命令测试

[root@localhost 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 容器名

 

拓展:用脚本删除所有容器

 

[root@localhost 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)多次使用可以实现多个接口的映射

 

[root@localhost docker]# docker run -itd -p 5000:22 -p 5001:23 nginx /bin/bash

 

 

查看容器信息,发现新容器的的22,23端口都映射到了宿主机的5000和5001端口。

[root@localhost 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

[root@localhost docker]#  docker run -dti -p 192.168.253.9:5000:80 nginx /bin/bash
[root@localhost 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

[root@localhost 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 访问验证

http://192.168.253.9:80

 技术分享图片

 

一些报错:

1)[root@localhost /]# docker run -itd --name busy busybox:latest /bin/bash
e105747eb16e52da2637379d75e221f46812955c929696234abbf1321fd56da3
docker: Error stat /bin/bash: no such file or directory": unknown

这是因为环境变量不可用,换成/bin/sh或者不加环境变量

 

2)[root@localhost /]# 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)[root@localhost /]# 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)root@localhost /]# 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

 
 

docker进阶——数据管理与网络

原文:https://www.cnblogs.com/zzzynx/p/11047059.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!