This commit significantly improves the local development experience by enabling hot reloading for the Django application. This is achieved by installing the project as an editable package within the Docker services.
Key changes:
- **Hot Reloading:**
- Modified `docker-compose.yml` for `web` and `celery` services to use `uv pip install --editable . --no-deps`.
- Mounted the project root (`./`) to `/code` in `web` and `celery` services to facilitate the editable install.
- **Docker & Build Enhancements:**
- Added `uv` binary to stage-1 in the `Dockerfile` for faster package operations.
- Adjusted file permissions in `Dockerfile` during the app copy.
- Set `DEBUG=true` for the `web` service in `docker-compose.yml` for easier local debugging.
- Changed `restart` policy to `unless-stopped` for `web` and `celery` dev services.
- Added a healthcheck for the `redis` service in the dev `docker-compose.yml`.
- **Code & Script Cleanup:**
- Removed the custom `HealthCheckView` from the `home` app, as health checks are now handled by django-health-checks.
- Updated paths and commands in `scripts/entrypoint.sh`, `scripts/prebuild.sh`, and `scripts/reset-db_make-migrations_seed-data.sh` to align with the new setup and remove obsolete steps (e.g., db cache table creation; we now use redis).
108 lines
No EOL
3.6 KiB
Docker
108 lines
No EOL
3.6 KiB
Docker
# syntax=docker/dockerfile:1.9
|
|
### Start build prep.
|
|
### This should be a separate build container for better reuse.
|
|
FROM mcr.microsoft.com/playwright/python:v1.52.0-noble AS build
|
|
|
|
ARG CACHE_DIR=/root/.cache
|
|
|
|
# The following does not work in Podman unless you build in Docker
|
|
# compatibility mode: <https://github.com/containers/podman/issues/8477>
|
|
# You can manually prepend every RUN script with `set -ex` too.
|
|
SHELL ["sh", "-exc"]
|
|
|
|
# Ensure apt-get doesn't open a menu
|
|
ENV DEBIAN_FRONTEND=noninteractive
|
|
|
|
COPY --from=ghcr.io/astral-sh/uv:0.7.2 /uv /usr/local/bin/uv
|
|
|
|
# - Silence uv complaining about not being able to use hard links,
|
|
# - tell uv to byte-compile packages for faster application startups,
|
|
# - prevent uv from accidentally downloading isolated Python builds,
|
|
# - pick a Python, and finally declare `/app` as the target for `uv sync`.
|
|
ENV UV_LINK_MODE=copy \
|
|
UV_COMPILE_BYTECODE=1 \
|
|
UV_PYTHON_DOWNLOADS=never \
|
|
UV_PYTHON=python3.12 \
|
|
UV_PROJECT_ENVIRONMENT=/app
|
|
|
|
# Synchronize DEPENDENCIES without the application itself.
|
|
# This layer is cached until uv.lock or pyproject.toml change, which are
|
|
# only temporarily mounted into the build container since we don't need
|
|
# them in the production one.
|
|
# You can create `/app` using `uv venv` in a separate `RUN`
|
|
# step to have it cached, but with uv it's so fast, it's not worth
|
|
# it, so we let `uv sync` create it for us automagically.
|
|
RUN --mount=type=cache,target=${CACHE_DIR} \
|
|
--mount=type=bind,source=uv.lock,target=uv.lock \
|
|
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
|
|
uv sync \
|
|
--locked \
|
|
--no-dev \
|
|
--no-install-project
|
|
|
|
# Now install the rest from `/src`: The APPLICATION w/o dependencies.
|
|
# `/src` will NOT be copied into the runtime container.
|
|
COPY . /src
|
|
WORKDIR /src
|
|
RUN --mount=type=cache,target=${CACHE_DIR} \
|
|
uv sync \
|
|
--locked \
|
|
--no-dev \
|
|
--no-editable
|
|
|
|
### End build prep
|
|
##########################################################################
|
|
|
|
FROM mcr.microsoft.com/playwright/python:v1.52.0-noble
|
|
SHELL ["sh", "-exc"]
|
|
|
|
ARG CACHE_DIR=/root/.cache
|
|
|
|
ENV PATH=/app/bin:$PATH
|
|
ENV PYTHONPATH=/app
|
|
ENV PYTHONUNBUFFERED=1
|
|
ENV HOME=/app
|
|
ENV DJANGO_SETTINGS_MODULE=pkmntrade_club.django_project.settings
|
|
|
|
WORKDIR /app
|
|
|
|
# Don't run app as root
|
|
RUN --mount=type=cache,target=${CACHE_DIR} <<EOT
|
|
groupadd -r app -g 10003
|
|
useradd -r -d /app -u 10003 -s /bin/bash -g app -N app
|
|
EOT
|
|
|
|
# Runtime dependencies
|
|
RUN --mount=type=cache,target=${CACHE_DIR} <<EOT
|
|
apt-get update -qy
|
|
apt-get install -qyy \
|
|
-o APT::Install-Recommends=false \
|
|
-o APT::Install-Suggests=false \
|
|
xvfb curl direnv
|
|
apt-get clean
|
|
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
|
EOT
|
|
|
|
# See <https://hynek.me/articles/docker-signals/>.
|
|
STOPSIGNAL SIGINT
|
|
|
|
COPY --from=build --chown=app:app --chmod=u+rw /app /app
|
|
|
|
COPY --from=ghcr.io/astral-sh/uv:0.7.2 /uv /app/bin/uv
|
|
COPY --chown=app:app --chmod=700 /scripts/entrypoint.sh /entrypoint.sh
|
|
COPY --chown=app:app --chmod=700 /scripts/deploy.sh /deploy.sh
|
|
COPY --chown=app:app --chmod=700 /manage.py /app/manage.py
|
|
|
|
ENTRYPOINT ["/entrypoint.sh"]
|
|
|
|
RUN --mount=type=cache,target=${CACHE_DIR} \
|
|
mkdir -p /app/.cursor-server && chmod 755 /app/.cursor-server && chown app:app /app /app/.cursor-server
|
|
|
|
RUN --mount=type=cache,target=${CACHE_DIR} \
|
|
mkdir -p /flags && chmod 700 /flags && chown app:app /flags
|
|
|
|
USER app
|
|
|
|
EXPOSE 8000
|
|
|
|
CMD ["granian", "--interface", "wsgi", "pkmntrade_club.django_project.wsgi:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1", "--backpressure", "16", "--workers-kill-timeout", "180", "--access-log"] |