Подтвердить что ты не робот

Как связать контейнер докеров друг с другом с помощью докеров

Мне нужно настроить набор реплик mongo с помощью docker-compose. Для набора реплик контейнеры должны знать друг друга.

Я пробовал в 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, я не могу выполнить ping из dbreplicasetpart2 в dbreplicasetpart1. Каково решение?

4b9b3361

Ответ 1

Обновлено для 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.

  • Создать сеть docker network create --driver bridge my-net

  • Ссылка на эту сеть как переменную среды (${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"

`` `

Обратите внимание, что replica1 в http://replica1:27018 будет разрешено ip-адрес службы replica1 (контейнер). Нет необходимости жестко кодировать IP-адреса; Запись для replica1 автоматически добавляется в /etc/host контейнера replica2. То же самое касается контейнера replica1. Docker добавит запись для replica2 в файл /etc/host.

  1. Позвоните в docker-compose, передав ему созданную вами сеть NETWORK=my-net docker-compose up -d -f docker-compose.yml

Я создал сеть моста , которая работает только с одним node (хостом). Хорошо для dev. Если вам нужно, чтобы два узла разговаривали друг с другом, вам необходимо создать . Тем не менее, тот же принцип. Вы передаете сетевое имя команде docker-compose up.

Ответ 2

Вы должны использовать шаблон посла:

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"

Для простоты я только скопировал ссылки

Ответ 3

Мы решили использовать решение с послом. Это действительно более удобное решение. Конфигурация, которая работает для нас:

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"

Ответ 4

Здесь то, что должно по-прежнему работать в 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:

#!/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\"}"

Вот объяснение:

  • Мы создали собственный DNS-сервер в контейнере
  • Мы настраиваем наши контейнеры для использования этого сервера
  • Мы настраиваем этот DNS-сервер с использованием специальных HTTP-запросов