在实践中会经常碰到需要多个服务组件容器共同协作的情况,这往往需要多个容器之间能够互相访问到对方的服务。除了通过网络访问外,Docker还提供了两个很方便的功能来满足服务访问的基本需求:一是允许映射容器内应用的服务端口到本地宿主主机;另一个是互联机制实现多个容器间通过容器名来快速访问。
端口映射实现访问容器
1、从外部访问容器应用
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。当容器中运行一些网络应用,要让外部访问这些应用时,可以通过-p
或-P
参数来指定端口映射。当使用-P
(大写的)标记时,Docker会随机映射一个端口到内部容器开放的网络端口:
1 |
|
-p
(小写的)可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有:
1 | IP:HostPort:ContainerPort|IP::ContainerPort|HostPort:ContainerPort |
2、映射所有接口地址
1 | //使用HostPort:ContainerPort格式将本地的5000端口映射到容器的5000端口 |
3、映射到指定地址的指定端口
1 |
|
4、映射到指定地址的任意端口
1 | //使用IP::ContainerPort绑定localhost的任意端口到容器的5000端口,本地主机会自动分配一个端口 |
[root@xxx ~]# docker port priceless_franklin 5000
0.0.0.0:5000
1 |
|
//使用–name参数自定义容器名称
[root@xxx ~]# docker run -d -p 5000:5000 –name web training/webapp python app.py
757d2ee95be01e2c509426c52bf5b4176ff7199eb654b5854ddf0e9b8412c044
//查看运行容器,注意NAMES栏
[root@xxx ~]# docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
757d2ee95be0 training/webapp “python app.py” 5 seconds ago Up 4 seconds 0.0.0.0:5000->5000/tcp web
//还可使用inspect –format “{{.Name}}“获取容器名字
[root@xxx ~]# docker inspect –format “{{.Name}}“ 757d2ee95be
/web
1 |
|
//创建一个db容器
[root@xxx ~]# docker run -d –name db training/postgres
Unable to find image ‘training/postgres:latest’ locally
latest: Pulling from training/postgres
a3ed95caeb02: Pull complete
6e71c809542e: Pull complete
2978d9af87ba: Pull complete
e1bca35b062f: Pull complete
500b6decf741: Pull complete
74b14ef2151f: Pull complete
7afd5ed3826e: Pull complete
3c69bb244f5e: Pull complete
d86f9ec5aedf: Pull complete
010fabf20157: Pull complete
Digest: sha256:a945dc6dcfbc8d009c3d972931608344b76c2870ce796da00a827bd50791907e
Status: Downloaded newer image for training/postgres:latest
3b48a3a82a86a52244527112a4a03e98e951c8edcdaedb3b63bc1a0775ac0315
//删除原来的web容器
[root@xxx ~]# docker rm -f web
web
//重建web容器,并让它连接到db容器,–link参数的格式为–link name:alias,其中name是要连接的容器名称,alias是这个连接的别名
[root@xxx ~]# docker run -d -P –name web –link db:db training/webapp python app.py
ca82ea2a2e5ad9b407d5c80fcfd6cd01f7e03be46864e5058b539075e858c626
//查看运行容器
[root@xxx ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ca82ea2a2e5a training/webapp “python app.py” 22 seconds ago Up 21 seconds 0.0.0.0:32784->5000/tcp web
3b48a3a82a86 training/postgres “su postgres -c ‘/us…” About a minute ago Up About a minute 5432/tcp db
//查看接受容器(web)连接信息
[root@xxx ~]# docaker inspect –format “{{.HostConfig.Links}}“ web
[/db:/web/db]
1 | Docker相当于在两个互联的容器之间创建了一个虚机通道,而且不用映射他们的端口在宿主主机上。在启动db容器的时候并没有使用`-p`和`-P`标记,从而避免了暴露数据库服务端口到外部网路上。 |
[root@xxx ~]# 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=6f8232ea8d36
DB_PORT=tcp://172.17.0.3:5432
DB_PORT_5432_TCP=tcp://172.17.0.3:5432
DB_PORT_5432_TCP_ADDR=172.17.0.3
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_PROTO=tcp
DB_NAME=/web2/db
DB_ENV_PG_VERSION=9.3
HOME=/root
1 |
|
//创建容器,并进入bash
[root@xxx ~]# docker run -it –rm –link db:db training/webapp /bin/bash
//查看hosts配置
root@d64fd0fa99f0:/opt/webapp# cat /etc/hosts
172.17.0.3 db 3b48a3a82a86
172.17.0.4 d64fd0fa99f0
//查看db容器,发现其将容器id作为主机名
root@3b48a3a82a86:/# cat /etc/hosts
127.0.0.1 localhost
172.17.0.3 3b48a3a82a86
1 |
|
//安装ping命令
root@d64fd0fa99f0:/opt/webapp# apt-get install inetutils-ping
Unpacking inetutils-ping (2:1.9.2-1) …
Setting up inetutils-ping (2:1.9.2-1) …
//执行ping命令,测试与db容器的连通性
root@d64fd0fa99f0:/opt/webapp# ping db
PING db (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=0.267 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.314 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.260 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.131 ms
`