单独运行Docker Compose服务时无法访问暴露端口的问题
我来帮你分析下问题所在,然后给出几个可行的解决方案:
问题根源
当你用docker-compose run --service-ports启动容器时,默认情况下这些容器不会自动加入Docker Compose项目的默认网络(也就是<你的项目名>_default这个网络)。容器之间要互相通信,必须处于同一个网络中,所以即使你能在宿主机看到端口映射,两个容器也没法通过对方的端口服务通信。
另外要注意:--service-ports只是把容器的端口映射到宿主机,方便宿主机访问容器服务,它解决的是宿主机和容器之间的通信,不是容器和容器之间的。
解决方案
方案1:启动时指定加入Compose默认网络
首先先查看你的Compose项目默认网络名称,执行:
docker network ls
你会看到一个类似your-project-name_default的网络(项目名一般是docker-compose.yml所在目录的名字)。
然后启动容器时加上--network参数指定这个网络:
# 启动django容器并加入默认网络 docker-compose run --service-ports --network your-project-name_default django /bin/bash # 启动other容器并加入默认网络 docker-compose run --service-ports --network your-project-name_default other /bin/bash
这样两个容器就处于同一个网络了,此时你可以在django容器里直接用服务名访问other的内部端口,比如访问9200端口就用other:9200,不用指定宿主机IP或者localhost。
方案2:用docker-compose up启动服务(推荐)
如果你的需求只是让服务运行,不需要进入容器的bash交互环境,直接用docker-compose up启动服务是更简单的方式:
# 后台启动django和other服务 docker-compose up -d django other
这种方式启动的容器会自动加入Compose默认网络,互相之间可以直接用服务名访问对方的内部端口。如果需要进入某个容器的bash,再用docker exec命令:
# 进入django容器 docker exec -it <django-container-id> /bin/bash # 进入other容器 docker exec -it <other-container-id> /bin/bash
容器ID可以通过docker ps查看。
方案3:配置自定义共享网络(长期维护推荐)
如果经常需要用docker-compose run启动容器并互相通信,可以在docker-compose.yml里配置一个外部共享网络:
services: django: # 你的django服务配置 image: littlehome networks: - shared-network other: # 你的other服务配置 image: littlehome_other networks: - shared-network networks: shared-network: external: true
然后先创建这个网络:
docker network create shared-network
之后再用docker-compose run启动容器时,它们会自动加入这个共享网络,互相之间直接用服务名访问即可。
关键提醒
容器之间通信时,不要用宿主机的端口映射地址(比如localhost:9200或者宿主机IP:9200),而是直接用服务名+容器内部端口(比如other:9200),这是Docker容器间通信的正确方式。
内容的提问来源于stack exchange,提问作者eugene

