10. 端口映射与容器互联
Docker 除了通过网络访问外, 还提供了两个很方便的功能来满足服务访问的基本需求:
-
一个是允许映射容器内应用的服务端口到本地宿主主机;
-
另一个是互联机制实现多个容器间通过容器名来快速访问。
1. 端口映射实现容器访问⚓
1.1 从外部访问容器应用⚓
在启动容器的时候,如果不指定对应参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。
要让外部访问这些应用时, 可以通过-P或-p参数来指定端口映射。 当使用-P
(大写的)标记时, Docker 会随机映射一个 49000~49900
的端口到内部容器开放的网络端口。然后使用docker port CONTAINER
查看端口。
$ docker run -P -itd --name test_mount changedcentos:latest /bin/bash
$ docker port test_mount
-p
(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有 IP:HostPort:ContainerPort 或 IP::ContainerPort 或 HostPort:ContainerPort
。
1.2 映射到指定地址的指定端口⚓
IP:HostPort:ContainerPort
指定映射使用一个特定的地址:
docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
1.3 映射到指定地址的随机端口⚓
IP::ContainerPort
绑定一个端口到容器的端口,本地主机自动分配一个端口:
docker run -d -p 127.0.0.1::5000 training/webapp python app.py
1.4 映射所有接口地址⚓
HostPort:ContainerPort
将本地所有接口上的所有地址的特定端口映射到容器的端口,可以执行如下命令:
docker run -d -p 5000:5000 webapp python app.py
多次使用-p
可以绑定多个端口:
docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
Note
容器有自己的内部网络和IP地址,使用 docker [container] inspect+容器ID 可以获取容器的具体信息。
2. 互联机制实现便捷互访⚓
容器的互联(Iinking)是一种让多个容器中的应用进行快速交互的方式。它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体的IP地址。
在执行docker [container] run的时候如果添加--rm
标记,则容器在终止后会立刻删除。
2.1 容器互联⚓
使用--link
参数可以让容器之间安全地进行交互。
# 先创建新的数据库容器
# 没有使用端口映射,避免暴露数据库服务端口到外部网络
$ docker run -d --name mysqldb -e MYSQL_ROOT_PASSWORD=abcd1234 mysql
# 然后创建一个新的web容器,并将它连接到db容器
# --link 容器名:别名
$ docker run -d -P --name my_flask --link mysqldb:db jcdemo/flaskapp
# 可以看到现在web容器的名字多了一个值:my_flask/db
$ docker ps --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb662a99332d4825e7bacfc914718b0d7097330efa10893232f1c7a16c0a5415 jcdemo/flaskapp "python /src/app.py" 8 minutes ago Up 8 minutes 0.0.0.0:32770->5000/tcp my_flask
aae4ae2138f76f945a042157755d6f1fc4f30d1b884b98902270d9d6826a2e7f mysql "docker-entrypoint.sh mysqld" 21 minutes ago Up 21 minutes 3306/tcp, 33060/tcp my_flask/db,mysqldb
Docker 通过两种方式为容器公开连接信息:
- 更新环境变量;
- 更新
/etc/hosts
文件。
使用 env 命令来查看 web 容器的环境变量:
$ docker run --rm -P --name my_registry2 --link mysqldb:db daocloud.io/registry env
DB_PORT_33060_TCP_ADDR=172.17.0.3
HOSTNAME=901607172aa7
DB_PORT=tcp://172.17.0.3:3306
DB_PORT_3306_TCP=tcp://172.17.0.3:3306
DB_PORT_33060_TCP_PORT=33060
DB_ENV_MYSQL_VERSION=8.0.16-2debian9
SHLVL=1
DB_PORT_33060_TCP_PROTO=tcp
HOME=/root
DB_NAME=/my_registry2/db
DB_PORT_33060_TCP=tcp://172.17.0.3:33060
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DB_ENV_MYSQL_MAJOR=8.0
DB_PORT_3306_TCP_ADDR=172.17.0.3
DB_ENV_MYSQL_ROOT_PASSWORD=abcd1234
PWD=/
DB_ENV_GOSU_VERSION=1.7
DB_PORT_3306_TCP_PORT=3306
DB_PORT_3306_TCP_PROTO=tcp
其中DB_开头的环境变量是供web容器连接db容器使用、前缀采用大写的连接别名。
除了环境变量, Docker 还添加 host信息到父容器的 /etc/hosts
的文件:
$ docker run --rm -P -it --name my_centos2 --link mysqldb:db changedcentos /bin/bash
# 其实也可以在这里执行env查看环境变量
[root@7881bcf7a164 /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
······
172.17.0.3 db aae4ae2138f7 mysqldb
172.17.0.5 7881bcf7a164
# 还可以去ping容器
[root@7881bcf7a164 /]# ping db
PING db (172.17.0.3) 56(84) bytes of data.
64 bytes from db (172.17.0.3): icmp_seq=1 ttl=64 time=0.258 ms
64 bytes from db (172.17.0.3): icmp_seq=2 ttl=64 time=0.114 ms
64 bytes from db (172.17.0.3): icmp_seq=3 ttl=64 time=0.125 ms
用户可以链接多个子容器到父容器,比如可以链接多个web到同一个db容器上。