你是否曾经想过 Docker
中的网络是如何工作的?也许你对使用 Docker
的网络层可以做的鲜为人知的事情感兴趣?以下是一些有趣的事实和用例,可能有助于日常使用。
开放端口
让我们从基础开始。端口开放是 Docker
网络中最常用的东西,但你了解它的全部内容吗?
让我们看一个简单的命令,如下所示:
1 | docker run -p 127.0.0.1:80:8080/tcp ubuntu bash |
这是什么意思?好吧,可能有点棘手,但它的意思是:
在端口 80
上监听 127.0.0.1
上的 TCP
连接,并将流量转发到容器内的端口 8080
。
如果我们稍微简化一下:
1 | docker run -p 80:8080/tcp ubuntu bash |
我们省略了 IP
部分,现在 Docker
将监听所有接口,因此可以从外部访问该服务。
我们可以进一步更改符号,然后运行:
1 | docker run -p 80:8080/udp ubuntu bash |
这将转发 udp
连接。另一个选项是 sctp
,但它并未广泛用于与 Web
相关的东西。TCP
显然是最常见的,因此如果我们跳过 /protocol 部分 - 它将默认设置为 TCP
。
如果我们只运行这个会发生什么:
1 | docker run -p 8080 ubuntu bash |
这会将 TCP
流量从随机选择的端口转发到容器中的端口 8080
。等等?随机?!我怎么知道使用了哪个端口?
只需查看 docker ps
- 有一列:
1 | docker ps |
PORTS
列中包含你需要的所有信息,甚至更多。它还显示未转发的开放端口。此类端口无法从外部访问(docker
网络除外,但这会改变),但如果你想转发它,你可以获得此信息。
你还可以运行 docker port
来检查给定容器的映射:
1 | docker port project_phpmyadmin_1 |
但是它缺少未映射端口的部分,所以我想你不会经常使用该命令 ;)
还有最后一件事我们需要提及,那就是 docker run
的 -P
参数。
1 | docker run -P ubuntu bash |
-P
在主机上的随机端口上开放 Dockerfile
中提到的所有端口。
连接容器
让我们启动一个简单的 Web
服务器:
1 | docker run -d --name test_web nginx:alpine |
如果我们启动第二个容器,比如说 ubuntu
,在其上安装 curl
并尝试访问网页:
1 | docker run -t -i --rm ubuntu bash |
这行不通,名称未解析!我们可以使用 docker inspect
并检查 test_web 容器的 IP
是否为 172.17.0.2,然后运行
1 | curl 172.17.0.2 |
而且它可以工作。因此连接性有限,但这是可能的。
如果你熟悉 docker-compose
,这可能会令人困惑。docker-compose
中的服务可以使用其名称轻松相互通信!如果你有一个简单的文件,例如:
1 | version: "3.6" |
然后 phpmyadmin
显然可以使用其名称 db 连接到 db 服务!
原因很简单,它适用于同一网络内的容器,默认容器除外。
让我们尝试一下!
我们可以通过运行以下命令创建一个新网络:
1 | docker network create test |
并将现有容器连接到它并运行:
1 | docker network connect test test_web |
我假设测试 bash
容器仍然处于活动状态,你只需在上面的第二行中使用它的名称即可。现在切换回它并运行:
1 | curl test_web |
可以正常工作!请注意,只要两个容器共享同一网络,就无需开放端口即可从第二个容器访问它。
通过运行以下命令断开其中一个容器与新创建的网络的连接:
1 | docker network disconnect test NameOfYourBashContainer |
并且名称将不再解析!
还可以在创建容器时将其连接到网络,只需将网络作为输入选项之一传递即可:
1 | docker run -t -i --rm --network test ubuntu bash |
相关文章: