получить докерский контейнер Python для взаимодействия с докерским контейнером Redis - PullRequest
0 голосов
/ 11 января 2019

Я новичок в докере, Redis и любых других сетях (я знаю Python по крайней мере!). Сначала я понял, как получить образ докера redis и запустить его в контейнере докера:

docker run --name some-redis -d redis

Насколько я понимаю, этот экземпляр Redis имеет порт 6379 для подключения к другим контейнерам.

docker network inspect bridge

   "Containers": {
        "2ecceba2756abf20d5396078fd9b2ecf0d60ab04ca6b8df5e1b631b6fb5e9a85": {
            "Name": "some-redis",
            "EndpointID": "09f0069dae3632a2456cb4d82ad5e7c9782a2b58cb7a4ee655f57b5c410c3e87",
            "MacAddress": "02:42:ac:11:00:02",
            "IPv4Address": "172.17.0.2/16",
            "IPv6Address": ""
        }

Если я запускаю следующую команду, я могу взаимодействовать с экземпляром redis и генерировать пары ключ: значение:

docker run -it --link some-redis:redis --rm redis redis-cli -h redis -p 6379
set 'a' 'abc'
>OK
get 'a'
>"abc"
quit

Я выяснил, как создать и запустить Docker-контейнер с установленной библиотекой Redis, которая будет запускать скрипт Python, следующим образом:

Вот мой Dockerfile:

FROM python:3
ADD redis_test_script.py /
RUN pip install redis 
CMD [ "python", "./redis_test_script.py" ]

Вот redis_test_script.py:

import redis
print("hello redis-py")

Создание образа докера:

docker build -t python-redis-py .

Если я запускаю следующую команду, скрипт запускается в своем контейнере:

docker run -it --rm --name pyRed python-redis-py

и возвращает ожидаемое:

>hello redis-py

Кажется, что оба контейнера работают нормально, проблема в том, чтобы соединить их вместе, я хотел бы в конечном итоге использовать python для выполнения операций над контейнером redis. Если я изменю сценарий следующим образом и пересоберу образ для контейнера python, произойдет сбой:

import redis
print("hello redis-py")
r = redis.Redis(host="localhost", port=6379, db=0)
r.set('z', 'xyz')
r.get('z')

Я получаю несколько ошибок:

...
OSError: [Errno 99] Cannot assign requested address
...
redis.exceptions.ConnectionError: Error 99 connecting to localhost:6379. Cannot assign requested address.
.....

Похоже, что они не соединяются, я попытался еще раз, используя IP-адрес моста в скрипте python:

r = redis.Redis(host="172.17.0.0/16", port=6379, db=0)

и получите эту ошибку:

redis.exceptions.ConnectionError: Error -2 connecting to 172.17.0.0/16:6379. Name or service not known.

и я попробовал IP-адрес subis:

r = redis.Redis(host="172.17.0.2/16", port=6379, db=0)

и я получаю эту ошибку:

redis.exceptions.ConnectionError: Error -2 connecting to 172.17.0.2/16:6379. Name or service not known.

Такое ощущение, что я в корне неправильно понимаю что-то о том, как заставить контейнеры общаться друг с другом. Я прочитал довольно много документации и учебных пособий, но, как я уже сказал, не имею опыта работы в сети и ранее не использовал Docker, поэтому любые полезные объяснения и / или решения были бы действительно полезны.

Большое спасибо

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Do:

  • Явно создайте сеть Docker для своего приложения и запустите контейнеры, подключенные к этой сети. (Если вы используете Docker Compose, это происходит автоматически, и вам не нужно ничего делать.)

    docker network create foo
    docker run -d --net foo --name some-redis redis
    docker run -it --rm --net foo --name pyRed python-redis-py
    
  • Используйте контейнеры ’--name в качестве имен хостов DNS: вы подключаетесь к some-redis:6379 для доступа к контейнеру. (В Docker Compose имя сервисного блока тоже работает.)

  • Сделать расположение внешних служб настраиваемым, скорее всего, с помощью переменной среды. В вашем коде Python вы можете подключиться к

    redis.Redis(host=os.environ.get("REDIS_HOST", "localhost"),
                port=int(os.environ.get("REDIS_PORT", "6379"))
    
    docker run --rm -it \
      --name py-red \
      --net foo \
      -e REDIS_HOST=some-redis \
      python-redis-py
    

Не

  • docker inspect что-нибудь, чтобы найти частные IP-адреса контейнера. Между контейнерами вы всегда можете использовать имена хостов, как описано выше. Частные IP-адреса контейнера недоступны с других хостов и даже могут быть недоступны с тех же хостов на некоторых платформах.

  • Используйте localhost в Docker для всего, ожидайте особого случая подключения из браузера или другого процесса, выполняющего напрямую на хосте (не в контейнере), к порту, который вы используете опубликовано с docker run -p на том же хосте. (Обычно это означает «этот контейнер».)

  • Имена хостов в вашем коде должны быть такими: усложняет запуск службы в другой среде. (В частности, для баз данных нередко запускать их вне Docker или даже в размещенной облачной службе.)

  • Используйте --link, оно устарело и не нужно.

0 голосов
/ 11 января 2019

Это все о Docker-сетях. Быстрое решение - используйте сетевой режим host для обоих контейнеров. Недостаток - низкая изоляция, но вы быстро заработаете:

docker run -d --network=host redis ...
docker run --network=host python-redis-py ...

Затем для подключения от python к redis просто используйте localhost в качестве имени хоста.

Лучшее решение - использовать пользовательскую мостовую сеть Docker

# create network
docker network create foo
docker run -d --network=foo --name my-db redis ...
docker run    --network=foo python-redis-py ...

Обратите внимание, что в этом случае вы не можете использовать localhost, а вместо этого использовать my-db в качестве имени хоста. Вот почему я использовал параметр --name my-db при запуске первого контейнера. В пользовательских мостовых сетях контейнеры достигают друг друга по именам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...