在使用Docker容器时,咱们须要访问容器的内部网络,或须要在容器间相互访问。Docker 容器默认不会开听任何端口,所以须要将容器与宿主机进行端口映射,使容器可外部访问。而容器间互相访问,除了能够基于端口映射进行访问外,还能够经过容器连接(Link)的方式,也能够经过Docker 网络(Networking)实现。html
端口映射与外部访问容器python
1.1 -P
绑定宿主机随机端口linux
1.2 -p
指定端口、IP地址绑定web
1.3 其它docker
容器连接(Link)数据库
2.1 容器的命名express
2.2 容器的互联npm
Docker网络(Networking)安全
3.1 建立网络bash
3.2 建立容器并链接到网络
3.3 将已有容器链接到Docker网络
3.4 断开网络与网络删除
Docker 容器运行后默认不会开启任何网络端口,这样就没法经过网络访问容器。要使容器能够经过外部网络访问Docker 容器的内部网络,就须要将容器端口与宿主机端口创建映射关系。
容器与宿主机间创建端口映射关系时,能够在运行容器时使用-P
或-p
参数指定端口映射。二者区别以下:
-P
参数会随机分配一个49000~49900
之间的端口到容器内部开放的网络(经过EXPORT
指定的)端口
-p
则能够具体指定要映射的端口,而且在一个指定端口上只能绑定一个容器
-P
绑定宿主机随机端口-P
参数会随机绑定一个49000~49900
之间的端口所运行容器的导出端口。
如,运行一个容器,并使用-P
绑定宿主机端口:
$ sudo docker run -d --name experss-app -P itbilu/express-app 28003e2dcdcd38075d1ad68d4791c77edaca47dc3d468b0333669ba483cd7b3d
在这个示例中,咱们经过itbilu/express-app
镜像建立并运行了一个名为express-app
的容器。运行容器时,咱们经过-P
参数进行了端口映射。这时,能够经过docker ps
命令查看所分配的端口号:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0781edb13563 itbilu/express-app "npm start" 15 seconds ago Up 14 seconds 0.0.0.0:32771->3000/tcp experss-app
如上所示,宿主机的32771
端口被绑定到了容器的3000
端口。
-p
指定端口、IP地址绑定若是不想使用随机端口,则可使用-p
参数来指定要绑定的端口号。-p
参数除了能够指定端口号外,还能够指定宿主机的IP,这一点在使用过程当中很是有用。
-p
支持如下几种绑定格式:
// 绑定宿主机IP及端口 ip:hostPort:containerPort // 绑定宿主机IP ip::containerPort // 绑定宿主机端口 hostPort:containerPort
绑定宿主机全部的IP
使用hostPort:containerPort
格式进行宿主机及容器端口映射时,默认会将宿主机的全部IP绑定到容器。如:
$ sudo docker run -d --name experss-app -p 3000:3000 itbilu/express-app
在这个示例中,将宿主机的3000
端口映射到了容器的3000
端口。在这种状况下,会绑定本地全部接口上的全部IP地址。
映射到指定地址的指定端口
使用ip:hostPort:containerPort
格式能够将宿主机指定的IP及端口,绑定到容器端口。
如,绑定127.0.0.1
IP到容器:
$ sudo docker run -d --name experss-app -p 127.0.0.1:3000:3000 itbilu/express-app
映射指定地址及随机端口
ip::containerPort
格式会绑定宿主机的指定IP地址及随机端口到容器端口。如:
$ sudo docker run -d --name experss-app -p 127.0.0.1::3000 itbilu/express-app
使用docker ps
查看所分配的端口:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6289a4714594 itbilu/express-app "npm start" 4 seconds ago Up 4 seconds 127.0.0.1:32768->3000/tcp experss-app
在前面示例中,咱们经过docker ps
查看已建立的容器及容器所绑定的端口。除了docker ps
命令外,还可使用docker port
查看所绑定的端口及IP地址:
$ sudo docker port experss-app 3000/tcp -> 127.0.0.1:32768
容器内部可能会使用多个网络端口,使用docker port
命令时,能够指定端口参数,以查看容器指定端口的绑定状况:
$ sudo docker port experss-app 3000 127.0.0.1:32768
在建立/运行容器时,-p
参数能够被屡次使用,以绑定多个容器端口:
$ sudo docker run -d --name experss-app -p 3000:3000 -p 5000:80 itbilu/express-app
Docker进行端口绑定时,默认会绑定TCP端口。还可使用udp
标记来绑定udp
端口:
$ sudo docker run -d --name experss-app -p 3000:3000/udp itbilu/express-app
容器的链接(link)系统是除了端口映射外,另外一种跟容器中应用交互的方式。该系统会在源容器和接收容器之间建立一个隧道,接收容器能够看到源容器指定的信息。Docker的连接是一个能够将具体的容器链接到一块儿来进行通讯的抽像层。
Docker的链接系统会依据容器的名称来进行链接,所以,首先须要定义容器的名称。在不指定容器命令的状况,系统会随机分配一个名称。但相对来讲,自定义容器名称更容易记。
自定义容器名称,可使用--name
参数:
$ sudo docker run -d --name db training/postgres
命令并运行容器后,能够经过docker ps
命令来查看相关信息。也可使用docker inspect
命令来查看容器的名称:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES db2093b13127 training/postgres "su postgres -c '/..." 4 seconds ago Up 2 seconds 5432/tcp db
$ sudo docker inspect -f "{{ .Name }}" db2093b13127 /db
使用--link
参数可让容器间安全的进行互联。
如,咱们能够像下面这样建立一个名为web
的容器,并将它链接到db
容器:
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
这样就在web
和db
之间创建了互联关系。
--link
参数格式
--link
参数的格式为--link name:alias
,其中:name
表示要链接的容器的名称,而alias
表示链接后的别名。
经过--link
参灵敏,Docker 会在两个互联的容器之间建立了一个安全的隧道,且不用映射它们的端口到宿主主机上。在前面咱们启动db
容器的时,并无使用-p
和-P
参数,从而避免了暴露数据库端口到外部网络上,增长了容器的安全性。
在Docker 1.9及以后,增长了Docker Networking
及docker network
命令。容器之间的链接经过网络来建立,这被称为Docker Networking
。
经过端口映射的方式开放容器的内部网络,这种方式并不够灵活、强大,且会暴露端口到外部网络。容器连接和Dcoker Networking是更好的处理方式,Docker 1.9以前的版本推荐使用容器连接(Link)的方式,在Docker 1.9及以后则更推荐使用Dcoker Networking。相对连接来讲,Networking具备如下优势:
Dcoker Networking能够将容器链接到不一样宿主机上的容器
经过Dcoker Networking链接的容器,能够在不更新链接的状况下对容器进行中止、启动或重启。而连接则须要经过更新配置,重启对应的容器来更新容器之间的网络
使用Dcoker Networking能够不用关心容器是否已运行,也不用关心容器的运行顺序,而能够在网络内部获取容器名的解析和发现
Docker 安装会,有三个网络会被自动建立。能够经过docker network ls
命令查看:
$ docker network ls NETWORK ID NAME DRIVER SCOPE 32dfd86b7900 bridge bridge local 18814c612f64 host host local 7914b1c3168c none null local
在Docker历史上,这三个网络是Docker执行的一部分。在运行容器时,可使用--network
指定要运行容器的网络,面这三个网络均可选。
Docker Networking
容许用户建立本身的网络,容器间能够经过这个网络互相通信。Docker Networking
容许容器跨越不一样的宿主机通信,且网络配置方式更灵活。
Docker Engine 会在引擎安装时自动建立一个名为bridge
(桥接)网络,这个网络会与docker0
(Docker内部网络)相对应。
除此以外,用户还能够自行建立bridge
或overlay
类型的网络。bridge
网络适用于单台宿主机运行的单Docker引擎环境,而overlay
网络容许咱们跨多台宿主机进行通信。
要实现Docker Networking
互联,首先要使用docker network create
命令建立一个网络:
$ sudo docker network create my_network 32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9
如上,咱们建立了一个名为my_network
的网络,如今能够经过docker network inspect
查看这个新建的网络:
$ sudo docker network inspect my_network [ { "Name": "my_network", "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9", "Created": "2017-04-04T04:05:13.230681143Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": {}, "Options": {}, "Labels": {} } ]
在不添加额外参数的状况下,建立的是一个本地桥接网络。而建立overlay
网络,须要预先存在一些条件,详细官方文档:Create networks
使用docker network ls
命令也能够看到这个新建的网络:
$ docker network ls NETWORK ID NAME DRIVER SCOPE 32ddd24fd698 my_network bridge local ae4ab5ad7602 bridge bridge local 18814c612f64 host host local 7914b1c3168c none null local
建立网络后,能够在建立容器时经过--network
参数指定容器要使用的网络:
$ sudo docker run -d --name db --network=my_network training/postgres
使用docker network inspect
查看的网络状况:
$ docker network inspect my_network [ { "Name": "my_network", "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9", "Created": "2017-04-04T04:05:13.230681143Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": { "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": { "Name": "db", "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
能够看到my_network
网络的Containers
参数中,包含了网建立的容器的信息,表中容器已链接到咱们所建立的网络,而该容器的IP地址为172.18.0.2
。
接下来,建立一个交互式容器,并查看该容器内部的网络状况:
$ sudo docker run -t -i --name web --network=my_network training/webapp /bin/bash root@acb03a7adec2:/opt/webapp#
而后使用ping
测试是否能够链接到db
容器:
# ping db PING db (172.18.0.2) 56(84) bytes of data. 64 bytes from db.my_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.136 ms 64 bytes from db.my_network (172.18.0.2): icmp_seq=2 ttl=64 time=0.092 ms ...
因而可知在同一网络中的容器是能够互相访问的。
当须要将已在运行的容器添加到已有的网络时,可使用docker network connect
命令。
删除刚建立的web
容器,并使用如下命令从新建立:
$ sudo docker run -d --name web training/webapp python app.py
将这个容器链接到已建立的名为my_network
的网络:
$ sudo docker network connect my_network web
使用docker network inspect
查看的网络状况,Containers
节点内容以下:
... "Containers": { "7258828bc9ab9153f060aa38c24daa63e22478632270172f5a1485e0e9a4797b": { "Name": "web", "EndpointID": "457fbf4ecebaabbe6cce2e95d7b1f47e35450897de3e6a00cde835cd3305eee9", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" }, "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": { "Name": "db", "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } } ...
一个容器能够链接入多个网络,从而构建出很是复杂的网络模型。
还可使用docker network disconnect
命令将容器与网络断开链接:
$ sudo docker network disconnect my_network web
这样就将容器web
与网络my_network
断开的了链接。
网络不在须要后,可使用docker network rm
命令将网络删除:
$ sudo docker network rm my_network
注意:删除网络时,须要已断开所容器的链接,不然会删除失败。