Docker Compose 容器链接

在Docker中,容器之间的连接是一种很常见的操做:它提供了访问其中的某个容器的网络服务而不须要将所需的端口暴露给Docker Host主机的功能。Docker Compose中对该特性的支持一样是很方便的。然而,若是须要连接的容器没有定义在同一个docker-compose.yml中的时候,这个时候就稍微麻烦复杂了点。nginx

在不使用Docker Compose的时候,将两个容器连接起来使用—link参数,相对来讲比较简单,以nginx镜像为例子:docker

1
2
docker run --rm --name test1 -d nginx  #开启一个实例test1
docker run --rm --name test2 --link test1 -d nginx #开启一个实例test2并与test1创建连接

这样,test2test1便创建了连接,就能够在test2中使用访问test1中的服务了。网络

若是使用Docker Compose,那么这个事情就更简单了,仍是以上面的nginx镜像为例子,编辑docker-compose.yml文件为:app

1
2
3
4
5
6
7
8
9
10
version: "3"
services:
  test2:
    image: nginx
    depends_on:
      - test1
    links:
      - test1
  test1:
    image: nginx

最终效果与使用普通的Docker命令docker run xxxx创建的连接并没有区别。这只是一种最为理想的状况。测试


  1. 若是容器没有定义在同一个docker-compose.yml文件中,应该如何连接它们呢?
  2. 又若是定义在docker-compose.yml文件中的容器须要与docker run xxx启动的容器连接,须要如何处理?

针对这两种典型的状况,下面给出我我的测试可行的办法:spa


方式一:让须要连接的容器同属一个外部网络

咱们仍是使用nginx镜像来模拟这样的一个情景:假设咱们须要将两个使用Docker Compose管理的nignx容器(test1test2)连接起来,使得test2可以访问test1中提供的服务,这里咱们以能ping通为准。code

首先,咱们定义容器test1docker-compose.yml文件内容为:get

1
2
3
4
5
6
7
8
9
10
11
version: "3"
services:
  test2:
    image: nginx
    container_name: test1
    networks:
      - default
      - app_net
networks:
  app_net:
    external: true

容器test2内容与test1基本同样,只是多了一个external_links,须要特别说明的是:最近发布的Docker版本已经不须要使用external_links来连接容器,容器的DNS服务能够正确的做出判断,所以若是你你须要兼容较老版本的Docker的话,那么容器test2docker-compose.yml文件内容为:it

1
2
3
4
5
6
7
8
9
10
11
12
13
version: "3"
services:
  test2:
    image: nginx
    networks:
      - default
      - app_net
    external_links:
      - test1
    container_name: test2
networks:
  app_net:
    external: true

不然的话,test2docker-compose.ymltest1的定义彻底一致,不须要额外多指定一个external_links。相关的问题请参见stackoverflow上的相关问题:docker-compose + external containerio

正如你看到的那样,这里两个容器的定义里都使用了同一个外部网络app_net,所以,咱们须要在启动这两个容器以前经过如下命令再建立外部网络:

1
docker network create app_net

以后,经过docker-compose up -d命令启动这两个容器,而后执行docker exec -it test2 ping test1,你将会看到以下的输出:

1
2
3
4
5
6
7
8
docker exec -it test2 ping test1
PING test1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.091 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.146 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.150 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.145 ms
64 bytes from 172.18.0.2: icmp_seq=4 ttl=64 time=0.126 ms
64 bytes from 172.18.0.2: icmp_seq=5 ttl=64 time=0.147 ms

证实这两个容器是成功连接了,反过来在test1中pingtest2也是可以正常ping通的。

若是咱们经过docker run --rm --name test3 -d nginx这种方式来先启动了一个容器(test3)而且没有指定它所属的外部网络,而须要将其与test1或者test2连接的话,这个时候手动连接外部网络便可:

1
docker network connect app_net test3

这样,三个容器均可以相互访问了。


方式二:更改须要连接的容器的网络模式

经过更改你想要相互连接的容器的网络模式为bridge,并指定须要连接的外部容器(external_links)便可。与同属外部网络的容器能够相互访问的连接方式一不一样,这种方式的访问是单向的。

仍是以nginx容器镜像为例子,若是容器实例nginx1须要访问容器实例nginx2,那么nginx2doker-compose.yml定义为:

1
2
3
4
5
6
version: "3"
services:
  nginx2:
    image: nginx
    container_name: nginx2
    network_mode: bridge

与其对应的,nginx1docker-compose.yml定义为:

1
2
3
4
5
6
7
8
version: "3"
services:
  nginx1:
    image: nginx
    external_links:
      - nginx2
    container_name: nginx1
    network_mode: bridge

须要特别说明的是,这里的external_links是不能省略的,并且nginx1的启动必需要在nginx2以后,不然可能会报找不到容器nginx2的错误。

接着咱们使用ping来测试下连通性:

1
2
3
4
5
6
7
8
$ docker exec -it nginx1 ping nginx2  # nginx1 to nginx2
PING nginx2 (172.17.0.4): 56 data bytes
64 bytes from 172.17.0.4: icmp_seq=0 ttl=64 time=0.141 ms
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.139 ms
64 bytes from 172.17.0.4: icmp_seq=2 ttl=64 time=0.145 ms

$ docker exec -it nginx2 ping nginx1 #nginx2 to nginx1
ping: unknown host

以上也能充分证实这种方式是属于单向联通的。

在实际应用中根据本身的须要灵活的选择这两种连接方式,若是想偷懒的话,大可选择第二种。不过我更推荐第一种,不难看出不管是联通性仍是灵活性,较为更改网络模式的第二种都更为友好。

相关文章
相关标签/搜索