第7章 端口映射与容器互联
在实践中,经常会碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。
Docker除了通过网络访问外,还提供了两个很方便的功能来满足服务访问的基本需求:一个是允许映射容器内应用的服务端口到本地宿主主机;另一个是互联机制实现多个容器间通过容器名来快速访问。
端口映射实现容器访问
在启动容器的时候,如果不指定对应参数,无法进行访问,需要通过-p进行设置参数,当使用-P的时候docker会随机映射一个49000~49000的端口
docker run -d -P training/webapp python app.py
PS C:\Users\fe> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
PS C:\Users\fe> docker run -d -P training/webapp python app.py
Unable to find image'training/webapp:latest'locally
latest: Pulling from training/webapp
[DEPRECATION NOTICE] Docker Image Format v1, and Docker Image manifest version 2, schema 1 support will be removedinan upcoming release. Suggest the author of docker.io/training/webapp:latest to upgrade the image to the OCI Format, or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/
e190868d63f8: Pull complete
909cd34c6fd7: Pull complete
0b9bfabab7c1: Pull complete
a3ed95caeb02: Pull complete
10bbbc0fc0ff: Pull complete
fca59b508e9f: Pull complete
e7ae2541b15b: Pull complete
9dd97ef58ce9: Pull complete
a4c1b0cb7af7: Pull complete
Digest: sha256:06e9c1983bd6d5db5fba376ccd63bfa529e8d02f23d5079b8f74a616308fb11d
Status: Downloaded newer imagefortraining/webapp:latest
a7e6b6e0577677bf2b9efa37dc7f7b2e36e55eda98f384fd142bec46fc9d74d4
PS C:\Users\fe> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7e6b6e05776 training/webapp"python app.py"44 seconds ago Up 30 seconds 0.0.0.0:32768->5000/tcp heuristic_bose
由此可见本机的32768被映射到了容器的5000端口,访问32768给访问容器类提供的应用,同样可以通过docker logs -f heuristic_bose 查看
如果是使用-p那么可以指定要映射的端口,在一个指定端口上只能绑定一个容器,多次使用-p可以映射多个端口
PS C:\Users\fe> docker run -d -p 3697:5000 --name test1127 training/webapp python app.py
833733604c25065f381ce9ed7ba097e70fa57f9e7d9c9a3c5ffb0505b9fb880c
PS C:\Users\fe> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833733604c25 training/webapp"python app.py"33 seconds ago Up 32 seconds 0.0.0.0:3697->5000/tcp test1127
a7e6b6e05776 training/webapp"python app.py"4 minutes ago Up 4 minutes 0.0.0.0:32768->5000/tcp heuristic_bose
可以使用IP:映射端口号:容器端口号格式映射到指定的地址
docker run -d -p 127.0.0.1:3697:5000 --name test1127 training/webapp python app.py
映射到指定地址的任意端口IP::容器端口
docker run -d -p 127.0.0.1::5000 --name test1127 training/webapp python app.py
可以通过udp标记来指定udp端口
docker run -d -p 127.0.0.1::5000/udp --name test1127 training/webapp python app.py
查看容器映射的端口
docker port 容器名称或ID 端口号
PS C:\Users\fe> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
833733604c25 training/webapp"python app.py"33 seconds ago Up 32 seconds 0.0.0.0:3697->5000/tcp test1127
a7e6b6e05776 training/webapp"python app.py"4 minutes ago Up 4 minutes 0.0.0.0:32768->5000/tcp heuristic_bose
PS C:\Users\fe> docker port a7e6b6e05776
5000/tcp -> 0.0.0.0:32768
PS C:\Users\fe> docker port a7e6b6e05776 5000
0.0.0.0:32768
❝
容器有自己的内部网络和 IP 地址,使用docker [container] inspect+容器ID 可以获取容器的具体信息。
❞
互联机制实现便捷互访
容器的互联是一种让多个容器中的应用进行快速交互的方式,它会在源和接受容器之间创建链接关系,接受容器可以通过容器名快速访问到源容器,而不是指定的具体IP地址。
自定义容器命名
连接系统依据容器的名称来执行,因此需要自定义一个好记的名称,在重启的时候或连接其他容器的时候,自定义的名称也不会改变,使用--name可以标记自定义名称。需要注意的是容器的名称是需要是唯一的
docker run -d -P --name web training/webapp python app.py
容器互联
使用--link参数可以让容器之间安全的进行交互
创建一个数据库容器
docker run -d --name db training/postgres
创建一个新的web容器,存在的话需要先删除,将新的容器连接到db容器
docker rm -f web
docker run -d -P --name web --link db:db training/webapp python app.py
此时,db容器和web容器建立了互联关系,--link name:alias,其中name是要连接容器的名称,alias是别名
测试时候连接连接成功
PS C:\Users\fe> dockerexec-it web ping db
PING db (172.17.0.2) 56(84) bytes of data.
64 bytes from db (172.17.0.2): icmp_seq=1 ttl=64 time=0.371 ms
64 bytes from db (172.17.0.2): icmp_seq=2 ttl=64 time=0.047 ms
64 bytes from db (172.17.0.2): icmp_seq=3 ttl=64 time=0.061 ms
64 bytes from db (172.17.0.2): icmp_seq=4 ttl=64 time=0.034 ms
64 bytes from db (172.17.0.2): icmp_seq=5 ttl=64 time=0.026 ms
64 bytes from db (172.17.0.2): icmp_seq=6 ttl=64 time=0.027 ms
^C
--- db ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5237ms
rtt min/avg/max/mdev = 0.026/0.094/0.371/0.124 ms
使用link参数建立的容器所链接的主机需要处于运行状态
所链接的容器也必须是运行状态
使用link选项链接的主机ip不需要固定,因为每次新建容器都会检查所链接容器的ip,并在/etc/hosts里生成新的alias 名称对应的ip
Docker相当于在两个互联的容器之间创建了一个虚机通道,而且不用映射它们的端口到宿主主机上。在启动d6容器的时候并没有使用-p和-P标记,从而避免了暴露数据库服务端口到外部网络上。
Docker 通过两种方式为容器公开连接信息:
更新环境变量
更新/etc/hosts 文件。
使用env命令来查看web容器的环境变量
PS C:\Users\fe> docker run --rm --name web2 --link db:db training/webapp env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=74f0d13e6593
DB_PORT=tcp://172.17.0.2:5432
DB_PORT_5432_TCP=tcp://172.17.0.2:5432
DB_PORT_5432_TCP_ADDR=172.17.0.2
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web2/db
DB_ENV_PG_VERSION=9.3
HOME=/root
其中DB_开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。
除了环境变量, Docker 还添加host 信息到父容器的/etc/hosts 的文件。下面是父 容器 web的hosts 文件:
PS C:\Users\fe> docker run -t -i --rm --link db:db training/webapp /bin/bash
root@87bb8e4295ab:/opt/webapp# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 db e4b1d33b74a4
172.17.0.6 87bb8e4295ab
PS C:\Users\fe> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a007b222bb77 wordpress"docker-entrypoint.s…"7 minutes ago Up 7 minutes 80/tcp blog
99ee79c9b33f mysql:5.6"docker-entrypoint.s…"11 minutes ago Up 11 minutes 3306/tcp mysql
820326e7de1a training/webapp"python app.py"14 minutes ago Up 14 minutes 0.0.0.0:32771->5000/tcp web
e4b1d33b74a4 training/postgres"su postgres -c '/us…"14 minutes ago Up 14 minutes 5432/tcp db
这里有 hos 信息,第一个是 db 容器的 IP 和主机名,第二个是 web 容器, web 容器用自己的 id 作为默认主机名。
可以在 web 容器中安装 ping 命令来测试跟 db 容器的连通:
root@820326e7de1a:/opt/webapp# apt-get install -yqq inetutils-ping
(Reading database ... 18233 files and directories currently installed.)
Removing ubuntu-minimal (1.325) ...
Removing iputils-ping (3:20121221-4ubuntu1.1) ...
Selecting previously unselected package inetutils-ping.
(Reading database ... 18221 files and directories currently installed.)
Preparing to unpack .../inetutils-ping_2%3a1.9.2-1_amd64.deb ...
Unpacking inetutils-ping (2:1.9.2-1) ...
Setting up inetutils-ping (2:1.9.2-1) ...
root@820326e7de1a:/opt/webapp# ping db
PING db (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.093 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.049 ms
^C--- db ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.045/0.068/0.093/0.000 ms
在用ping的时候会将db转成对应的ip,可以使用 inspect 命令查看容器的详细信息