问题描述
在使用docker-compose时,可以通过在docker-compose.yml
中设置ports
配置,例如127.0.0.1:8080:80
,将端口仅转发到容器内部的localhost
。然而,在Docker Swarm中,这种方式不适用,因为发布的端口会对外界可见。用户想知道在不将端口对外开放的情况下,如何仅从localhost
访问容器端口。尝试使用iptables
配置拒绝连接到特定端口,但由于Docker的iptables
设置,该方法无效。
解决方案
以下解决方案中的操作需要注意版本差异,可能需要备份数据。请在操作前谨慎阅读并确保理解。
使用docker_gwbridge
接口访问容器
在Docker Swarm中,可以通过容器所属的docker_gwbridge
接口访问容器。通过在容器内部运行ifconfig
命令,可以获取容器在docker_gwbridge
接口上的IP地址。以下是具体步骤:
- 进入需要访问的容器:
bash
docker exec -it <container-id> sh - 在容器内部运行
ifconfig
命令来查找docker_gwbridge
接口的IP地址:
bash
ifconfig
记下该IP地址,假设为172.18.0.2
。
这样,在主机上可以使用容器的docker_gwbridge
接口IP地址和端口号进行访问,例如172.18.0.2:5432
,从而实现仅从localhost
访问容器端口,而无需将端口对外开放。
请注意,在Docker Swarm服务中,使用docker inspect <container-id>
、docker inspect <service-name>
或docker inspect <network-id>
来查找IP地址可能不会显示出docker_gwbridge
接口的IP地址。因此,建议在容器内部使用ifconfig
来获取IP地址。
使用内部网络设置
另一种方法是使用内部网络设置来实现容器端口的访问,而无需将端口发布到外部网络。以下是具体步骤:
-
在Docker Compose或Docker Swarm的服务配置中,定义一个自定义网络:
yaml
version: '3'
services:
service_a:
image: your_image_for_service_a:latest
networks:
- internal_network
# 其他配置项
service_b:
image: your_image_for_service_b:latest
networks:
- internal_network
# 其他配置项
networks:
internal_network: -
这样,
service_a
和service_b
将加入到名为internal_network
的自定义网络中。 -
在容器内部,可以使用服务名称来访问其他服务的端口。例如,在
service_b
中可以通过service_a
的服务名和端口号来访问service_a
的端口:
bash
http://service_a:port_number
这种方式可以在Docker Swarm中实现容器之间的内部通信,而不需要将端口发布到外部网络,从而实现只从localhost
访问容器端口的需求。
使用脚本进行访问
如果以上方法不适用,你还可以考虑编写脚本来实现容器的访问控制。例如,你可以编写一个bash脚本,在容器A启动后等待其完全启动,然后再启动容器B。
以下是一个示例bash脚本,用于在容器A启动后等待并启动容器B:
#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b
在这个示例中,我们首先使用docker run
命令启动容器A,并将其命名为container_a
。然后,使用一个循环来等待容器A完全启动。一旦容器A就绪,我们再使用docker run
命令启动容器B,并将其命名为container_b
。
请注意,这种方法可能会增加复杂性,并且需要确保容器A和容器B之间的依赖关系正确设置。
总结
在Docker Swarm中访问容器/服务端口,而不将端口发布到外部网络,可以通过使用容器的docker_gwbridge
接口IP地址、内部网络设置或编写脚本来实现。根据实际情况,选择合适的方法来满足你的需求。