docker 服务如何设法从单独的 docker 容器中调用实例?

How did the docker service manage to call instance from a seperate docker container?

我最近开始使用 Docker+Celery。我还分享了 full sample codes for this example on github,以下是其中的一些代码片段,以帮助解释我的观点。

就上下文而言,我的示例被设计为订阅微服务系统中事件的节点。在这个节点中,它包含以下服务:

  1. 订阅者(使用kombu订阅事件)
  2. Worker(将 celery 用于处理事件的异步任务)
  3. Redis(作为 celery 的消息代理和结果后端)

服务在 docker-compose.yml 文件中定义如下:

version: "3.7"
services:
    # To launch the Subscriber (using Kombu incl. in Celery)
    subscriber:
        build: .
        tty: true
        #entrypoint: ...

    # To launch Worker (Celery)
    worker:
        build: .
        entrypoint: celery worker -A worker.celery_app --loglevel=info
        depends_on: 
            - redis

    redis: 
        image: redis
        ports: 
            - 6379:6379
        entrypoint: redis-server

为简单起见,我省略了 subscriber 的代码,我想在 subscriber 中使用 python 交互式 shell这个例子的容器应该足够了:

python3
>>> from worker import add
>>> add.delay(2,3).get()
5

并且在 worker 容器 日志中:

worker_1      | [2020-09-17 10:12:34,907: INFO/ForkPoolWorker-2] worker.add[573cff6c-f989-4d06-b652-96ae58d0a45a]: Adding 2 + 3, res: 5
worker_1      | [2020-09-17 10:12:34,919: INFO/ForkPoolWorker-2] Task worker.add[573cff6c-f989-4d06-b652-96ae58d0a45a] succeeded in 0.011764664999645902s: 5

虽然一切似乎都很顺利,但我还是感到不安。我认为这个例子不遵守 docker 容器的隔离原则。

Aren't containers designed to be isolated to the level of it's OS, processes and network? And if containers have to communicate, shouldn't it be done via IP address and network protocols (TCP/UDP etc.)

首先,workersubscriber 运行 在我的示例中是相同的代码库,因此预计不会出现问题导入语句。

但是,celery worker 是从 worker 容器 中的 entrypoint 启动的,因此,subscriber设法在假定隔离的 worker 容器?

中调用 celery worker 实例

为了进一步验证它实际上是从 worker 容器 调用 celery worker 实例,我停止了 worker 容器 并重复python 交互式 shell 示例在 订阅者容器 中。请求等待(这是 celery 的预期)并在工作容器再次打开后立即返回相同的结果。所以 IMO,是的,来自一个容器的服务正在从另一个容器调用应用程序实例,而无需联网,就像连接到 Redis 的情况(使用 IP 地址等)一样。

如果我的理解不正确或者我不知道的地方可能有错误的实现,请告知。

消费者(工作者)和生产者(订阅者)都配置为使用 Redis(redis)作为代理和结果后端。这就是为什么一切都奏效了。 - 当您在订阅者容器中执行 add.delay(2,3).get() 时,它会将任务发送到 Redis,并由另一个容器中的 Celery worker 运行 选取。 请记住,Python 进程 运行 add.delay(2,3).get() 代码在订阅者容器中是 运行,而执行 add() 函数并存储的 ForkPoolWorker-2 进程结果后端中的结果是工作容器中的 运行 。这些进程是完全独立的。

订户进程没有调用工作容器中的任何东西! - 用简单的英语来说它所做的是:“这里(在 Redis 中)是我需要做的,请工作人员去做,让我知道你已经完成了,这样我就可以获取结果”。

Docker-compose 为在单个文件中创建的容器创建默认 docker 网络。由于您正确地指向所有内容,它正在沿着该网络发出请求,这就是成功的原因。如果您不使用 docker-compose.

分别并行地 运行 每个容器,我会很惊讶地听到这仍然有效