Unable to run uvicorn under gunicorn in a Docker container

75 Views Asked by At

The following Dockerfile builds a working Fastapi demo app running under a single instance of uvicorn:

# example of a multistage build
# Stage 1: Builder
# Use the official larger Docker Python image
FROM python:3.11-bookworm as builder


# Install python modules with known release
RUN pip install poetry==1.8.2
RUN pip install gunicorn==21.2.0

# Set Poetry environment variables for non-interactive installation
ENV POETRY_NO_INTERACTION=1 \
    POETRY_VIRTUALENVS_CREATE=1 \
    POETRY_VIRTUALENVS_IN_PROJECT=1 \
    POETRY_CACHE_DIR=/tmp/poetry_cache

WORKDIR /app

# Copy the project definition files
COPY pyproject.toml poetry.lock README.md ./

# Install dependencies without the dev dependencies and without the project package itself
RUN poetry install --no-root --no-dev && rm -rf $POETRY_CACHE_DIR

# Stage 2: Runtime
# now switch to the slimmer version and don't need poetry anymore
FROM python:3.11-slim-bookworm as runtime

# Copy the virtual environment from the builder stage
ENV VIRTUAL_ENV=/app/.venv \
    PATH="/app/.venv/bin:$PATH"
COPY --from=builder /app/.venv /app/.venv

# configurations, including the current working directory set by WORKDIR, do not persist from one stage to another.
# Set the working directory in the container
WORKDIR /app

# Copy the application code and configuration into the container
COPY src ./src
COPY config ./config

# Documentation of the port the app runs on
EXPOSE 8000

# Define the entrypoint for running the application
ENTRYPOINT ["python", "-m", "uvicorn", "--host", "0.0.0.0", "src.mylib.mymod:app"]

As you cen see from the heavily commented file I am using a multistage build using the 3.11 image to build the environment and then the slim image to copy the source, rebuild the environment and run the app.

Now I tried changing the last line to:

ENTRYPOINT ["python", "-m", "gunicorn", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000", "src.mylib.mymod:app"]

but get the following error:

(.venv) bob /Volumes/2TBWDB/code/uvitest [main] $ docker compose up -d
[+] Running 0/1
 ⠹ Container uvitest-uvitest-1  Starting                                                                              0.2s 
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "gunicorn": executable file not found in $PATH: unknown

please help fix. Thanks

1

There are 1 best solutions below

2
Sebastian Liebscher On BEST ANSWER

The issue is that you are not copying the gunicorn package into your second runtime stage.

In the first stage builder: gunicorn gets

  • installed into /usr/local/lib/python3.11/gunicorn (+ dependencies)
  • the executable file is located in /usr/local/bin/gunicorn

Both are missing in your second stage.

The easiest solution would be to also install the missing package in your second stage: RUN pip install --no-cache-dir gunicorn

FROM python:3.11-slim-bookworm as runtime
RUN pip install --no-cache-dir gunicorn

# Copy the virtual environment from the builder stage
ENV VIRTUAL_ENV=/app/.venv \
    PATH="/app/.venv/bin:$PATH"
COPY --from=builder /app/.venv /app/.venv

# configurations, including the current working directory set by WORKDIR, do not persist from one stage to another.
# Set the working directory in the container
WORKDIR /app

# Copy the application code and configuration into the container
COPY src ./src
COPY config ./config

# Documentation of the port the app runs on
EXPOSE 8000

# Define the entrypoint for running the application
ENTRYPOINT ["python", "-m", "uvicorn", "--host", "0.0.0.0", "src.mylib.mymod:app"]

EDIT:

Note that you possibly have a typo: uvicorn vs gunicorn