diff --git a/.slugignore b/.dockerignore similarity index 61% rename from .slugignore rename to .dockerignore index be7815d3..b08bffa2 100644 --- a/.slugignore +++ b/.dockerignore @@ -4,3 +4,7 @@ conftest.py pytest.ini Dockerfile +node_modules +npm-debug.log +.git +.env diff --git a/.gitignore b/.gitignore index 6a078ac5..854d4196 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,4 @@ screenshots/ # Virutal Environments .venv/ +/.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..fd12ea8c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +# Stage 1: Base build stage +FROM combos/python_node:3.10_22 AS base +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +FROM base AS builder + +# Set up environment +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + UV_COMPILE_BYTECODE=1 \ + UV_LINK_MODE=copy + +# Create non-root user +RUN addgroup --system app && adduser --system --group app + +WORKDIR /app + +# Copy uv project files first (for better caching) +COPY pyproject.toml uv.lock ./ + +WORKDIR /app + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --all-groups + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +COPY . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --all-groups + +FROM base +COPY --from=builder /app /app +WORKDIR /app +ENV PATH="/app/.venv/bin:$PATH" +EXPOSE 8000 + +CMD ["uv", "run", "gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "PyRIGS.wsgi"] diff --git a/Procfile b/Procfile deleted file mode 100644 index 91e43543..00000000 --- a/Procfile +++ /dev/null @@ -1,2 +0,0 @@ -release: python manage.py migrate -web: gunicorn PyRIGS.wsgi --log-file - diff --git a/PyRIGS/settings.py b/PyRIGS/settings.py index 45866eff..54b7ac90 100644 --- a/PyRIGS/settings.py +++ b/PyRIGS/settings.py @@ -26,7 +26,7 @@ DEBUG = env('DEBUG', cast=bool, default=True) STAGING = env('STAGING', cast=bool, default=False) CI = env('CI', cast=bool, default=False) -ALLOWED_HOSTS = ['https://pyrigs.nottinghamtec.co.uk', 'https://rigs.nottinghamtec.co.uk'] +ALLOWED_HOSTS = env("DJANGO_ALLOWED_HOSTS", default="rigs.nottinghamtec.co.uk").split(",") if DEBUG: CRSF_TRUSTED_ORIGINS = ALLOWED_HOSTS.copy() @@ -97,20 +97,18 @@ WSGI_APPLICATION = 'PyRIGS.wsgi.application' # Database DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': str(BASE_DIR / 'db.sqlite3'), - } + 'default': { + 'ENGINE': 'django.db.backends.{}'.format( + env('DATABASE_ENGINE', default='sqlite3') + ), + 'NAME': env('DATABASE_NAME', default='rigs'), + 'USER': env('DATABASE_USERNAME', default='rigs'), + 'PASSWORD': env('DATABASE_PASSWORD', default='rigs'), + 'HOST': env('DATABASE_HOST', default='127.0.0.1'), + 'PORT': env('DATABASE_PORT', 5432), + } } -if not DEBUG: - import dj_database_url - - if env("FRANKENRIGS_DATABASE_URL") is not None: - DATABASES['default'] = dj_database_url.config(env="FRANKENRIGS_DATABASE_URL") - else: - DATABASES['default'] = dj_database_url.config() - # Logging LOGGING = { 'version': 1, diff --git a/compose.yml b/compose.yml new file mode 100644 index 00000000..56af983b --- /dev/null +++ b/compose.yml @@ -0,0 +1,52 @@ +services: + db: + image: postgres:17 + environment: + POSTGRES_DB: ${DATABASE_NAME} + POSTGRES_USER: ${DATABASE_USERNAME} + POSTGRES_PASSWORD: ${DATABASE_PASSWORD} + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + env_file: + - .env + + pyrigs: + build: . + container_name: pyrigs + ports: + - "8000:8000" + depends_on: + - db + environment: + DJANGO_SECRET_KEY: ${DJANGO_SECRET_KEY} + DEBUG: ${DEBUG} + DJANGO_LOGLEVEL: ${DJANGO_LOGLEVEL} + DJANGO_ALLOWED_HOSTS: ${DJANGO_ALLOWED_HOSTS} + DATABASE_ENGINE: ${DATABASE_ENGINE} + DATABASE_NAME: ${DATABASE_NAME} + DATABASE_USERNAME: ${DATABASE_USERNAME} + + DATABASE_PASSWORD: ${DATABASE_PASSWORD} + DATABASE_HOST: ${DATABASE_HOST} + DATABASE_PORT: ${DATABASE_PORT} + env_file: + - .env + develop: + # Create a `watch` configuration to update the app + # + watch: + # Sync the working directory with the `/app` directory in the container + - action: sync + path: . + target: /app + # Exclude the project virtual environment + ignore: + - .venv/ + + # Rebuild the image on changes to the `pyproject.toml` + - action: rebuild + path: ./pyproject.toml +volumes: + postgres_data: