【问题标题】:how to link docker container to each other with docker-compose如何使用 docker-compose 将 docker 容器相互链接
【发布时间】:2015-03-27 18:23:08
【问题描述】:

我必须使用 docker-compose 设置一个 mongo 副本集。对于副本集,容器必须相互了解。

我试过docker-compose.yml

    dbreplicasetpart1:
      image: mongo:2.6.8
      expose:
        - '27018'
      links:
        - replicasetpart2
        - replicasetpart3
      cap_add:
        - NET_ADMIN

    dbreplicasetpart2:
      image: mongo:2.6.8
      links:
        - replicasetpart1
        - replicasetpart3
      expose:
        - '27019'
      cap_add:
        - NET_ADMIN
...

我收到一条循环导入消息。但是,如果我删除到 dbreplicasetpart1 的反向链接,我就无法从 dbreplicasetpart2 ping 到 dbreplicasetpart1。 解决办法是什么?

【问题讨论】:

  • 这里的所有答案都早于 Docker 1.9 中引入的新 Docker Networking。你现在要做的是首先创建一个网络并将其传递给 docker-compose up。我将在下面添加一个示例作为答案。

标签: docker docker-compose


【解决方案1】:

已针对 Docker 1.10 更新

Docker 1.10 允许在 compose 文件中定义网络。 这是更新的代码

version: "2"

services:
  replica1:
    image: mongo:2.6.8
    container_name: replica1
    networks:
      - my-net
    ports:
      - "27018"
    environment:
      REPLICA2_URL: "http://replica2:27019"
  replica2:
    image: mongo:2.6.8
    container_name: replica2
    networks:
      - my-net
    ports:
      - "27019"
    environment:
      REPLICA1_URL: "http://replica1:27018"

networks:
  my-net:
    driver: bridge

Docker 1.9 的先前答案

从 Docker 1.9 开始,解决方案是创建一个自定义网络并将其传递给 docker-compose up 命令。

  1. 创建网络 docker network create --driver bridge my-net

  2. 在 docker-compose.yml 文件中将该网络作为环境变量 (${NETWORK}) 引用。例如:

```

replica1:
  image: mongo:2.6.8
  container_name: replica1
  net: ${NETWORK}
  ports:
    - "27018"
  environment:
    REPLICA2_URL: "http://replica2:27019"

replica2:
  image: mongo:2.6.8
  container_name: replica2
  net: ${NETWORK}
  ports:
    - "27019"
  environment:
    REPLICA1_URL: "http://replica1:27018"

```

注意http://replica1:27018 中的replica1 将解析为replica1 服务(容器)的IP 地址。无需硬编码 IP 地址;副本 1 的条目会自动添加到副本 2 容器的 /etc/host 中。 replica1 容器也是如此。 Docker 会在它的 /etc/host 文件中为 replica2 添加一个条目。

  1. 调用 docker-compose,将您创建的网络传递给它 NETWORK=my-net docker-compose up -d -f docker-compose.yml

我在上面创建了一个bridge network,它只能在一个节点(主机)内工作。对开发人员有好处。如果您需要让两个节点相互通信,您需要创建一个 overlay network。不过原理一样。您将网络名称传递给 docker-compose up 命令。

【讨论】:

  • 由于 Docker 1.9 的变化,这是更好的解决方案。因此,恕我直言,这应该是公认的答案。
  • 试图让同样的东西为 mysql 工作,已经尝试了上面的方法,也许我错过了一些东西,无法让它工作。如果您能看一看,将不胜感激:stackoverflow.com/questions/49059109/…
【解决方案2】:

你应该使用大使模式:

https://docs.docker.com/engine/admin/ambassador_pattern_linking/

基本上,您创建了一个将它们连接在一起的中间组件。您可以看到我们与 Spring Cloud 的 Eureka 发现服务一起使用的示例:

ambassador:
  image: cpuguy83/docker-grand-ambassador
  volumes:
    - "/var/run/docker.sock:/var/run/docker.sock"
  command: "-name eureka_1 -name eureka2_1 "

eureka:
  links:
    - "ambassador:eureka2"

eureka2:
  links:
    - "ambassador:eureka"

为简单起见,我只复制了链接

【讨论】:

  • 使用像你这样的配置我得到了这个错误:ambassador_1 | time="2015-03-30T11:34:06Z" level=info msg="Error creating proxy for %s %s:%s - %vdockerfoo_dbreplicasetpart1_1172.17.0.17927017listen tcp 0.0.0.0:27017: bind: address already in use" ambassador_1 | time="2015-03-30T11:34:06Z" level=info msg="Error creating proxies for container dockerfoo_dbreplicasetpart1_1"
  • 你能把你的配置发给大使吗?下面的 hack 并不是最好的方法,因为 IP 地址可能会在不同的环境中发生变化。
  • Miguel,我们想出使用您的大使解决方案,请在下面的答案中查看我的配置。
  • 在 docker-compose 环境中,您必须调整 docker-grand-ambassador 的 -name 参数,例如 @MichaelK。下面的解决方案显示:__1,见docs.docker.com/compose/reference/overview和-p标志docs.docker.com/compose/reference/docker-compose
  • 请勿将此方法用于 >=Docker 1.10 看看桥接网络答案
【解决方案3】:

不更新docker-compose.yml文件,

docker network connect docker-compose-network-you-want-to-connect conatianer-name-from-another-docker-compose

更多here

【讨论】:

    【解决方案4】:

    我们想出了与大使一起使用的解决方案。这确实是更舒适的解决方案。 适合我们的配置:

    amba1:
      image: cpuguy83/docker-grand-ambassador
      volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
      command: "-name cucumber_dbreplicasetpart1_1"
    
    amba2:
      image: cpuguy83/docker-grand-ambassador
      volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
      command: "-name cucumber_dbreplicasetpart2_1"
    
    amba3:
      image: cpuguy83/docker-grand-ambassador
      volumes:
        - "/var/run/docker.sock:/var/run/docker.sock"
      command: "-name cucumber_dbreplicasetpart3_1"
    
    dbreplicasetpart1:
      image: 'mongo:2.6.8'
      hostname: dbreplicasetpart1
      command: >
        bash -c
        '
          mongod --fork --logpath mongo.log --smallfiles --replSet rs1
          echo "
            printjson(
              rs.initiate(
                {
                  _id : \"rs1\",
                  members : [
                    {_id : 0, host : \"dbreplicasetpart1:27017\"},
                    {_id : 1, host : \"dbreplicasetpart2:27017\"},
                    {_id : 2, host : \"dbreplicasetpart3:27017\"},
                  ]
                }
              )
            );
          " | mongo;
          tail -f mongo.log
        '
      links:
        - "amba2:dbreplicasetpart2"
        - "amba3:dbreplicasetpart3"
    
    dbreplicasetpart2:
      image: 'mongo:2.6.8'
      hostname: dbreplicasetpart2
      command: >
        bash -c
        '
          mongod --fork --logpath mongo.log --smallfiles --replSet rs1
          echo "
            printjson(
              rs.initiate(
                {
                  _id : \"rs1\",
                  members : [
                    {_id : 0, host : \"dbreplicasetpart1:27017\"},
                    {_id : 1, host : \"dbreplicasetpart2:27017\"},
                    {_id : 2, host : \"dbreplicasetpart3:27017\"},
                  ]
                }
              )
            );
          " | mongo;
          tail -f mongo.log
        '
      links:
        - "amba1:dbreplicasetpart1"
        - "amba3:dbreplicasetpart3"
    
    dbreplicasetpart3:
      image: 'mongo:2.6.8'
      hostname: dbreplicasetpart3
      command: >
        bash -c
        '
          mongod --fork --logpath mongo.log --smallfiles --replSet rs1
          echo "
            printjson(
              rs.initiate(
                {
                  _id : \"rs1\",
                  members : [
                    {_id : 0, host : \"dbreplicasetpart1:27017\"},
                    {_id : 1, host : \"dbreplicasetpart2:27017\"},
                    {_id : 2, host : \"dbreplicasetpart3:27017\"},
                  ]
                }
              )
            );
          " | mongo;
          tail -f mongo.log
        '
      links:
        - "amba1:dbreplicasetpart1"
        - "amba2:dbreplicasetpart2"
    

    【讨论】:

      【解决方案5】:

      以下是在 Docker 1.7.1 中仍然可以使用的内容(以防您坚持使用 CentOS 6):

      etcd:
        image: elcolio/etcd:latest
      skydns:
        image: outrider/skydns
        links:
          - etcd
        environment:
          ETCD_MACHINES: "http://etcd:4001"
          SKYDNS_DOMAIN: "docker"
          SKYDNS_PATH_PREFIX: my
          SKYDNS_NDOTS: 0
          SKYDNS_VERBOSE: "true"
          SKYDNS_ADDR: 0.0.0.0:53
        expose:
          - 53
      
      my-service:
          image: alpine
          command: sh -c "dns_add my-service && ping my-service"
          links:
            - etcd
            - skydns
      

      dns_add脚本:

      #!/usr/bin/env sh
      
      # This script configures resov.conf to use
      # "skydns" name server with "docker" domain
      # and adds a service name specified in the first argument
      SERVICE_NAME=$1
      
      waitforit () {
        HOST=$1
        PORT=$2
        TIME_OUT=${3:-30};
        END=$(($(date "+%s+$TIME_OUT")))
        while [ $(date "+%s") -lt $END ]
          do nc -z -w1 $HOST $PORT && break
        done
        return $END
      }
      
      # Use skydns to resolve names
      echo "nameserver `resolveip -s skydns`" > /etc/resolv.conf
      echo "search docker" >> /etc/resolv.conf
      
      # Put yourself to DNS
      ETCD_HOST=etcd
      ETCD_PORT=4001
      waitforit $ETCD_HOST $ETCD_PORT
      HOST_IP=`resolveip -s $HOSTNAME`
      apk update && apk add curl
      curl -XPUT http://$ETCD_HOST:$ETCD_PORT/v2/keys/my/docker/$SERVICE_NAME -d value="{\"host\":\"$HOST_IP\"}"
      

      这里有一个解释:

      1. 我们在容器中设置了自己的 DNS 服务器
      2. 我们将容器配置为使用该服务器
      3. 我们使用特殊的 HTTP 请求配置 DNS 服务器

      【讨论】:

        猜你喜欢
        • 2016-01-06
        • 1970-01-01
        • 2018-02-11
        • 1970-01-01
        • 2017-09-02
        • 2023-03-09
        • 2022-11-13
        • 1970-01-01
        • 2016-04-16
        相关资源
        最近更新 更多