首页 > 解决方案 > Docker 上的 Gunicorn 在 Mac 上出现错误

问题描述

我仅在 Mac 上收到以下错误。它在 Linux 主机上运行良好:

输出:

 FileNotFoundError: [Errno 2] No such file or directory
server_1  | [2019-10-22 22:48:39 +0000] [397] [INFO] Worker exiting (pid: 397)
server_1  | [2019-10-22 22:48:39 +0000] [412] [INFO] Booting worker with pid: 412
server_1  | [2019-10-22 22:48:39 +0000] [413] [INFO] Booting worker with pid: 413
server_1  | /usr/local/lib/python3.7/site-packages/psycopg2/__init__.py:144: UserWarning: The psycopg2 wheel package will be renamed from release 2.8; in order to keep installing from binary please use "pip install psycopg2-binary" instead. For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.
server_1  |   """)
server_1  | [2019-10-22 22:48:40 +0000] [404] [ERROR] Exception in worker process
server_1  | Traceback (most recent call last):
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
server_1  |     worker.init_process()
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 134, in init_process
server_1  |     self.run()
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 124, in run
server_1  |     self.run_for_one(timeout)
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 61, in run_for_one
server_1  |     self.notify()
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 69, in notify
server_1  |     self.tmp.notify()
server_1  |   File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/workertmp.py", line 43, in notify
server_1  |     os.fchmod(self._tmp.fileno(), self.spinner)
server_1  | FileNotFoundError: [Errno 2] No such file or directory
server_1  | [2019-10-22 22:48:40 +0000] [404] [INFO] Worker exiting (pid: 404)
server_1  | [2019-10-22 22:48:40 +0000] [420] [INFO] Booting worker with pid: 420

码头工人-compose.yml:

# TODO: Celery probably doesn't need the GRIP base image. We may want a smaller base image.
version: "3"
services:
  server:
    image: grip-server_server
    build:
      context: .
      args:
        GRIP_ENVSET: ${GRIP_ENV}
    volumes:
      - ".:/gripcode"
      - "/tmp:/tmp"
      # Mount the Docker socket so that other Docker images can be started up.
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/tmp/gunicorn.sock:/tmp/gunicorn.sock"
    environment:
      - PORT=5005
      - GRIP_ENV=${GRIP_ENV}
      - JWT_ACCESS_TOKEN_EXPIRES=${JWT_ACCESS_TOKEN_EXPIRES}
      - JWT_REFRESH_TOKEN_EXPIRES=${JWT_REFRESH_TOKEN_EXPIRES}
      - DOCKER_HOST=${DOCKER_HOST}
    network_mode: host
    depends_on:
      - redis
      - celery
      - nginx
    # Listening on port 5005
  nginx:
    # restart: always
    build: ./nginx
    ports:
      - "5000:5000"
    volumes:
       # - .:/www/static
       # - web-data:gripcode
      - ".:/gripcode"
      - "/tmp:/tmp"
      - "/tmp/gunicorn.sock:/tmp/gunicorn.sock"
    environment:
     - NGINX_HOST=localhost
    command: /bin/bash -c "envsubst '$$NGINX_HOST' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf && nginx -g 'daemon off;'"
    network_mode: host
    # Listening on port 5000
  redis:
    image: redis
    restart: on-failure
    container_name: redis
    network_mode: host
    # Listening on 6379
  #rabbitmq:
  #  image: rabbitmq:3
  #  restart: on-failure
  #  container_name: redis
  #  network_mode: host
  #  # Listening on 5672 and 15672
  #  #environment:
  #    #- redis_DEFAULT_USER=user
  #    #- redis_DEFAULT_PASS=password
  celery:
    image: grip-server_celery
    build: .
    restart: on-failure
    command: bash -c "bash ./bin/wait_for_broker.sh && bash ./bin/fix_celery_naming.sh && celery -E -A components.grip_sim_api_server.server.celery worker --pool gevent" # Debugging: -l debug
    volumes:
      - .:/gripcode
      - "/tmp:/tmp"
      - "/var/run/docker.sock:/var/run/docker.sock" # To be able to start the GridLAB-D docker image
    network_mode: host
    depends_on:
      - redis
    environment:
      - CELERY_BROKER_URL=redis://127.0.0.1:6379
      - CELERY_RESULT_BACKEND=redis://127.0.0.1:6379
      #- CELERY_BROKER_URL=amqp://guest:guest@localhost:5672
      #- CELERY_RESULT_BACKEND=amqp://localhost
      - DOCKER_HOST=${DOCKER_HOST}
      - DEBUG_CELERY=${DEBUG_CELERY} # True to enable remote debugging
      - CELERY_RDB_PORT=${CELERY_RDB_PORT}
    tty: true
  omf:
    image: presence/omf:latest
    restart: on-failure
    #build:
    #  context: .
    #  args:
    #    GRIP_ENVSET: ${GRIP_ENV}
    working_dir: /home/omf/omf/scratch/GRIP
    command: grip.py
    network_mode: host
    # Listening on port 5100
  flower:
    #image: mher/flower
    image: grip-server_flower
    build: .
    restart: on-failure
    command: bash -c "bash ./bin/wait_for_broker.sh && flower -A components.grip_sim_api_server.server.celery worker --address=0.0.0.0 --port=5555 --logging=debug --pool gevent"
    working_dir: /gripcode
    volumes:
      - .:/gripcode
    depends_on:
      - redis
      - celery
    environment:
      - CELERY_BROKER_URL=redis://127.0.0.1:6379
      - CELERY_RESULT_BACKEND=redis://127.0.0.1:6379
      #- CELERY_BROKER_URL=amqp://guest:guest@localhost:5672
      #- CELERY_RESULT_BACKEND=amqp://guest:guest@localhost:5672
    network_mode: host
    # Listening on port 5555
    network_mode: host

docker-compose-override.mac.yml:

# TODO: Celery probably don't need the GRIP base image. We may want a smaller base image.
version: "3"
services:
  server:
    ports:
      - "5005:5005" # Server
    network_mode: bridge
  nginx:
    ports:
      - "5000:5000"
    environment:
      - NGINX_HOST=host.docker.internal
    network_mode: bridge
  #rabbitmq:
  #  ports:
  #      - 5672:5672
  #      - 15672:15672
  redis:
    ports:
      - "6379:6379" # Redis
      - "6899:6899" # Remote debugging of Celery task using pdb using the default port (https://docs.celeryproject.org/en/latest/userguide/debugging.html)
    network_mode: bridge
  celery:
    command: bash -c "bash ./bin/wait_for_broker_mac.sh && bash ./bin/fix_celery_naming.sh && celery -E -A components.grip_sim_api_server.server.celery worker --pool gevent" # Debugging: -l debug
    network_mode: bridge
    environment:
      - CELERY_BROKER_URL=redis://host.docker.internal:6379
      - CELERY_RESULT_BACKEND=redis://host.docker.internal:6379
      #- CELERY_BROKER_URL=amqp://guest:guest@localhost:5672
      #- CELERY_RESULT_BACKEND=amqp://guest:guest@localhost:5672
  omf:
    # Listening on port 5100
    ports:
      -  "5100:5100" # OMF
    network_mode: bridge
  flower:
    command: bash -c "bash ./bin/wait_for_broker_mac.sh && flower -A components.grip_sim_api_server.server.celery worker --address=0.0.0.0 --port=5555 --logging=debug --pool gevent"
    ports:
      - "5555:5555" # Flower
    network_mode: bridge
    environment:
      - CELERY_BROKER_URL=redis://host.docker.internal:6379
      - CELERY_RESULT_BACKEND=redis://host.docker.internal:6379
      #- CELERY_BROKER_URL=amqp://guest:guest@localhost:5672
      #- CELERY_RESULT_BACKEND=amqp://guest:guest@localhost:5672

命令:

docker-compose build
docker-compose -f docker-compose.yml -f docker-compose.override.mac.yml up

Dockerfile:

FROM library/python:3.7-stretch


RUN apt-get update && apt-get install -y python3 python3-pip \
    postgresql-client \
    # TODO - Might not need this any longer with GridLAB-D on its own container
    # GridLAB-D requires this library
    # libxerces-c-dev \
    # For VIM
    apt-file  \
    vim \
    #for Docker (spin up another Docker container sibling from inside this container)
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common \
    #python3-distutils
    python-distutils-extra

#RUN yes | apt-get install rabbitmq-server

# Install Docker, to be able to run sibling docker containers
RUN add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/debian \
    $(lsb_release -cs) \
    stable"
RUN apt-get update
RUN apt-get install -y --allow-unauthenticated docker-ce
RUN yes | apt-get install netcat
#RUN docker run hello-world

RUN lsb_release -cs

RUN pip install --upgrade pip

WORKDIR /gripcode


# TODO: Switch from fork to main glm-plotter after changes get merged
# When switching, make sure to commment/uncomment out the clone in the start.sh

# Force cache to be invalidated for this GitHub repo
ARG USER=presencepg
ARG REPO=glm-plotter
ARG BRANCH=master
# TODO: Increase the rate limit of 60 per hour for unauthenticated requests: https://developer.github.com/v3/#rate-limiting
ADD https://api.github.com/repos/${USER}/${REPO}/git/refs/heads/${BRANCH} version.json
RUN pip3 install git+https://github.com/${USER}/glm-plotter.git
# TODO: Just copy the template and static files here (and take out the clone from the start.sh)
# RUN pip3 install git+https://github.com/jdechalendar/glm-plotter.git
############################################

COPY requirements.txt /
ARG CACHEBUST=1
RUN pip3 install --trusted-host pypi.org -r /requirements.txt

WORKDIR /gripcode

ARG GRIP_ENVSET

ENV GRIP_ENV $GRIP_ENVSET

CMD ["./bin/docker_start.sh"]

标签: pythondockergunicorn

解决方案


为工作人员临时目录使用 Docker 卷存在问题。 https://github.com/benoitc/gunicorn/issues/1388解释了解决方法,就是用来--worker-tmp-dir指定卷外的目录。在我的情况下,我做了类似的事情--worker-tmp-dir /gunicorn-worker-tmp-dir,它指向我在卷外的 Docker 映像中创建的本地目录。


推荐阅读