本篇是关于 docker 容器的端口映射和容器之间的互联内容。
注:环境为 CentOS7,docker 19.03。
docker 的容器除了能连接网络外,在许多时候,我们需要让多个容器来协同完成任务。为了应对这样的需求,docker 提供了两种机制:
- docker 容器和主机间的端口映射。
- 利用互联机制让多个容器通过容器名来快速访问。
端口映射实现容器访问
容器启动时,如果不指定对应的参数,容器外部是无法访问容器内部的。要让外部能访问内部的话,在容器启动时利用选项 -p | -P 可以实现端口的映射。
- -p :指定映射端口。
- -P(大写):Docker会随机映射⼀个49000~49900的端⼜到内部容器开放的⽹络端口。
# docker run -d -P training/webapp python app.py
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a91ece91213 training/webapp "python app.py" 8 seconds ago Up 6 seconds 0.0.0.0:32768->5000/tcp eloquent_fermat
指定 -P 随机分配主机的32768端口映射到容器的5000端口,访问主机的32768输出如下:
# curl http://127.0.0.1:32768
Hello world!
端口映射类型
利用选项 -p | -P 能实现不同的映射类型。
1.指定端口映射:-p HostPort:ContainerPort
# docker run -d -p 5000:5000 training/webapp python app.py
2.多个端口映射,多次使用 -p 实现
# docker run -d -p 5001:5000 -p 3000:80 training/webapp python app.py
3.映射到指定地址的指定端口 -p IP:HostPort:ContainerPort
# docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
4.映射到指定地址的任意端口 -p IP::ContainerPort
# docker run -d -p 127.0.0.1::5000 training/webapp python app.py
5.映射到指定的协议 tcp 或 udp -p IP::ContainerPort/protocol
# docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
查看端口映射
查看 docker 容器的映射端口可以使用 inspect 命令,同时 docker 也提供了更直观的子命令 port
# docker port f061c03d
5000/udp -> 127.0.0.1:5000
容器互联
容器的互联(linking) 是⼀种让多个容器中的应⽤进⾏快速交互的⽅式。 它会在源和接收容器之间创建连接关系, 接收容器可以通过容器名快速访问到源容器, ⽽不⽤指定具体的IP地址。
连接系统依据容器的名称来执⾏。所以在启动容器的时候需要使用 --name 选项指定容器名称,虽然容器启动时会被随机分配一个名称,但互联是指定名称还是必要的。
# docker run -d -p 127.0.0.1:5000:5000 --name web training/webapp python app.py
注:docker 名唯一。
容器互联使用选项 --link name:alias
,前者是容器名,后者是自定义的别名。
例如我们创建一个数据库容器 db ,再创建一个web应用容器 web 连接 db
# docker run -d --name db training/postgres
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73fd1af29108 training/postgres "su postgres -c '/us…" 5 seconds ago Up 4 seconds 5432/tcp db
# docker run -d -P --name web --link db:db training/webapp python app.py
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e983b169dd5 training/webapp "python app.py" 6 seconds ago Up 4 seconds 0.0.0.0:32769->5000/tcp web
73fd1af29108 training/postgres "su postgres -c '/us…" About a minute ago Up About a minute 5432/tcp db
这样一来,web容器就和db容器建立互联关系了。
docker 相当于在两个互联的容器之间创建了⼀个虚机通道, ⽽且不⽤映射它们的端⼜到宿主主机上。 在启动db容器的时候并没有使⽤ -p 和 -P 标记, 从⽽避免了暴露数据库服务端⼜到外部⽹络上。
docker 通过两种⽅式为容器公开连接信息:
- 更新环境变量;
- 更新 /etc/hosts ⽂件。
重新启动容器查看它互联的环境变量
# docker run -it -P --name web2 --link db:db --rm training/webapp env
TERM=xterm
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=/web4/db
DB_ENV_PG_VERSION=9.3
HOME=/root
其中DB_开头的环境变量是供web容器连接db容器使⽤, 前缀采⽤⼤写的连接别名。
除了环境变量, docker 还添加 host 信息到⽗容器的 /etc/hosts 的⽂件。 下⾯是⽗容器 web 的 hosts ⽂件:
172.17.0.3 db 73fd1af29108
172.17.0.4 7e983b169dd5
172.17.0.3 指定 db 容器和对应的 id,172.17.0.4 是 web 容器。当然使用多个 --link 就可以连接多个容器。