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

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

 

 

在使用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.1IP到容器:

$ 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

 

容器的连接(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

 

使用--link参数可以让容器间安全的进行互联。

如,我们可以像下面这样创建一个名为web的容器,并将它连接到db容器:

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

这样就在webdb之间建立了互联关系。

--link参数格式

--link参数的格式为--link name:alias,其中:name表示要连接的容器的名称,而alias表示连接后的别名。

通过--link参灵敏,Docker 会在两个互联的容器之间创建了一个安全的隧道,且不用映射它们的端口到宿主主机上。在前面我们启动db容器的时,并没有使用-p-P参数,从而避免了暴露数据库端口到外部网络上,增加了容器的安全性。

 

3. Docker网络(Networking)

在Docker 1.9及之后,增加了Docker Networkingdocker 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内部网络)相对应。

除此之外,用户还可以自行创建bridgeoverlay类型的网络。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

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

转自:https://itbilu.com/linux/docker/Ey5dT-i2G.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: docker-compose 端口映射是指将容器内部的端口映射到宿主机上的端口,实现容器与宿主机之间的通信。在docker-compose.yml文件中,可以通过配置ports关键字实现端口映射。 具体使用方法如下: 1. 在docker-compose.yml文件中的对应服务的配置下方添加ports关键字。 2. 在ports后紧跟着宿主机端口:容器内部端口的形式,例如:"3000:80",表示将容器内部的80端口映射到宿主机上的3000端口。 3. 可以配置多个端口映射,使用空格分隔开,例如:"3000:80 8080:8080",表示将容器内部的80端口映射到宿主机上的3000端口,并将容器内部的8080端口映射到宿主机上的8080端口。 4. 使用端口映射后,可以通过访问宿主机的对应端口来与容器进行通信,例如,在上述例子中,可以通过访问localhost:3000来访问容器中的应用程序。 需要注意的是,端口映射只是实现了容器与宿主机之间的通信,但并没有修改容器内部的网络配置。因此,容器内部的应用程序仍然需要监听容器内部的端口。 总之,docker-compose的端口映射为我们提供了一种简便的方式来实现容器与宿主机之间的网络通信,方便我们进行开发和测试工作。 ### 回答2: Docker-compose端口映射是一种在Docker容器和宿主机之间建立端口映射的方法。通过端口映射,可以将容器内部的服务发布到宿主机的指定端口上,从而可以通过宿主机的IP地址和映射的端口访问容器内的服务。 在docker-compose.yml文件中,可以使用"ports"关键字来定义端口映射端口映射的格式为"宿主机端口:容器端口",例如"8080:80"表示将容器的80端口映射到宿主机的8080端口上。 通过端口映射,可以实现以下几点: 1. 容器内的服务可以通过宿主机的IP地址和映射的端口进行访问。例如,如果将容器的80端口映射到宿主机的8080端口上,那么可以使用"http://宿主机IP地址:8080"来访问容器内的服务。 2. 可以实现容器容器之间的通信。如果多个容器在同一网络中,可以通过容器的名称和映射的端口进行通信。 3. 可以将多个容器的服务映射到宿主机的不同端口上。通过不同的端口映射,可以同时在宿主机上运行多个容器,并通过不同的端口访问它们的服务。 需要注意的是,端口映射只是一种将容器内部的端口映射到宿主机端口上的方法,并不能改变容器内部的服务监听端口。因此,在容器内部的服务中仍需要使用容器内部的端口来进行监听和访问。而端口映射则是为了方便通过宿主机进行访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值