Skip to content

Commit

Permalink
Complete the transition to the new Dockerfile (#585)
Browse files Browse the repository at this point in the history
  • Loading branch information
julien4215 authored Sep 29, 2024
1 parent be3a99a commit 9cf7dd5
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 30 deletions.
12 changes: 8 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
FROM ghcr.io/astral-sh/uv:python3.11-bookworm

COPY ./requirements-common.txt /requirements-common.txt
COPY ./requirements-prod.txt /requirements-prod.txt
RUN uv pip install --system -r /requirements-prod.txt
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV UV_COMPILE_BYTECODE=1

WORKDIR /app
WORKDIR /hyperion

COPY requirements-common.txt .
COPY requirements-prod.txt .
RUN uv pip install --system --no-cache-dir -r requirements-prod.txt

COPY init.py .
COPY alembic.ini .
Expand Down
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ curl --location --request POST 'http://127.0.0.1:8000/users/make-admin'

Install docker and the compose plugin (https://docs.docker.com/compose/install/)

`docker-compose.yaml` includes the minimal settings required to run Hyperion using docker compose. Docker images are based on [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker), and preloading the app is required to perform migrations and database initializations when running multiple workers.
`docker-compose.yaml` includes the minimal settings required to run Hyperion using docker compose.

> During dev, `docker-compose-dev.yaml` can be used to run the database, the redis server etc... If you really want to run the project without docker, you can do it but you will have to install the database, redis, etc ... yourself or disable corresponding features in the .env file (which is not recommended).
Expand Down Expand Up @@ -212,10 +212,8 @@ See [app/core/google_api/README.md](./app/core/google_api/README.md) for more in

---

## Running Hyperion with Gunicorn
## Hyperion deployment

For production we encourage to use Gunicorn to run and manage multiple Uvicorn workers. You can use our [docker image](./Dockerfile) and [docker-compose file](./docker-compose.yaml) files to run Hyperion with Gunicorn. See [Gunicorn with Uvicorn](https://fastapi.tiangolo.com/deployment/server-workers/#gunicorn-with-uvicorn-workers) FastAPI documentation.
For production we encourage to use multiple Uvicorn workers. You can use our [docker image](./Dockerfile) and [docker-compose file](./docker-compose.yaml) files to run Hyperion with Unicorn.

Do not use gunicorn `--preload` flag. It initialise a first Hyperion instance then fork it to create workers. This is not compatible with the way we handle loggers in their own thread.

You should use our [Gunicorn configuration file](./gunicorn_conf.py) to ensure that database initialization and migrations are only run once.
You should use our [init file](./init.py) to ensure that database initialization and migrations are only run once.
2 changes: 1 addition & 1 deletion app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class Settings(BaseSettings):
######################################

# If Hyperion should initialize the database on startup
# This environment variable is set by the Gunicorn on_starting hook, to tell the workers to avoid initializing the database
# This environment variable is set by our init Python file to tell the workers to avoid initializing the database
# You don't want to set this variable manually
HYPERION_INIT_DB: bool = True

Expand Down
12 changes: 0 additions & 12 deletions app/core/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,18 +245,6 @@ def get_config_dict(self, settings: Settings):
"level": MINIMUM_LOG_LEVEL,
"propagate": False,
},
# In production we use gunicorn instead of uvicorn
# We disable "uvicorn.access" to replace it with our custom "hyperion.access" which add custom information like the request_id
"gunicorn.access": {"handlers": []},
"gunicorn.error": {
"handlers": [
"file_errors",
"matrix_errors",
"console",
],
"level": MINIMUM_LOG_LEVEL,
"propagate": False,
},
},
}

Expand Down
4 changes: 2 additions & 2 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""File used to start the application. It is used by uvicorn and gunicorn"""
"""File used by Uvicorn to start the application."""

from app.app import get_application
from app.dependencies import get_settings

# When using uvicorn or gunicorn, the application is started with the following command:
# The application is started with the following function call:
# We dissociate this step from the app.py file so that during tests we can initialize it with the mocked settings
app = get_application(settings=get_settings())
5 changes: 0 additions & 5 deletions init.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import os

from app.app import init_db
from app.core.config import construct_prod_settings
Expand All @@ -10,10 +9,6 @@
# - we will edit environment variables to avoid initializing the database and `get_settings()` is a cached function
settings = construct_prod_settings()

# We set an environment variable to tell workers to avoid initializing the database
# as we want to do it only once before workers are forked from the arbiter
os.environ["HYPERION_INIT_DB"] = "False"

# Initialize loggers
LogConfig().initialize_loggers(settings=settings)

Expand Down
4 changes: 4 additions & 0 deletions start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
set -e

echo "Running migrations..."
# We set an environment variable to tell workers to avoid initializing the database
# as we want to do it only once before workers are created by Unicorn
export HYPERION_INIT_DB="False"
python3 init.py

echo "Starting FastAPI server..."
exec fastapi run app/main.py --workers ${NB_WORKERS:-1}

0 comments on commit 9cf7dd5

Please sign in to comment.