Python Celery 试图在 docker-compose 中占用一个端口号并产生问题

Python Celery trying to occupy a port number in docker-compose and creating problems

docker-compose.yml:

  python-api: &python-api
    build:
      context: /Users/AjayB/Desktop/python-api/
    ports:
      - "8000:8000"
    networks:
      - app-tier
    expose:
      - "8000"
    depends_on:
      - python-model
    volumes:
      - .:/python_api/
    environment:
      - PYTHON_API_ENV=development
    command: >
      sh -c "ls /python-api/ &&
             python_api_setup.sh development
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"

  python-model: &python-model
    build:
      context: /Users/AjayB/Desktop/Python/python/
    ports:
      - "8001:8001"
    networks:
      - app-tier
    environment:
      - PYTHON_API_ENV=development
    expose:
      - "8001"
    volumes:
      - .:/python_model/
    command: >
      sh -c "ls /python-model/
             python_setup.sh development
             cd /server/ &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8001"

  python-celery:
    <<: *python-api
    environment:
      - PYTHON_API_ENV=development
    networks:
      - app-tier
    links:
      - redis:redis
    depends_on:
      - redis
    command: >
      sh -c "celery -A server worker -l info"

  redis:
    image: redis:5.0.8-alpine
    hostname: redis
    networks:
          - app-tier
    expose:
      - "6379"
    ports:
      - "6379:6379"
    command: ["redis-server"]

python-celerypython-api 里面,应该 运行 作为一个单独的容器。但它试图占用与 python-api 相同的端口,这永远不会是这种情况。

我得到的错误是:

AjayB$ docker-compose up
Creating integrated_redis_1        ... done
Creating integrated_python-model_1 ... done
Creating integrated_python-api_1   ... 
Creating integrated_python-celery_1 ... error

Creating integrated_python-api_1    ... done
e1d1055165b1f85f179f69c): Bind for 0.0.0.0:8000 failed: port is already allocated

ERROR: for python-celery  Cannot start service python-celery: driver failed programming external connectivity on endpoint integrated_python-celery_1 (ab5e079dbc3a30223e16052f21744c2b5dfc56adbe1d1055165b1f85f179f69c): Bind for 0.0.0.0:8000 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.

在做 docker ps -a 时,我明白了:

AjayB$ docker ps -a
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS                      PORTS                    NAMES
2ff1277fb7a7        integrated_python-celery   "sh -c 'celery -A se…"   10 seconds ago      Created                                              integrated_python-celery_1
5b60221b42a4        integrated_python-api      "sh -c 'ls /crackd-a…"   11 seconds ago      Up 9 seconds                0.0.0.0:8000->8000/tcp   integrated_python-api_1
bacd8aa3268f        integrated_python-model    "sh -c 'ls /crackd-m…"   12 seconds ago      Exited (2) 10 seconds ago                            integrated_python-model_1
9fdab833b436        redis:5.0.8-alpine         "docker-entrypoint.s…"   12 seconds ago      Up 10 seconds               0.0.0.0:6379->6379/tcp   integrated_redis_1

尝试强制删除容器并尝试 docker-compose up 得到同样的错误。 :/我在哪里犯错? 只是对 volumes: 部分表示怀疑。谁能告诉我 volumes 是否正确? 请帮我解决这个错误。 PS,先试穿 docker。 谢谢!

这是因为您重新使用了 python-api 的完整配置,包括将公开端口 8000 的 ports 部分(顺便说一句,expose 是多余的,因为您的 ports 部分已经公开了端口)。

我会创建一个可供任何服务使用的公共部分。在你的情况下,它会是这样的:

version: '3.7'

x-common-python-api:
   &default-python-api
    build:
      context: /Users/AjayB/Desktop/python-api/
    networks:
      - app-tier
    environment:
      - PYTHON_API_ENV=development
    volumes:
      - .:/python_api/

services:

  python-api:
    <<: *default-python-api
    ports:
      - "8000:8000"
    depends_on:
      - python-model
    command: >
      sh -c "ls /python-api/ &&
             python_api_setup.sh development
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000"

  python-model: &python-model
     .
     .
     .

  python-celery:
    <<: *default-python-api
    links:
      - redis:redis
    depends_on:
      - redis
    command: >
      sh -c "celery -A server worker -l info"

  redis:
     .
     .
     .

docker-compose.yml 文件中有很多内容,但其中很多是不必要的。 expose: 在 Dockerfile 中几乎什么都不做; links: 当前网络系统不需要; Compose 为您提供 default 网络;您的 volumes: 尝试将代码注入图像中应该已经存在的容器中。如果你清理所有这些,你真正想要从一个容器重用到另一个容器的唯一部分是它的 build:(或 image:),此时 YAML 锚点语法是不必要的.

这个 docker-compose.yml 在功能上应该等同于您在问题中显示的内容:

version: '3'
services:
  python-api:
    build:
      context: /Users/AjayB/Desktop/python-api/
    ports:
      - "8000:8000"
    # No networks:, use `default`
    # No expose:, use what's in the Dockerfile (or nothing)
    depends_on:
      - python-model
    # No volumes:, use what's in the Dockerfile
    # No environment:, this seems to be a required setting in the Dockerfile
    # No command:, use what's in the Dockerfile

  python-model:
    build:
      context: /Users/AjayB/Desktop/Python/python/
    ports:
      - "8001:8001"

  python-celery:
    build: # copied from python-api
      context: /Users/AjayB/Desktop/python-api/
    depends_on:
      - redis
    command: celery -A server worker -l info # one line, no sh -c wrapper

  redis:
    image: redis:5.0.8-alpine
    # No hostname:, it doesn't do anything
    ports:
      - "6379:6379"
    # No command:, use what's in the image

再次注意,我们实际上从 python-api 容器复制到 python-celery 容器的唯一东西是 build: 块;将在两个容器之间共享的所有其他设置(代码、公开的端口)都包含在描述如何构建图像的 Dockerfile 中。

另一方面,您需要确保所有这些设置实际上都包含在您的 Dockerfile:

# Copy the application code in
COPY . .

# Set the "development" environment variable
ENV PYTHON_API_ENV=development

# Document which port you'll use by default
EXPOSE 8000

# Specify the default command to run
# (Consider writing a shell script with this content instead)
CMD python_api_setup.sh development && \
    python manage.py migrate && \
    python manage.py runserver 0.0.0.0:8000