在使用Docker部署服务时,有时候会因为新的需求,变更或者增加容器中的服务端口,为了不中断容器的运行,我们需要为运行中的Docker容器动态增加端口映射。整体来说,可通过以下方案实现。

一.Docker宿主机的iptables命令

Docker容器的端口映射是通过宿主机的iptables实现的,我们可以通过控制宿主机的iptables实现容器的端口映射,类似路由器中设置路由端口映射。容器已有的端口映射规则存储在nat表的DOCKER链中,可以通过以下命令查看。

sudo iptables -t nat -vnL DOCKER

//输出
Chain DOCKER
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.3:80

可以看到,DOCKER中的第二条规则将宿主机的8080端口映射到IP:172.17.0.3容器的80端口。如果我们需要增加新的端口映射,只需要在DOCKER链中增加新的规则。例如我们将8443端口映射到172.17.0.3的443端口。

sudo iptables -t nat -A DOCKER -p tcp --dport 8443 -j DNAT --to-destination 172.17.0.3:443

iptables方案不用中断Docker容器的运行,但是会在每次重启后失效,即使通过service iptables save保存了当前配置,也会由于Docker服务重启时会重新分配容器地址,清空DOCKER链而失效,因此只适用于临时修改容器端口映射。

二.修改容器配置文件

容器的配置文件存储在/var/lib/docker/container/${containerId}目录下,其中containerId是容器的Id,可以通过

docker inspect ${containerName}

查看。容器的配置分别存储在hostconfig.json和config.v2.json文件中。我们可以修改两个文件中关于端口映射的配置内容,重启Docker容器实现动态添加容器端口映射。

修改容器配置文件的方法永久有效,但需要重启容器。

三.打包镜像重新运行

为了不修改容器内容,我们可以通过重新打包镜像的方式,实现端口映射添加。首先通过命令:

docker commit ${containerName} ${imageTag}

打包当前容器,然后运行${imageTag}的新容器实例,实现端口映射动态添加。

docker run -d -p 8443:443 ${imageTag}