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

时间:2015-03-27 18:23:09

标签: docker docker-compose

我必须使用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。 解决方案是什么?

5 个答案:

答案 0 :(得分:41)

针对Docker 1.10进行了更新

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

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})。例如:

  3. ```

    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"
    

    ```

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

    1. 调用docker-compose,将其传递给您创建的网络 NETWORK=my-net docker-compose up -d -f docker-compose.yml
    2. 我已经创建了一个 bridge network ,只能在一个节点(主机)中运行。对开发者有好处。如果您需要让两个节点相互通信,则需要创建 overlay network 。同样的原则。您将网络名称传递给docker-compose up命令。

答案 1 :(得分:14)

你应该使用大使模式:

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"

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

答案 2 :(得分:0)

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

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"

答案 3 :(得分:0)

不更新docker-compose.yml文件

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

更多here

答案 4 :(得分:-1)

以下是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服务器