如何使用docker compose将docker容器相互链接

如何使用docker compose将docker容器相互链接,docker,docker-compose,Docker,Docker Compose,我必须用docker compose设置mongo副本集。对于副本集,容器必须相互了解 我在docker compose.yml中尝试了 dbreplicasetpart1: image: mongo:2.6.8 expose: - '27018' links: - replicasetpart2 - replicasetpart3 cap_add: - NET_ADMIN

我必须用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
...
我收到一条循环导入消息。但是,如果删除指向DBReplicateSetPart1的反向链接,则无法从DBReplicateSetPart2 ping到DBReplicateSetPart1。
解决方案是什么?

您应该使用大使模式:

基本上,您可以创建一个中间组件,将这两个组件连接在一起。您可以看到我们在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"

为了简单起见,我只复制了我们想出的使用大使解决方案的链接。这确实是一个更舒适的解决方案。 适用于我们的配置:

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"

为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
命令

  • 创建网络
    
    docker网络创建--驱动程序桥接我的网络
    

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

  • ```

    ```

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

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

  • 我在上面创建了一个只在一个节点(主机)内工作的。对开发人员来说很好。如果需要让两个节点相互通信,则需要创建一个。但原则是一样的。您将网络名称传递给docker compose up命令。

    以下是docker 1.7.1中仍应使用的内容(如果您坚持使用CentOS 6):

    dns\u添加
    脚本:

    #!/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\"}"
    
    这里有一个解释:

  • 我们在一个容器中设置了自己的DNS服务器
  • 我们将容器配置为使用该服务器
  • 我们使用特殊的HTTP请求配置DNS服务器

  • 不更新
    docker compose.yml
    文件

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

    更多

    像您这样的配置,我遇到了以下错误:
    ambassador|1 | time=“2015-03-30T11:34:06Z”level=info msg=“为%s%s创建代理时出错:%s-%vdockerfoo_dbreplicasetpart1_1172.17.0.0.17927017:绑定:地址已在使用”ambassador|time=“2015-03-30T11:34:06Z”level=info msg=“为容器dockerfoo\u dbreplicasetpart1\u创建代理时出错”“
    你能把你的配置文件发给大使吗?下面的黑客攻击不是最好的方法,因为IP地址可能会在不同的环境中发生变化。Miguel,我们找到了使用大使解决方案的方法,请参见下面答案中的我的配置。在docker compose环境中,您必须调整docker grand ambassador的-name参数,如@MichaelK。下面的解决方案显示:_1,see和-p标志不使用此方法>=Docker 1.10查看桥接网络答案这里的所有答案都早于Docker 1.9中引入的新Docker网络。您现在要做的是首先创建一个网络并将其传递给docker compose up。我将在下面添加一个示例作为答案。由于Docker 1.9中的更改,这是一个更好的解决方案。因此,这应该是一个被接受的答案,试图让同样的东西为mysql工作,已经尝试了上面的方法,也许我遗漏了一些东西,无法让它工作。如果您能看一下,我将不胜感激:
    #!/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\"}"
    
    docker network connect docker-compose-network-you-want-to-connect conatianer-name-from-another-docker-compose