持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情
现象
在公司部署某新的重构项目时按照原有部署文档部署时,我们将 mysql,engine等容器的端口使用bridge模式映射到宿主机上。
docker run --name mysql --restart always -p 3306:3306 --log-opt max-size=500m
-v $PWD/mysql/datadir:/var/lib/mysql
-v $PWD/mysql/logs:/log
-e MYSQL_ROOT_PASSWORD=XXXXXX
-e MYSQL_DATABASE=ctu
-e MYSQL_USER=ctu
-e MYSQL_PASSWORD=XXXXXX
-d xxx.xxx.top/basic/mysql:5.7.22-dx
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
docker run --restart always --name engine -p 7090:7090 --log-opt max-size=500m
-v $PWD/logs/xxx:/home/admin/logs --log-opt max-size=1000m
-v $PWD/web/xxx/application.properties:/home/admin/application.properties
-d xxx.xxx-xxx.top/xxx/xxx-xxx:feature_xxx
这样,外部就能通过访问宿主机的对应端口直接访问容器内提供的服务。
然而在项目启动后,发现console项目启动失败,日志打印无法连接到mysql数据库。
首先考虑应用容器网络问题,进入容器内,ping宿主机IP进行测试
结果没有问题,容器到宿主机的网络可达。
接下来查看mysql容器提供的服务是否有问题,由于容器内软件条件不够。本地尝试连接数据库。
数据库服务正常可用。外部可进行访问。
至此暂无其他思路。
临时解决方案
在看完之前项目提供的完整的部署文档后,发现在文档最后有这么一段
常见问题
-- 在redis容器中, 命令redis-trib.rb create 出现无法创建集群的问题
Creating cluster
[ERR] Sorry, can't connect to node XXXX:port
原因: 防火墙中未开放端口, 通过iptables或者firewall-cmd开放, 建议此种情况下建议关闭防火墙, 然后应用启动参数使用--net host去掉-p映射
$ sudo service iptables stop(iptables) 或$ sudo service firewalld stop(firewalld)
当然也可以开放所有端口, 这样可以使用-p参数
firewall-cmd --permanent --zone=public --add-port=80-65535/tcp
firewall-cmd --permanent --zone=public --add-port=80-65535/udp
firewall-cmd --reload
iptables -I INPUT -p tcp --dport 80:65535 -j ACCEPT
iptables -I INPUT -p udp --dport 80:65535 -j ACCEPT
service iptables save
service iptables restart
常见异常No route to host, 也是防火墙引起的, 原因与处理方法同上
根源问题还是出在了防火墙上,开放端口后容器间可正常进行服务访问。但是这种做法对外暴露了过多的端口,几乎所有的中间件,内部服务端口全部对外网开放,于系统而言不是一个安全的做法。
思考
- iptables和docker的机制是如何导致在防护墙未开放端口的情况下,外部连接可直接访问服务,而宿主机中的其他容器无法访问
- 如何更好的利用docker的网络模式部署一个安全的集群(只对外网开发服务需要的端口,可结合nginx使用