如何使用docker-compose链接Docker容器

我必须用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 ... 

我得到一个循环导入消息。 但是,如果我删除backlink到dbreplicasetpart1,我无法从dbreplicasetpart2 ping到dbreplicasetpart1。 解决办法是什么?

更新了Docker 1.10

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

 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开始,解决scheme是创build一个自定义networking并将其传递给docker-compose up命令。

  1. 创build一个networkingdocker network create --driver bridge my-net

  2. 在docker-compose.yml文件中将networking引用为环境variables( ${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将parsing为replica1服务(容器)的ip地址。 不需要硬编码的IP地址; replica1的条目会自动添加到replica2容器的/ etc / host。 replica1容器也一样。 Docker将在/ etc / host文件中添加一个replica2条目。

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

我创build了一个只能在一个节点(主机)内工作的桥接networking 。 良好的开发。 如果您需要让两个节点相互交谈,则需要创build一个覆盖networking 。 尽pipe相同的原则。 您将networking名称传递给docker-compose up命令。

你应该使用大使模式:

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

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

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

我们计划与大使一起使用这个解决scheme。 这确实是更舒适的解决scheme。 适合我们的configuration:

 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. 我们在容器中build立了自己的DNS服务器
  2. 我们将容器configuration为使用该服务器
  3. 我们使用特殊的HTTP请求来configurationDNS服务器