[英]how to link docker container to each other with docker-compose
I have to setup a mongo replica set with docker-compose.我必须使用 docker-compose 设置一个 mongo 副本集。 For the replica set the containers have to know each other.
对于副本集,容器必须相互了解。
I tried in docker-compose.yml
我在
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
...
I get an circular import message.我收到一条循环导入消息。 But if I remove the back-link to dbreplicasetpart1 I can't ping from dbreplicasetpart2 to dbreplicasetpart1.
但是,如果我删除到 dbreplicasetpart1 的反向链接,我将无法从 dbreplicasetpart2 ping 到 dbreplicasetpart1。 What is the solution?
解决办法是什么?
Updated for Docker 1.10为 Docker 1.10 更新
Docker 1.10 allows the definition of networks within the compose file. Docker 1.10 允许在撰写文件中定义网络。 Here's the updated code
这是更新后的代码
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
Previous answer for Docker 1.9 Docker 1.9 的上一个答案
As of Docker 1.9, the solution to this is to create a custom network and pass it to the docker-compose up
command.从 Docker 1.9 开始,解决方案是创建一个自定义网络并将其传递给
docker-compose up
命令。
Create a network docker network create --driver bridge my-net
创建网络
docker network create --driver bridge my-net
Reference that network as an environment variable ( ${NETWORK}
)in the docker-compose.yml files.在 docker-compose.yml 文件中将该网络作为环境变量 (
${NETWORK}
) 引用。 Eg:例如:
``` ``
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"
``` ``
Note that replica1
in http://replica1:27018
will resolve to the ip address of the replica1 service (container).需要注意的是
replica1
在http://replica1:27018
解析到replica1服务(容器)的IP地址。 No need to hardcode ip addresses;无需硬编码 IP 地址; An entry for replica1 is automatically added to the /etc/host of the replica2 container.
replica1 的条目会自动添加到 replica2 容器的 /etc/host 中。 Same goes for the replica1 container.
replica1 容器也是如此。 Docker will add an entry for replica2 in its /etc/host file.
Docker 将在其 /etc/host 文件中为 replica2 添加一个条目。
NETWORK=my-net docker-compose up -d -f docker-compose.yml
NETWORK=my-net docker-compose up -d -f docker-compose.yml
传递给它NETWORK=my-net docker-compose up -d -f docker-compose.yml
I've created a bridge network above which only works within one node (host).我在上面创建了一个桥接网络,它只能在一个节点(主机)内工作。 Good for dev.
对开发有好处。 If you need to get two nodes to talk to each other, you need to create an overlay network .
如果您需要让两个节点相互通信,则需要创建一个覆盖网络。 Same principle though.
不过原理一样。 You pass the network name to the docker-compose up command.
您将网络名称传递给 docker-compose up 命令。
You should use the ambassador pattern:您应该使用大使模式:
https://docs.docker.com/engine/admin/ambassador_pattern_linking/ https://docs.docker.com/engine/admin/ambassador_pattern_linking/
Basically you create an intermediate component that bridges both of them together.基本上,您创建了一个将它们连接在一起的中间组件。 You can see an example that we use with Spring Cloud's Eureka discovery service:
您可以看到我们与 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"
For simplicity, I only copied the links为简单起见,我只复制了链接
We figured out to use the solution with the ambassador.我们想出了与大使一起使用的解决方案。 It is indeed the more comfortable solution.
这确实是更舒适的解决方案。 The configuration that works for us:
对我们有用的配置:
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"
Here's what should still work in Docker 1.7.1 (in case you stuck with CentOS 6):以下是在 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
script: 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\"}"
Here's an explanation:这是一个解释:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.