无法通过Docker Compose服务名连接MySQL容器的问题排查
问题分析与解决方案
你的问题出在app服务设置了network_mode: host,这直接导致容器间无法通过服务名互相访问,具体原因和解决办法如下:
核心原因
Docker Compose默认会为所有服务创建一个专属的桥接网络,服务之间可以通过服务名(比如db)进行DNS解析,实现容器间通信。但当你给app服务设置network_mode: host后,这个容器会直接使用宿主机的网络栈,完全脱离了Compose创建的专属网络。这时候app容器和db容器不在同一个网络环境里,自然无法通过db这个服务名找到对应的数据库容器。
解决方案
根据你的需求,有两种可行的解决方式:
方式一:移除network_mode: host(推荐)
这是最符合Docker Compose设计理念的方案,修改后的docker-compose.yml如下:
version: '3' services: app: build: . volumes: - .:/usr/usr/src/app db: image: mysql/mysql-server:5.7 environment: MYSQL_DATABASE: config_dev MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' volumes: - ./docker/images/config-dev-image/sql-scripts:/docker-entrypoint-initdb.d restart: always ports: - "1200:3306"
修改后重新启动服务,此时app和db处于同一个Compose网络中,你在app容器内执行mysql --hostname=db --port=3306 --user=root就能正常连接了。
方式二:保留network_mode: host(仅当你有特殊需求时使用)
如果你必须让app使用宿主机网络,那需要通过宿主机的IP来访问db服务:
- 在app容器内执行连接命令时,把主机名换成宿主机的IP(本地环境可直接用
localhost),端口用你映射的宿主机端口1200:mysql --hostname=localhost --port=1200 --user=root - 额外配置:默认情况下MySQL 5.7仅绑定
127.0.0.1,会导致宿主机无法访问容器内的MySQL。你需要修改db服务的配置,让MySQL监听所有网卡:
在docker-compose.yml的db服务中添加command参数:
这样MySQL就会监听所有可用的网络接口,宿主机(以及使用host网络的app容器)就能通过映射端口访问了。db: image: mysql/mysql-server:5.7 environment: MYSQL_DATABASE: config_dev MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' volumes: - ./docker/images/config-dev-image/sql-scripts:/docker-entrypoint-initdb.d restart: always ports: - "1200:3306" command: --bind-address=0.0.0.0
内容的提问来源于stack exchange,提问作者Vishakha Lall
相关产品推荐
相关产品推荐

