博文大纲:

  • 一、docker的数据管理
    1、数据卷
    2、数据卷容器
  • 二、docker网络通信
    1、端口映射
    2、容器互联

一、docker的数据管理

在docker中,为了方便查看容器内产生的数据或者将多个容器之间的数据实现共享,会涉及到容器的数据管理操作,管理docker容器中的数据主要有两种方式:数据卷和数据卷容器。

1、数据卷

数据卷是一个供容器使用的特殊目录,位于容器中,可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立即可见,并且更新数据不会影响镜像,从而实现数据在宿主机与容器之间的迁移,数据卷的使用类似于Linux下对目录进行的mount挂载操作(注意:是将宿主机本地的目录挂载到容器中,举例:若宿主机本地/data目录挂载的是/dev/sdb1,那么要将/data做数据卷映射时,容器中指定的目录使用的文件系统也是/dev/sdb1,我不知道这样解释,你们能不能理解它的工作原理)。

挂载宿主机目录作为数据卷举例:

使用-v选项可以创建数据卷(只是运行容器时,创建一个目录),创建数据卷的同时将宿主机的目录挂载到数据卷上使用,以实现宿主机与容器之间的数据迁移。

需要注意的是,宿主机本地目录的路径必须是使用绝对路径,如果路径不存在,Docker会自动创建相应的路径。

[root@localhost ~]# docker run -d -p 5000:5000 -v /data/registry/:/tmp/registry docker.io/registry
#这是运行了一个私有仓库的容器,其中-p是端口映射的选项,这里不做解释。
# -v才是目录映射,将本地/data/registry/目录映射到容器中的/tmp/registry目录。
#然后容器中的/tmp/registry目录下的内容就和宿主机的/data/registry/内容一样了。
[root@localhost ~]# df -hT /data/registry/           #先查看本地/data/registry/ 挂载的文件系统
文件系统         类型            容量  已用  可用 已用% 挂载点
node4:dis-stripe fuse.glusterfs   80G  130M   80G    1% /data/registry
[root@localhost ~]# docker exec -it a6bf726c612b /bin/sh #进入私有仓库的容器中,该容器没有/bin/bash,所以使用的是/bin/sh。
/ # df -hT /tmp/registry/    #查看发现,该目录挂载的和宿主机挂载的文件系统是同一个,说明没问题。
Filesystem           Type            Size      Used Available Use% Mounted on
node4:dis-stripe     fuse.glusterfs
                                    80.0G    129.4M     79.8G   0% /tmp/registry

2、数据卷容器

如果需要在容器之间共享一些数据,最简单的方法就是使用数据卷容器。数据卷容器就是一个普通的容器,专门提供数据卷给其他容器挂载使用。使用方法如下:首先,需要创建一个容器作为数据卷容器,之后在其他容器创建时用--volumes-from挂载数据卷容器中的数据卷使用。

容器卷创建及使用举例:

[root@localhost ~]# docker run -itd --name datasrv -v /data1 -v /data2  docker.io/sameersbn/bind /bin/bash
#创建运行一个容器,容器名为datasrv,并创建两个数据卷:data1和data2。
d9e578db8355da35637d2cf9b0a3406a647fe8e70b2df6172ab41818474aab08
[root@localhost ~]# docker exec -it datasrv /bin/bash     #进入创建的容器
root@d9e578db8355:/# ls | grep data             #查看是否有对应的数据卷
data1
data2
[root@localhost ~]# docker run -itd --volumes-from datasrv --name ftpsrv docker.io/fauria/vsftpd /bin/bash
#运行一个名为ftpsrv的容器,使用--volumes-from来将datasrv容器中的数据卷挂载到这个ftpsvr新容器上。
eb84fa6e85a51779b652e0058844987c5974cf2a66d1772bdc05bde30f8a254f
[root@localhost ~]# docker exec -it ftpsrv /bin/bash         #进入新创建的容器
[root@eb84fa6e85a5 /]# ls | grep data          #查看新的容器是否可以看到datasrv提供的数据卷
data1
data2
[root@eb84fa6e85a5 /]# echo " data volumes test" > /data1/test.txt       #在ftpsrv容器中向data1目录写入文件进行测试
[root@eb84fa6e85a5 /]# exit          #退出该容器
exit
[root@localhost ~]# docker exec -it datasrv /bin/bash     #进入提供数据卷的datasrv容器
root@d9e578db8355:/# cat /data1/test.txt            #可以看到刚在ftpsrv容器创建的文件,OK。
 data volumes test

注意,生产环境中最注重的就是存储的可靠性,以及存储的可动态扩展性,一定要在做数据卷时考虑到这一点,在这方面比较出色的还要数GFS文件系统了,我上面只是做了简单的配置,若在生产环境中,一定要好好考虑,就比如上面做的镜像卷容器,就可以在宿主机本地挂载GFS文件系统,然后创建镜像卷容器时,将挂载GFS的目录映射到容器中的镜像卷,这样才是一个合格的镜像卷容器。

二、docker网络通信

1、端口映射

docker提供了映射容器端口到宿主机和容器互联机制来为容器提供网络服务。

在启动容器的时候,如果不指定对应的端口,在容器外是无法通过网络来访问容器内的服务的。docker提供端口映射机制来将容器内的服务提供给外部网络访问,实质上就是将宿主机的端口映射到容器中,使外部网络访问宿主机的端口可访问容器内的服务。

实现端口映射,需要在运行docker run命令时使用-P(大写)选项实现随机映射,Docker一般会随机映射到一个端口访问在49000~49900的端口到容器内部开放的网络端口,但不是绝对的,也有例外情况不会映射到这个范围;也可以使用在运行docker run命令时使用-p(小写)选项实现指定要映射的端口(常用此种方法)。

端口映射举例:

[root@localhost ~]# docker run -d -P docker.io/sameersbn/bind      #随机映射端口
9b4b7c464900df3b766cbc9227b21a3cad7d2816452c180b08eac4f473f88835
[root@localhost ~]# docker run -itd -p 68:67 docker.io/networkboot/dhcpd /bin/bash
#将容器中的67端口映射到宿主机的68端口
6f9f8125bcb22335dcdb768bbf378634752b5766504e0138333a6ef5c57b7047
[root@localhost ~]# docker ps -a     #查看发现没问题咯
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                                                                    NAMES
6f9f8125bcb2        docker.io/networkboot/dhcpd   "/entrypoint.sh /b..."   2 seconds ago       Up 1 second         0.0.0.0:68->67/tcp                                                       keen_brattain
9b4b7c464900        docker.io/sameersbn/bind      "/sbin/entrypoint...."   4 minutes ago       Up 4 minutes        0.0.0.0:32768->53/udp, 0.0.0.0:32769->53/tcp, 0.0.0.0:32768->10000/tcp   coc_gates
#此时,访问宿主机的68端口就相当于访问第一个容器的67端口;访问宿主机的32768端口,就相当于访问容器的53端口。

2、容器互联

容器互联是通过容器的名称在容器之间建立一条专门的网络通信隧道从而实现的互联。简单说,就是会在源容器和接收容器之间建立一条隧道,接收容器可以看到源容器指定的信息。

在运行docker run命令时,使用--link选项实现容器之间的互联通信,格式如下:

--link name: alias    #其中name是要连接的容器名称,alias是这个连接的别名。

容器互联是通过容器的名称来执行的,--name选项可以给容器创建一个友好的名称,这个名称是唯一的,如果已经命名了一个相同名称的容器,当要再次使用这个名称的时候,需要先使用docker rm命令来删除之前创建的同名容器。

容器互联举例:

[root@localhost ~]# docker run -tid -P --name web1  docker.io/httpd /bin/bash    #运行容器web1
c88f7340f0c12b9f5228ec38793e24a6900084e58ea4690e8a847da2cdfe0b
[[root@localhost ~]# docker run -tid -P --name web2 --link web1:web1 docker.io/httpd /bin/bash
#运行容器web2,并关联web1容器
c7debd7809257c6375412d54fe45893241d2973b7af1da75ba9f7eebcfd4d652
[root@localhost ~]# docker exec -it web2 /bin/bash     #进入web2容器
root@c7debd780925:/usr/local/apache2# cd
root@c7debd780925:~# ping web1        #对web1进行ping测试
bash: ping: command not found        #sorry,提示没有ping命令,下载一个咯
root@c7debd780925:~#apt-get update    #更新一下
root@c7debd780925:~#apt install iputils-ping     #安装ping命令
root@c7debd780925:~#apt install net-tools      #这个是安装ifconfig命令,可以不安装,我这里只是做个笔记
root@c7debd780925:~# ping web1     #再对web1进行ping测试
PING web1 (172.17.0.2) 56(84) bytes of data.
64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.114 ms
              ..............#省略部分内容
#ping通了,所以可以说这两个容器肯定是互联的咯
#若此时又创建了web3这个新容器,要同时和web1、web2进行互联,命令如下:
[root@localhost ~]# docker run -dit -P --name web3 --link web1:web1 --link web2:web2 docker.io/httpd /bin/bash
#运行容器时,关联web1和web2。
#以下是进入web3
[root@localhost ~]# docker exec -it web3 /bin/bash
root@433d5be6232c:/usr/local/apache2# cd
#以下是安装ping命令
root@433d5be6232c:~# apt-get update
root@433d5be6232c:~# apt install iputils-ping
#以下是分别对web1,web2进行ping测试
root@433d5be6232c:~# ping web1
PING web1 (172.17.0.2) 56(84) bytes of data.
64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.112 ms
              ..............#省略部分内容
root@433d5be6232c:~# ping web2
PING web2 (172.17.0.3) 56(84) bytes of data.
64 bytes from web2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.165 ms
64 bytes from web2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.115 ms
              ..............#省略部分内容
#OK,没问题