应用在容器中运行,总会用到或者产生一些数据,那么这些数据是如何保存的呢?外部又是如何使用这些数据的呢?
容器网络基础:容器通过对外暴露端口向外提供服务
数据卷的概念和使用:通过数据卷来存储和共享数据
容器连接:通过互联让一个容器安全的使用另一个容器已有的服务
当Docker启动后,会在宿主主机上创建一个名为docker0的虚拟网络接口;
[[email protected] ~]# ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:9c:ff:c5 brd ff:ff:ff:ff:ff:ff
inet 192.168.212.131/24 brd 192.168.212.255 scope global dynamic eno16777736
valid_lft 1281sec preferred_lft 1281sec
inet6 fe80::20c:29ff:fe9c:ffc5/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:09:c2:33:1a brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:9ff:fec2:331a/64 scope link
valid_lft forever preferred_lft forever
4.1.1 暴露网络端口
暴露端口有动态分配和静态指定两种方式:-P:动态分配 -p:静态分配
①:
[[email protected] ~]# docker run -d -P training/webapp python app.py //-P(大写)会在宿主主机上随机为应用分配一个49000~49900内的未被使用的端口
fd36eab96d7b130085253efa851314edd645f5faaa0ba4a496459202138f43b2
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd36eab96d7b training/webapp "python app.py" 6 seconds ago Up 4 seconds 0.0.0.0:32768->5000/tcp silly_newton
7461f21c6c44 ubuntu "/bin/bash" 46 minutes ago Up 45 minutes ubuntu_inet2
10ff3e568491 ubuntu "/bin/bash" 47 minutes ago Up 45 minutes ubuntu_inet1
[[email protected] ~]# curl localhost:32768 || curl your_ip:32768
Hello world![[email protected] ~]# //发现可以正常访问了
查看日志:
[[email protected] ~]# docker logs -f silly_newton
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
172.17.42.1 - - [28/Nov/2015 01:27:56] "GET / HTTP/1.1" 200 -
172.17.42.1 - - [28/Nov/2015 01:29:35] "GET / HTTP/1.1" 200 -
②:
-p参数可以指定宿主主机上的短剧偶映射到容器内容指定的开放端口,格式有如下三种:
hostport:containerport | ip:hostport:containerport | ip::containerport
<1>、想把宿主主机中所有网络接口中的80端口映射到容器的5000端口
[[email protected] ~]# docker run -d -p 80:5000 training/webapp python app.py
38699b09361464cbc7f3cfe99869c87a1183f6d8b4bd147738bb31b0e50c8b56
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
38699b093614 training/webapp "python app.py" 3 seconds ago Up 2 seconds 0.0.0.0:80->5000/tcp tender_newton
db02f8633423 training/webapp "python app.py" About a minute ago Up About a minute 0.0.0.0:5000->5000/tcp mad_kirch
fd36eab96d7b training/webapp "python app.py" 17 minutes ago Up 17 minutes 0.0.0.0:32768->5000/tcp silly_newton
7461f21c6c44 ubuntu "/bin/bash" About an hour ago Up About an hour ubuntu_inet2
10ff3e568491 ubuntu "/bin/bash" About an hour ago Up About an hour ubuntu_inet1
[[email protected] ~]# curl localhost || curl your_ip
Hello world![[email protected] ~]#
可以使用如下命令查看容器的5000端口映射到宿主主机的80端口
[[email protected] ~]# docker port tender_newton 5000
0.0.0.0:80
<2>、指定IP地址的指定端口和容器的指定端口映射
[[email protected] ~]# docker run -d -p 127.0.0.1:6000:5000 training/webapp python app.py
0d91baa150baf78acfa83606fd16d9cd5d2e2404e5548522c933ffc9bc1814f3
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0d91baa150ba training/webapp "python app.py" 6 seconds ago Up 5 seconds 127.0.0.1:6000->5000/tcp elated_fermi
38699b093614 training/webapp "python app.py" 12 minutes ago Exited (137) 48 seconds ago tender_newton
db02f8633423 training/webapp "python app.py" 14 minutes ago Exited (137) 48 seconds ago mad_kirch
fd36eab96d7b training/webapp "python app.py" 30 minutes ago Exited (137) 48 seconds ago silly_newton
7461f21c6c44 ubuntu "/bin/bash" About an hour ago Exited (0) 58 seconds ago ubuntu_inet2
10ff3e568491 ubuntu "/bin/bash" About an hour ago Exited (0) 58 seconds ago ubuntu_inet1
[[email protected] ~]# curl localhost:6000
Hello world![[email protected] ~]#
<3>、指定IP的随机端口映射到容器的指定端口
[[email protected] ~]# docker run -d -p 127.0.0.1::5000 training/webapp python app.py
51abc14e67c5b623b2d8a948781f1a1348e587c52c1f251c919fd5b450c7841b
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51abc14e67c5 training/webapp "python app.py" 9 seconds ago Up 8 seconds 127.0.0.1:32768->5000/tcp distracted_yalow
0d91baa150ba training/webapp "python app.py" About a minute ago Up About a minute 127.0.0.1:6000->5000/tcp elated_fermi
38699b093614 training/webapp "python app.py" 14 minutes ago Exited (137) 2 minutes ago tender_newton
db02f8633423 training/webapp "python app.py" 16 minutes ago Exited (137) 2 minutes ago mad_kirch
fd36eab96d7b training/webapp "python app.py" 31 minutes ago Exited (137) 2 minutes ago silly_newton
7461f21c6c44 ubuntu "/bin/bash" About an hour ago Exited (0) 2 minutes ago ubuntu_inet2
10ff3e568491 ubuntu "/bin/bash" About an hour ago Exited (0) 2 minutes ago ubuntu_inet1
[[email protected] ~]# curl localhost:32768
Hello world![[email protected] ~]#
<4>、当容器暴露多个端口的时候,我们可以对每个端口一一进行映射:
#docker run -d -p 5000:5000 -p 4000:80 training/webapp python app.py
4.1.2查看网络配置
[[email protected] ~]# docker inspect distracted_yalow
格式化过滤查看容器中网络相关的配置:
[[email protected] ~]# docker inspect --format ‘{{.NetworkSettings}}‘ distracted_yalow
{ 2cd2e0552193e97149b504c29ea560908aac28528d0d4a43627c31da97cfe276 172.17.42.1 0 false 172.17.0.2 16 0 02:42:ac:11:00:02 624a6e77108aac7dbf07198393a10f7d02438fddd8984677eecdd130f0738169 map[] map[5000/tcp:[{127.0.0.1 32768}]] /var/run/docker/netns/51abc14e67c5 [] []}
4.2数据卷
数据卷是一个可供一个或多个容器使用的特殊目录;
4.2.1创建数据卷
1、在Dockerfile中,使用VOLUME指令,如:
VOLUME /var/lib/mysql
2、在命令行中使用docker run时,需要-v参数来创建数据卷并将其挂载到容器中:
[[email protected] ~]# docker run -d -P -v /webapp training/webapp python app.py
"Mounts": [
{
"Name": "7a996594e2abaa10bb1dd6d54232ed5d822fdf73a16176c6ba0f31892e8290c1",
"Source": "/var/lib/docker/volumes/7a996594e2abaa10bb1dd6d54232ed5d822fdf73a16176c6ba0f31892e8
"Destination": "/webapp",
"Driver": "local",
"Mode": "",
"RW": true
}
]
4.2.2挂载主机目录作为数据卷
[[email protected] ~]# docker run -d -P --name webapp -v `pwd`:/webapp training/webapp python app.py
"Mounts": [
{
"Source": "/root",
"Destination": "/webapp",
"Mode": "",
"RW": true
}
]
通过挂载本地目录到容器中的数据卷,容器对目录中的改变实时映射到了宿主主机上的/root目录:
[[email protected] ~]# docker exec -it webapp /bin/bash
[email protected]:/opt/webapp# ls /webapp/
Dockerfile anaconda-ks.cfg local.txt
[email protected]:/opt/webapp# touch /webapp/from_docker.txt
[email protected]:/opt/webapp# ls /webapp/
Dockerfile anaconda-ks.cfg from_docker.txt local.txt
[email protected]:/opt/webapp# exit
exit
[[email protected] ~]# ls
anaconda-ks.cfg Dockerfile from_docker.txt local.txt
[[email protected] ~]# touch from_local.txt
[[email protected] ~]# docker exec -it webapp /bin/bash
[email protected]:/opt/webapp# ls /webapp/
Dockerfile anaconda-ks.cfg from_docker.txt from_local.txt local.txt
[email protected]:/opt/webapp#
[注意]:如果容器内部已经存在/webapp目录,那么在挂载宿主目录之后,它的内容将会被覆盖;
如果想以只读的方式进行挂载,那么:
[[email protected] ~]# docker run -d -P --name webapp -v `pwd`:/webapp:ro training/webapp python app.py
4.2.3挂载主机文件作为数据卷
[[email protected]st ~]#echo "hello,this is from local;" > test.txt
[[email protected] ~]# docker run --rm -it -v ~/test.txt:/docker_test.txt ubuntu /bin/bash
[email protected]:/# ls /
bin boot dev docker_test.txt etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[email protected]:/# cat docker_test.txt
hello,this is from local;
[email protected]:/# echo "hello,this is from docker container;" >> docker_test.txt
[email protected]:/# cat docker_test.txt
hello,this is from local;
hello,this is from docker container;
[email protected]:/# exit
exit
[[email protected] ~]# cat test.txt
hello,this is from local;
hello,this is from docker container;
4.2.4数据卷容器
数据卷容器是指一个专门用于挂载数据卷的容器,一共其他容器的引用和使用。
有了确定的容器名之后,对他有依赖关系的其他容器就可以使用--volumes-from引用它的数据卷;
首先建立一个数据卷容器,名为DBdata,并为该容器新建数据卷/dbdata:
[[email protected] ~]# docker run -d -v /dbdata --name DBdata training/postgres
接着创建一个容器db1,他引用DBdata的数据卷:
[[email protected] ~]# docker run -d --volumes-from DBdata --name db1 training/postgres
验证db1引用的是DBdata的数据卷,可以使用:
docker inspect DBdata
docker inspect db1
由此可以确定两者的数据卷是一样的。
[注意]:
数据卷一旦声明,它的生命周期和声明它的那个容器就无关了,当声明他的容器停止了,数据卷也依然存在,除非所有引用它的容器都被删除了并且显示地删除了该数据卷;
一个容器引用一个数据卷容器时,并不要求数据卷容器是运行的;
(2)删除数据卷:
再创建一个数据卷容器,它可以引用DBdata或者db1,引用db1则成为级联;
[[email protected] ~]# docker run -d --name db2 --volumes-from=db1 training/postgres
[注意]:
无论是声明数据卷的容器还是后续引用该数据卷的容器,容器的停止和删除都不会导致数据卷本身删除。
如果需要删除数据卷,那么需要删除所哟与依赖它的容器,并且在删除最后一个容器时加入-v标志;
[[email protected] ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a190a669aaa training/postgres "su postgres -c ‘/usr" 3 minutes ago Up 3 minutes 5432/tcp db2
9fccb117882c training/postgres "su postgres -c ‘/usr" 12 minutes ago Up 12 minutes 5432/tcp db1
455a97bce1df training/postgres "su postgres -c ‘/usr" 13 minutes ago Up 13 minutes 5432/tcp DBdata
[[email protected] ~]# docker stop `docker ps -q`
7a190a669aaa
9fccb117882c
455a97bce1df
[[email protected] ~]# docker rm DBdata
DBdata
[[email protected] ~]# docker start db2
db2
[[email protected] ~]# docker stop db2
db2
[[email protected] ~]# docker rm db1
db1
[[email protected] ~]# docker rm -v db2
db2
[[email protected] ~]# ls /var/lib/docker/
containers/ graph/ repositories-devicemapper trust/
devicemapper/ linkgraph.db tmp/ volumes/
4.2.5数据卷的备份与恢复
1、备份
[[email protected] ~]# docker run -d -v /dbdata --name DBdata training/postgres
c2c1190fd59262fa4642341cde80a78c2a078daa8b4403c1e16ad2effee596b0
[[email protected] ~]# docker exec -it DBdata /bin/bash
[email protected]:/# ls
bin boot dbdata dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[email protected]:/# echo "this is /dbdata volume file" > /dbdata/volume.txt
[email protected]:/# ls /dbdata/volume.txt
/dbdata/volume.txt
[email protected]:/# exit
exit
[[email protected] ~]# docker run --volumes-from DBdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/‘ from member names
/dbdata/
/dbdata/volume.txt
这里通过ubuntu镜像新建立一个容器,他引用DBdata容器的数据卷,并创建一个数据卷映射,将本地文件系统的当前工作目录映射到容器的/backup目录;
通过tar命令将/dbdata目录打包到/backup数据卷中,而该数据卷又因映射到本地,所以DBdata容器的数据卷内的数据就保存到了本地的当前目录,文件名为backup.tar;
[[email protected] ~]# ls
anaconda-ks.cfg backup.tar(就是这个~~) Dockerfile from_docker.txt from_local.txt local.txt test test.txt
[[email protected] ~]# tar tvf backup.tar //显示这个打包目录中的东西
drwxr-xr-x root/root 0 2015-12-01 21:34 dbdata/
-rw-r--r-- root/root 28 2015-12-01 21:34 dbdata/volume.txt
2、恢复数据
[[email protected] ~]# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
[[email protected] ~]# docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
dbdata/
dbdata/volume.txt
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5839791795ed busybox "tar xvf /backup/back" 6 seconds ago Exited (0) 4 seconds ago naughty_hypatia
5b2f124d9a2b ubuntu "/bin/bash" 50 seconds ago Exited (0) 47 seconds ago dbdata2
[[email protected] ~]# docker start naughty_hypatia
naughty_hypatia
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5839791795ed busybox "tar xvf /backup/back" 45 seconds ago Exited (0) 2 seconds ago naughty_hypatia
5b2f124d9a2b ubuntu "/bin/bash" About a minute ago Exited (0) About a minute ago dbdata2
[[email protected] ~]# docker start dbdata2
dbdata2
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5839791795ed busybox "tar xvf /backup/back" 58 seconds ago Exited (0) 15 seconds ago naughty_hypatia
5b2f124d9a2b ubuntu "/bin/bash" About a minute ago Exited (0) 2 seconds ago dbdata2
#如上,有一点我不明白,为什么无法启动容器;
4.3、容器连接
连接的格式为--link name:alias,其中name为源容器的名称,alias是这个连接的别名。
[[email protected] ~]# docker run -d --name dbdata training/postgres
928b24b76606032bb14c3aa7d5b91211514324da94affcbb56c88d1854544cc2
[[email protected] ~]# docker run -d -P --name web --link dbdata:db training/webapp python app.py
0aad19be1064101d529731d04b07741b05af2f98c677f2fcbd902df451f71657
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0aad19be1064 training/webapp "python app.py" 8 seconds ago Up 6 seconds 0.0.0.0:32768->5000/tcp web
928b24b76606 training/postgres "su postgres -c ‘/usr" 34 seconds ago Up 32 seconds 5432/tcp dbdata
可以查看相关的字段:
[[email protected] ~]# docker inspect web
"Links": [
"/dbdata:/web/db"
]
通过这种方式,dbdata容器为web容器提供了服务,但并没有像-P/-p那样,让容器对外暴露端口,这使得源容器dbdata更安全;
既然web容器和dbdata容器之间已经建立了连接,那么web是如何使用dbdata的服务的呢?
Docker给目标容器提供了两种方式来暴露连接提供的服务:
(1)环境变量
(2)/etc/hosts文件
(1)、一般情况下,可以使用env命令来查看一个容器的环境变量:
[[email protected] ~]# docker run --rm --name web2 --link dbdata:webdb training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=7ade2c8c5d8d
WEBDB_PORT=tcp://172.17.0.1:5432
WEBDB_PORT_5432_TCP=tcp://172.17.0.1:5432
WEBDB_PORT_5432_TCP_ADDR=172.17.0.1
WEBDB_PORT_5432_TCP_PORT=5432
WEBDB_PORT_5432_TCP_PROTO=tcp
WEBDB_NAME=/web2/webdb
WEBDB_ENV_PG_VERSION=9.3
HOME=/root
(2)查看hosts文件:
[[email protected] ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0aad19be1064 training/webapp "python app.py" 29 minutes ago Up 29 minutes 0.0.0.0:32768->5000/tcp web
928b24b76606 training/postgres "su postgres -c ‘/usr" 29 minutes ago Up 29 minutes 5432/tcp dbdata
[[email protected] ~]# docker exec -it web /bin/bash
[email protected]:/opt/webapp# cat /etc/hosts
172.17.0.2 0aad19be1064
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.1 db 928b24b76606 dbdata
172.17.0.1 dbdata.bridge
172.17.0.2 web
172.17.0.2 web.bridge
172.17.0.1 dbdata
[email protected]:/opt/webapp#
[扩展]:如果docker停止了,当再次启动的时候,以前建立的容器连接会不会再次保持?
docker容器中的IP地址是动态分配的,那么每次重启动docker容器将会导致ip地址发生改变,而容器连接会不断更新环境变量以及/etc/hosts文件;