Py学习  »  Redis

获取python docker容器以与redis docker容器交互

user3062260 • 5 年前 • 1838 次点击  

我对Docker、Redis和任何类型的网络都不熟悉(至少我了解Python!)。首先,我了解了如何获取Redis Docker映像并在Docker容器中运行它:

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实例交互并生成key:value对:

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

我已经了解了如何在安装了Redis库的情况下创建和运行Docker容器,该库将运行python脚本,如下所示:

这是我的文件:

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图像:

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.
.....

看起来他们没有连接,我在python脚本中再次尝试使用bridge ip:

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.

我尝试了Redis子IP:

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,所以任何有用的解释和/或解决方案都会非常棒。

多谢

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/30844
 
1838 次点击  
文章 [ 2 ]  |  最新文章 5 年前
David Maze
Reply   •   1 楼
David Maze    5 年前

做:

  • 显式地为应用程序创建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中,服务块的名称也可以组成。)

  • 使外部服务的位置可配置,最有可能使用环境变量。在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 它已经过时了,而且是不必要的。

grapes
Reply   •   2 楼
grapes    5 年前

这就是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 ...

注意在这种情况下你 不能 使用 本地服务器 而是使用 my-db 作为主机名。所以我才用 --name my-db 启动第一个容器时的参数。在用户定义的桥接网络中,容器通过它们的名称相互连接。