您的位置:首页 > 运维架构 > Docker

Docker 网络-端口映射、容器链接、Networking

2020-01-15 09:44 288 查看

在使用Docker容器时,我们需要访问容器的内部网络,或需要在容器间相互访问。Docker 容器默认不会开放任何端口,因此需要将容器与宿主机进行端口映射,使容器可外部访问。而容器间互相访问,除了可以基于端口映射进行访问外,还可以通过容器链接(Link)的方式,也可以通过Docker 网络(Networking)实现。

  1. 端口映射与外部访问容器
  2. 容器链接(Link)
  3. Docker网络(Networking)

1. 端口映射与外部访问容器

Docker 容器运行后默认不会开启任何网络端口,这样就无法通过网络访问容器。要使容器可以通过外部网络访问Docker 容器的内部网络,就需要将容器端口与宿主机端口建立映射关系。

容器与宿主机间建立端口映射关系时,可以在运行容器时使用

-P
-p
参数指定端口映射。两者区别如下:

  • -P
    参数会随机分配一个
    49000~49900
    之间的端口到容器内部开放的网络(通过
    EXPORT
    指定的)端口
  • -p
    则可以具体指定要映射的端口,并且在一个指定端口上只能绑定一个容器

 

1.1 
-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
端口。

 

1.2 
-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

 

1.3 其它

在前面示例中,我们通过

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

 

2. 容器链接(Link)

容器的连接(link)系统是除了端口映射外,另一种跟容器中应用交互的方式。该系统会在源容器和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。Docker的链接是一个可以将具体的容器连接到一起来进行通信的抽像层。

2.1 容器的命名

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

 

2.2 容器的互联

使用

--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
参数,从而避免了暴露数据库端口到外部网络上,增加了容器的安全性。

 

3. Docker网络(Networking)

在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
指定要运行容器的网络,面这三个网络都可选。

3.1 创建网络

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

 

3.2 创建容器并连接到网络

创建网络后,可以在创建容器时通过

--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
...

由此可见在同一网络中的容器是可以互相访问的。

 

3.3 将已有容器连接到Docker网络

当需要将已在运行的容器添加到已有的网络时,可以使用

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": ""
}
}
...

一个容器可以连接入多个网络,从而构建出非常复杂的网络模型。

 

3.4 断开网络与网络删除

还可以使用

docker network disconnect
命令将容器与网络断开连接:

$ sudo docker network disconnect my_network web

这样就将容器

web
与网络
my_network
断开的了连接。

网络不在需要后,可以使用

docker network rm
命令将网络删除:

$ sudo docker network rm my_network

注意:删除网络时,需要已断开所容器的连接,否则会删除失败。

下一篇:MySQL 官方Docker镜像的使用

上一篇:使用 Docker 部暑Node.js应用

 

转载于:https://my.oschina.net/airship/blog/3080308

  • 点赞
  • 收藏
  • 分享
  • 文章举报
chijue3990 发布了0 篇原创文章 · 获赞 0 · 访问量 4453 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: