繁体   English   中英

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

[英]how to link docker container to each other with 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。 解决办法是什么?

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

``

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"

``

需要注意的是replica1http://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传递给它NETWORK=my-net docker-compose up -d -f docker-compose.yml

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

您应该使用大使模式:

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"

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

无需更新docker-compose.yml文件,

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

更多在这里

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

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.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 服务器

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM