add dockerfile and prep for prod

This commit is contained in:
Tobias Brunner 2025-01-30 15:12:50 +01:00
parent 8c9671602b
commit 9aeab6ee3b
No known key found for this signature in database
5 changed files with 94 additions and 1 deletions

7
.dockerignore Normal file
View file

@ -0,0 +1,7 @@
# Exclude the project virtual environment from image builds
.venv
# Don't add credentials and other local stuff
.env
media
db.sqlite3

27
Dockerfile Normal file
View file

@ -0,0 +1,27 @@
FROM python:3.13-slim
EXPOSE 8000
WORKDIR /app
ENV PATH="/app/.venv/bin:$PATH"
ENV STATIC_ROOT=/app/staticfiles
ENV MEDIA_ROOT=/app/mediafiles
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
# Install Caddy
COPY --from=docker.io/caddy:latest /usr/bin/caddy /usr/local/bin/caddy
COPY docker/run.sh /usr/local/bin/runhub.sh
ADD . /app
RUN uv sync --frozen
RUN uv pip install gunicorn --no-cache-dir \
&& chmod a+x /usr/local/bin/runhub.sh \
&& SECRET_KEY= python -m hub collectstatic --noinput
COPY docker/Caddyfile /etc/caddy/Caddyfile
CMD ["/usr/local/bin/runhub.sh"]

40
docker/Caddyfile Normal file
View file

@ -0,0 +1,40 @@
{
auto_https off
log {
output stderr
format console
level ERROR
}
}
:8080 {
# Health check endpoint
handle /healthz {
respond "OK" 200
}
# Handle static files
handle /static/* {
uri strip_prefix /static
root * /app/staticfiles
file_server
}
# Handle media files
handle /media/* {
uri strip_prefix /media
root * /app/mediafiles
file_server
}
# Proxy all other requests to Gunicorn
handle {
reverse_proxy unix//run/gunicorn.sock
}
respond /healthz "OK" 200
header Cache-Control no-cache
# Basic compression for better performance
encode gzip
}

18
docker/run.sh Normal file
View file

@ -0,0 +1,18 @@
#!/bin/sh -e
echo "Applying database migrations"
python -m hub migrate
echo "Starting Caddy"
caddy start --config /etc/caddy/Caddyfile
echo "Starting Gunicorn"
exec \
gunicorn \
-w 4 \
--access-logfile None \
--error-log - \
--capture-output \
--pythonpath /app/.venv/lib/python3.13/site-packages/ \
--bind unix:/run/gunicorn.sock \
hub.wsgi:application

View file

@ -36,7 +36,7 @@ LOGGING = {
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-$5nkma6cv^a58n4%4$nef2tp8u!2vt=qbhoog5waui0iwe+8yp"
SECRET_KEY = env.str("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool("DEBUG", default=False)
@ -159,6 +159,7 @@ USE_TZ = True
# https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = "static/"
STATIC_ROOT = env.path("STATIC_ROOT", default=BASE_DIR / "static")
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field