Skip to content

在实践过程中,经常会碰到需要多个服务组件的容器协同工作的情况,而这往往需要多个容器之间能够访问到对方的服务。为此 docker 提供了除了网络访问外的另外两种方式来方便容器的互访实现,一个是将容器内应用的端口映射到本地宿主机,另一互联机制使得容器能够使用容器名称来快速的访问。

端口映射实现容器访问

从容器外部访问容器应用

默认情况下下如果不指定参数,容器外部的是无法访问容器内的网络和服务的。当容器中运行一些网络应用,要让外部访问者些应用时,可以使用-P 或者-p 参数来指定端口映射。

使用—P 参数时容器会随机的映射一个 49000-49900 的端口到容器内部开放的网络端口。

shell
docker run -d -p training/webapp python app.py

使用-p 参数时可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器具体的格式为:ip: hostport:ContainerPort | IP:ContainerPort | HostPort:ContainerPort

映射所有接口地址

使用 HostPort : ContainerPort 格式将本地的端口映射到容器的端口

shell
# 此时默认情况下会映射本地多有的网段到该端口上
docker run -d -p 5000:5000 training/webapp  python app.py
# 多次使用该参数可以绑定多个端口
docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py

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

使用 Ip : HostPort : ContainerPort 的格式将端口映射到指定地址的指定端口上。

shell
docker run -d -p 127.0.01:5000:5000 training/webapp python app.py

映射到指定地址的任意端口

使用 Ip:ContainerPort 的格式将端口映射到指定地址的任意端口上。

shell
# 映射到本机回环网络的5000端口,本机之外无法访问
docker run -d -p 127.0.0.1:5000 training/webapp python app.py

# 映射到本机所有网络的5000端口,外网访问
docker run -d -p 5000:5000 training/webapp python app.py

#映射到本地回环网络 udp 端口
docker run -d -p 127.0.0.1:5000/udp training/webapp python app.py

查看映射端口配置

使用 docker port containerName portNumber 命令可以查看当前映射的端口配置,也可以查看到绑定的地址。

shell
docker port nostalgic_more 5000

# 容器有自己的内部网络和 IP地址,使用 docker inspect + 容器 ID 可以获取容器的具体信息。

容器互联机制实现便捷访问

容器互联机制是一种让容器中的应用快速交互的方式,他会在源和接收容器之间建立链接关系,接收容器可以通过容器名快速的访问到源容器,而不用指定具体的 IP 地址。

自定义容器名

连接系统依据容器的名称来执行,在此之前需要定义好一个容器名称。

shell
docker run -d -P --name web training/webapp python app.py
# 使用--name 来指定容器的名称

容器的名称是唯一的,不能创建同名称的容器,如果要创建已经存在的容器名称需要先删除原先的容器在创建新的容器,在执行 docker run 时可以使用--rm 参数来标记,该标记表示在容器停止之后容器将会被删除。

容器关联互联

使用--link 参数可以让容器之间安全的进行交互。link 的参数为:--link name:alias 其中 name 是要联机的容器名称,alias 是此链接的别名,需要注意的是这种方式会将被连接容器的所有端口都暴露给外部容器,使用容器名访问其他容器其底层实现是依赖 docker dns 来实现的。

shell
docker run -d -name db training/mysql

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

docker ps # 可以查看到相对应的映射关系

使用互联机制当问容器的好处在于,docker 相当于为容器建立了一个通道,在不需要映射端口信息的情况下实现了容器的互联互访,避免了端口映射暴露到公网之上的危险。

DANGER

需要注意的是新版本的 docker 已经废弃了此种连接方式.

docker 提供了两种公开容器链接的方式

  1. 更新环境变量
  2. 更新本地的/etc/hosts 文件

使用 env 参数来查看容器的环境变量

shell
docker run -d -P --rm --name web --link db:db training/webapp python app.py
DB_NAME=/web/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5000_TCP=tcp://172.17.0.5:5432

其中 DB 开头的环境变量是提供 web 容器 链接 db 时使用的,前端采用大小拼接别名。 传了环境变量外,docker 还添加 host 信息到芙蓉起的 /etc/hosts 文件中

shell
docker run -t -i --rm --link db:db training/webapp /bin/bash
172.12.0.17  daubbw2ea1d

172.12.0.15  db

# 其中第一个时父级容器的 id 信息,后者是 db 容器的 ip  和主机名。

网络互联

网络互联是随着 docker 的发展而逐渐被 docker 作为默认的访问方式。在新版本的 docker 并没有内置 docker dns 服务,因此默认情况下你讲无法使用 docker 的网络访问。为了应对这一问题你可以使用容器别名或者自建 docker dns 来实现访问。

容器别名

容器别名的实现是基于 docker dns 来实现的,在同一网络中使用容器别名访问需要按照如下步骤进行:

  1. 创建一个自定义的 docker 网络,并指定一个网络名称。
bash
docker network creeate xnet
  1. 创建容器时指定所使用的网络
shell
docker run -d --name xname --network xnet --network-alias xname_alias nginx

自建 dns

新版的 docker 已经不再内置 dns 服务而是使用宿主机的 dns 来实现访问,如果要自定义 docker dns 这需要按照下边的步骤进行:

  1. 创建一个自定义的网络
shell
docker network create xnet
  1. 启动一个 dns 容器并将其链接到 xnet 中
shell
docker run -d --name dns_server --network xnet -p 53:53/udp --restart always dns_server_image
  1. 将其他的容器链接到 xnet 中,并且将其 dns 服务器的 IP 地址设置为 dns 容器的 ip 地址
shell
docker run -d --name x_container --network xnet --dns IP_ADDRESS another_image
  1. 检测在中的 dns 服务解析是否正常
shell
docker exec -it x_container nslookup dns_server

TIP

容器别名访问和 docker dns 方式都是依赖 docker dns 服务来实现的,不同的是在使用别名的方式中容器之间的互访使用的是容器别名且要求容器必须在同一网络,dns 的方式这使用 IP 进行可以跨网络使用也就更容易实现扩展.