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

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

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

容器与宿主机间建立端口映射关系时,可以在运行容器时使用-P或-p参数指定端口映射。两者区别如下:

  • -P参数会随机分配一个49000~49900之间的端口到容器内部开放的网络(通过EXPORT指定的)端口

  • -p则可以具体指定要映射的端口,并且在一个指定端口上只能绑定一个容器

1.1 -P绑定宿主机随机端口

-P参数会随机绑定一个49000~49900之间的端口所运行容器的导出端口。

如,运行一个容器,并使用-P绑定宿主机端口:在上一篇我拉取了一个 python 应用的镜像

docker run -d --name webapp-test -P training/webapp
file

在这个示例中,我们通过training/webapp镜像创建并运行了一个名为webapp-test的容器。运行容器时,我们通过-P参数进行了端口映射。这时,可以通过docker ps命令查看所分配的端口号:

如上所示,宿主机的32770端口被绑定到了容器的5000端口。

1.2 -p指定端口、IP地址绑定

如果不想使用随机端口,则可以使用-p参数来指定要绑定的端口号。-p参数除了可以指定端口号外,还可以指定宿主机的IP。-p支持以下几种绑定格式:

// 绑定宿主机IP及端口
ip:hostPort:containerPort
// 绑定宿主机IP
ip::containerPort
// 绑定宿主机端口
hostPort:containerPort
1.2.1 绑定宿主机所有的IP

使用hostPort:containerPort格式进行宿主机及容器端口映射时,默认会将宿主机的所有IP绑定到容器。如:

docker run -d --name webapp-test -p 5000:5000 training/webapp

在这个示例中,将宿主机的5000端口映射到了容器的5000端口。在这种情况下,会绑定本地所有接口上的所有IP地址

1.2.2 映射到指定地址的指定端口

使用ip:hostPort:containerPort格式可以将宿主机指定的IP及端口,绑定到容器端口。

如,绑定127.0.0.1IP到容器:

docker run -d --name webapp-test -p 127.0.0.1:5000:5000 training/webapp
1.2.3 映射指定地址及随机端口

ip::containerPort格式会绑定宿主机的指定IP地址及随机端口到容器端口。如:

docker run -d --name webapp-test -p 127.0.0.1::5000 training/webapp

使用docker ps查看所分配的端口:

file
1.3 其它

在前面示例中,我们通过docker ps查看已创建的容器及容器所绑定的端口。除了docker ps命令外,还可以使用docker port查看所绑定的端口及IP地址:

docker port webapp-test
file

容器内部可能会使用多个网络端口,使用docker port命令时,可以指定端口参数,以查看容器指定端口的绑定情况:

 docker port webapp-test 5000
file

在创建/运行容器时,-p参数可以被多次使用,以绑定多个容器端口:

docker run -d --name webapp-test -p 5000:5000 -p 6000:80 training/webapp

Docker进行端口绑定时,默认都是绑定 tcp 端口,如果要绑定 UDP端口,可以在端口后面加上 /udp:

docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
file

二. 容器链接(Link)

端口映射并不是唯一把 docker 连接到另一个容器的方法。
docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。
docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息。

2.1 容器的命名

Docker的连接系统会依据容器的名称来进行连接,因此,首先需要定义容器的名称。在不指定容器命令的情况,docker 会自动对它进行命名。另外,我们也可以使用 --name 标识来命名容器,例如:

docker run -d -P --name webapp training/webapp python app.py

命令并运行容器后,可以通过docker ps命令来查看相关信息。也可以使用docker inspect命令来查看容器的名称:

file
docker inspect -f "{{ .Name }}" 8afb061a2da9
file
2.2 容器的互联

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

2.2.1 下载postgres镜像
 docker pull postgres:9.4
file
2.2.2 新建一个数据库容器
docker run -d --name db -e POSTGRES_PASSWORD=123456  postgres:9.4
file
2.2.3 新建一个web容器和postgres容器互联
docker run -d -P --name web --link db:db training/webapp python app.py
file

--link表示建立容器互联,参数为name:aliasname是要链接的容器名称,alias是我们取得别名

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

2.3 查看新建的容器
docker ps
file

web容器的hosts文件也发生了变化,我们可以看下

docker exec -it web /bin/bash
cat /etc/hosts
file

这里面有两个ip,一个是web的,一个是db的,我们可以用ping命令查看这个两个ip之间能否ping通

 ping db
file
 ping 1efe89571e10
file
 ping 172.18.0.11
file

建立链接没问题!我们启动db容器的时候,没有通过-p指定端口,避免了数据库端口暴露在外部网络,这样很安全。

三. Docker网络(Networking)

Docker Networking允许用户创建自己的网络,容器间可以通过这个网络互相通讯。Docker Networking允许容器跨越不同的宿主机通讯,且网络配置方式更灵活。

Docker Engine 会在引擎安装时自动创建一个名为bridge(桥接)网络,这个网络会与docker0(Docker内部网络)相对应。

除此之外,用户还可以自行创建bridge或overlay类型的网络。bridge网络适用于单台宿主机运行的单Docker引擎环境,而overlay网络允许我们跨多台宿主机进行通讯。

3.1 创建网络

要实现Docker Networking互联,首先要使用docker network create命令创建一个网络:

docker network create -d bridge test-net

参数说明:

  • -d:参数指定 Docker 网络类型,有 bridge、overlay。

其中 overlay 网络类型用于 Swarm mode,在本小节中你可以忽略它。

现在可以通过docker network inspect查看这个新建的网络:

file

使用docker network ls命令也可以看到这个新建的网络

docker network ls
file
3.2 创建容器并连接到网络

创建网络后,可以在创建容器时通过--network参数指定容器要使用的网络:

docker run -d --name db2 --network=test-net training/postgres
file

使用docker network inspect查看的网络情况:

docker network inspect test-net
file

可以看到test-net网络的Containers参数中,包含了网创建的容器的信息,表中容器已连接到我们所创建的网络,而该容器的IP地址为172.19.0.2/16。

接下来,创建一个交互式容器,并查看该容器内部的网络情况:

docker run -it --name web3 --network=test-net training/webapp /bin/bash
file

然后使用ping测试是否可以连接到db2容器:

ping db2
file

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

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

当需要将已在运行的容器添加到已有的网络时,可以使用docker network connect命令。

删除刚创建的web容器,并使用以下命令重新创建:

docker ps -a
docker rm 5f5e095922f2
docker run -d --name web3 training/webapp python app.py
file

将这个容器连接到已创建的名为test-net的网络:

docker network connect test-net web3

使用docker network inspect查看的网络情况,Containers节点内容如下:

file

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

3.4 断开网络与网络删除

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

 docker network disconnect test-net web3

这样就将容器web3与网络test-net断开的了连接。

网络不在需要后,可以使用docker network rm命令将网络删除:

docker network rm test-net

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

参考链接:
http://suo.im/5EYLab

 往期推荐 

????

Docker 入门到实战教程(一)介绍Docker

Docker 入门到实战教程(二)安装Docker

Docker 入门到实战教程(三)镜像和容器

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐