Docker容器间通信是很常见的操作,它允许一个容器使用另一个容器提供的服务。本文主要介绍的是多个容器在同一个Docker主机进行通信的方式。
myapp/docker-compose.yml
version: '3.8'
services:
app:
container_name: docker-node-mongo
restart: always
build: . # 在当前目录下查找 Dockerfile 构建容器
ports:
- '8080:3000'
depends_on:
- mongodb
mongodb:
container_name: mongo
image: mongo
ports:
- '27015:27017'
运行docker-compose up
之后,将会发生以下事情
- 创建名为
myapp_default
的网络,myapp
是docker-compose.yml
所在的目录 - 创建
docker-node-mongo
容器,并加入到myapp_default
网络 - 创建
mongo
容器,并加入到myapp_default
网络
每个容器可以通过主机名(hostname)docker-node-mongo
和mongo
查找对应容器的ip地址,如docker-node-mongo
容器的代码中可以通过mongodb://mongo:27017/docker-node-mongo
连接到Mongo数据库。
这里注意区分HOST_PORT
和CONTAINER_PORT
,对于mongodb
,CONTAINER_PORT
为27017,它是服务间通信的端口,HOST_PORT
为27015,它是外部访问mongo服务的端口。
depends_on
用于建立服务间的依赖关系,但是仅仅是按顺序启动,并不能保证此时数据库已就绪
,可以参考这篇文章了解解决方案
如果两个服务并不是定义在同一个yml文件中,这种直接通信方式就失效了,这里提供两种解决方式。
- 方式一:让需要通信的服务处于同一个外部网络
创建网络
docker network create app_net
docker-node-mongo/docker-compose.yml
version: '3'
services:
app:
container_name: docker-node-mongo
restart: always
build: .
image: docker-node-mongo:1.0.1
ports:
- '8550:3000'
networks:
- default
- app_net
networks:
app_net:
external: true
mongo/docker-compose.yml
version: '3'
services:
mongodb:
container_name: mongo
image: mongo
ports:
- '27017:27017'
volumes:
- /opt/docker_mongo/data/db:/data/db
networks:
- default
- app_net
networks:
app_net:
external: true
这样两个服务都使用了同一个外部网络app_net
,也就可以正常通信了。使用docker exec -it docker-test ping mongo
查看容器间是否连通。
docker exec -it docker-test ping mongo
PING mongo (172.28.0.2) 56(84) bytes of data.
64 bytes from mongo.app_net (172.28.0.2): icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from mongo.app_net (172.28.0.2): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from mongo.app_net (172.28.0.2): icmp_seq=3 ttl=64 time=0.053 ms
64 bytes from mongo.app_net (172.28.0.2): icmp_seq=4 ttl=64 time=0.061 ms
64 bytes from mongo.app_net (172.28.0.2): icmp_seq=5 ttl=64 time=0.060 ms
^C
--- mongo ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4104ms
- 方式二:更改需要通信的服务的网络模式
mongo/docker-compose.yml
version: '3'
services:
mongodb:
container_name: mongo
image: mongo
ports:
- '27017:27017'
volumes:
- /opt/docker_mongo/data/db:/data/db
network_mode: bridge
docker-test/docker-compose.yml
version: '3'
services:
app:
container_name: docker-test
restart: always
build: .
image: docker-test:1.0
ports:
- '8150:4000'
network_mode: bridge
external_links:
- mongo
通过修改network_mode
为bridge
,并且指定external_links
为另一个容器的container_name
,可以实现docker-test
到mongo
的单向通信。