docker 端口映射是通过宿主机的 iptables
来实现的,本文通过示例介绍端口映射的原理。
启动MySQL容器
docker 启动 mysql 容器
docker run -d -e MYSQL_ROOT_PASSWORD=password --name mysql_db -p 3306:3306 mysql
查看ip地址
$ docker inspect mysql_db|grep IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
3306 端口是通过 docker-proxy 代理的
$ ps -ef|grep 3306
root 1755 1268 0 08:35 ? 00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3306 -container-ip 172.17.0.2 -container-port 3306
iptables 规则
- 查看 iptables 中有一条
Chain DOCKER
的链
$ iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 129 packets, 38495 bytes)
pkts bytes target prot opt in out source destination
13 816 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 129 packets, 38495 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 634 packets, 48923 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 644 packets, 49630 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:3306
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.2:3306
- 显示
Chain DOCKER
的 line-number
,删除规则时使用
$ sudo iptables -t nat -vnL DOCKER --line-number
Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.2:3306
新增其他端口
sudo iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:8080
容器内启动 python3 -m http.server 8080
,后可以通过 curl 172.17.0.2:8080
访问
查看 Chain DOCKER
$ iptables -t nat -nvL DOCKER --line-number
Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:3306 to:172.17.0.2:3306
3 0 0 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:8080
删除端口
sudo iptables -t nat -D DOCKER <num>
说明
上面修改只是临时配置方法,也可以通过修改容器的配合文件防止重启后不生效问题,配置文件在/var/lib/docker/containers/[containerId]
目录下 hostconfig.json
和 config.v2.json
$ cat hostconfig.json | jq
{
...
"NetworkMode": "default",
"PortBindings": {
"3306/tcp": [
{
"HostIp": "",
"HostPort": "3306"
}
]
},
cat config.v2.json | jq
{
...
"NetworkSettings": {
...
"Ports": {
"3306/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "3306"
}
]
},