网络功能介绍

By timebusker on July 31, 2019

Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。

外部访问容器

容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。

当使用 -P 标记时,Docker 会随机映射一个 (49000~49900)有误 的端口到内部容器开放的网络端口。

使用 docker container ls 可以看到,本地主机的32768被映射到了容器的5000端口。此时访问本机的32768端口即可访问容器内 web 应用提供的界面。

[root@localhost docker]# docker container ls

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
e3b88320ebe1        training/webapp     "python app.py"     17 seconds ago      Up 15 seconds       0.0.0.0:32768->5000/tcp   quirky_black
[root@localhost docker]# 

同样的,可以通过 docker logs 命令来查看应用的信息。

# 可以直接查看容器内运行应用的日志

docker logs <容器ID>/<容器名称>

-p 则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有

ip:hostPort:containerPort 或者 ip::containerPort 或者 hostPort:containerPort
映射所有接口地址

使用hostPort:containerPort格式本地的5000端口映射到容器的5000端口,可以执行

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

此时默认会绑定本地所有接口上的所有地址。

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

可以使用ip:hostPort:containerPort格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1

docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
映射到指定地址的任意端口

使用ip::containerPort绑定localhost的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。

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

还可以使用 udp 标记来指定 udp 端口

docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
查看映射端口配置

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

docker port e3b88320ebe1 5000

注意:

  • 容器有自己的内部网络和 ip 地址(使用 docker inspect 可以获取所有的变量,Docker 还可以有一个可变的网络配置。)

  • -p 标记可以多次使用来绑定多个端口

docker run -d \
    -p 5000:5000 \
    -p 3000:80 \
    training/webapp \
    python app.py

容器互联

如果你之前有 Docker 使用经验,你可能已经习惯了使用 –link 参数来使容器互联。

随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 –link 参数。

  • 新建网络

下面先创建一个新的 Docker 网络。

docker network create -d bridge timebusker-net

-d参数指定 Docker 网络类型,有bridgeoverlay。其中overlay网络类型用于Swarm mode,在本小节中你可以忽略它。

  • 连接容器
# 启动Tomcat的测试网镜像容器,连接到timebusker-net网络,容器停止后删除

docker run -it --rm --name test-net1 --network timebusker-net tomcat bash

docker run -it --rm --name test-net2 --network timebusker-net tomcat bash

这样,在容器内部,可以直接使用ping测试联通

ping <容器ID>、<容器名称>

root@70ac2f9fe222:/usr/local/tomcat# ping 96693a05775b 
PING 96693a05775b (172.18.0.2) 56(84) bytes of data.
64 bytes from test-net1.timebusker-net (172.18.0.2): icmp_seq=1 ttl=64 time=0.522 ms
64 bytes from test-net1.timebusker-net (172.18.0.2): icmp_seq=2 ttl=64 time=0.177 ms


root@96693a05775b:/usr/local/tomcat# ping 70ac2f9fe222
PING 70ac2f9fe222 (172.18.0.3) 56(84) bytes of data.
64 bytes from test-net2.timebusker-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.121 ms
64 bytes from test-net2.timebusker-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.181 ms
64 bytes from test-net2.timebusker-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.181 ms

  • Docker Compose

如果你有多个容器之间需要互相连接,推荐使用 Docker Compose。

配置 DNS

如何自定义配置容器的主机名和 DNS 呢?秘诀就是 Docker 利用虚拟文件来挂载容器的 3 个相关配置文件。

在容器中使用mount命令可以看到挂载信息:

$ mount
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
tmpfs on /etc/resolv.conf type tmpfs ...

这种机制可以让宿主主机 DNS 信息发生更新后,所有 Docker 容器的 DNS 配置通过 /etc/resolv.conf 文件立刻得到更新。

配置全部容器的 DNS ,也可以在 /etc/docker/daemon.json 文件中增加以下内容来设置。

{
  "dns" : [
    "114.114.114.114",
    "8.8.8.8"
  ]
}

这样每次启动的容器 DNS 自动配置为 114.114.114.114 和 8.8.8.8。使用以下命令来证明其已经生效。

$ docker run -it --rm ubuntu:18.04  cat etc/resolv.conf

nameserver 114.114.114.114
nameserver 8.8.8.8

如果用户想要手动指定容器的配置,可以在使用 docker run 命令启动容器时加入如下参数:

-h HOSTNAME或者--hostname=HOSTNAME设定容器的主机名,它会被写到容器内的/etc/hostname/etc/hosts。 但它在容器外部看不到,既不会在docker container ls中显示,也不会在其他的容器的/etc/hosts看到。

--dns=IP_ADDRESS添加 DNS 服务器到容器的/etc/resolv.conf中,让容器用这个服务器来解析所有不在/etc/hosts中的主机名。

--dns-search=DOMAIN设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS不仅搜索 host,还会搜索 host.example.com。

注意:如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的 /etc/resolv.conf 来配置容器。