29

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

4

5 回答 5

44

针对 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. ${NETWORK}在 docker-compose.yml 文件中将该网络作为环境变量 ( ) 引用。例如:

```

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"

```

请注意,replica1inhttp://replica1:27018将解析为 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

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

于 2015-12-27T01:18:24.287 回答
13

您应该使用大使模式:

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"

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

于 2015-03-30T09:15:31.343 回答
1

在不更新docker-compose.yml文件的情况下,

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

更多在这里

于 2019-02-12T05:12:13.267 回答
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"
于 2015-04-13T08:33:14.990 回答
0

以下是在 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-10-13T07:22:28.607 回答