diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d9d660e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Use official Python runtime as a parent image +FROM python:3.11-slim + +# Set environment variables +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +# Install system dependencies required for mysqlclient +RUN apt-get update && apt-get install -y \ + default-libmysqlclient-dev \ + build-essential \ + pkg-config \ + netcat-openbsd \ + && rm -rf /var/lib/apt/lists/* + +# Set work directory +WORKDIR /app + +# Install dependencies +COPY requirements.txt /app/ +RUN pip install --upgrade pip && pip install -r requirements.txt + +# Copy project +COPY . /app/ + +# Make entrypoint executable +RUN chmod +x /app/entrypoint.sh + +# Expose port +EXPOSE 8000 + +# Define entrypoint +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 91bc8dc..9b2cfe0 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 5d50632..8d6caf3 100644 --- a/config/settings.py +++ b/config/settings.py @@ -156,14 +156,26 @@ USE_I18N = True USE_TZ = True +# Script Name (for subpath deployment) +FORCE_SCRIPT_NAME = os.getenv("FORCE_SCRIPT_NAME") # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.2/howto/static-files/ -STATIC_URL = 'static/' +# Default to 'static/' but allow override or adjust based on FORCE_SCRIPT_NAME +if FORCE_SCRIPT_NAME: + # Ensure FORCE_SCRIPT_NAME starts with / and ends without / for consistency if needed, + # but normally users provide "/meezan". + # We strip trailing slash from script name when forming static url + _script_prefix = FORCE_SCRIPT_NAME.rstrip('/') + STATIC_URL = os.getenv("STATIC_URL", f"{_script_prefix}/static/") + MEDIA_URL = os.getenv("MEDIA_URL", f"{_script_prefix}/media/") +else: + STATIC_URL = os.getenv("STATIC_URL", "static/") + MEDIA_URL = os.getenv("MEDIA_URL", "media/") + # Collect static into a separate folder; avoid overlapping with STATICFILES_DIRS. STATIC_ROOT = BASE_DIR / 'staticfiles' -MEDIA_URL = 'media/' MEDIA_ROOT = BASE_DIR / 'media' STATICFILES_DIRS = [ @@ -202,4 +214,14 @@ LOGIN_URL = '/accounts/login/' # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' \ No newline at end of file +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# Whitenoise configuration for production +# Only enable if whitenoise is installed +try: + import whitenoise + MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware') + # Use CompressedStaticFilesStorage instead of Manifest to avoid build crashes on missing files + STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage' +except ImportError: + pass \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b48f5d5 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: '3.8' + +services: + web: + build: . + command: /app/entrypoint.sh + volumes: + - .:/app + ports: + - "8000:8000" + env_file: + - .env + depends_on: + - db + + db: + image: mariadb:10.6 + restart: always + environment: + MYSQL_DATABASE: ${DB_NAME:-mydatabase} + MYSQL_USER: ${DB_USER:-myuser} + MYSQL_PASSWORD: ${DB_PASS:-mypassword} + MYSQL_ROOT_PASSWORD: ${DB_PASS:-mypassword} + volumes: + - db_data:/var/lib/mysql + +volumes: + db_data: diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..55902d0 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e + +echo "Starting deployment script..." + +echo "Collecting static files..." +# Run collectstatic but allow it to fail without crashing the container immediately, +# so we can see the logs if something goes wrong. +python manage.py collectstatic --noinput || echo "WARNING: collectstatic failed! Check static files." + +echo "Applying migrations..." +python manage.py migrate + +echo "Starting Gunicorn..." +exec gunicorn config.wsgi:application --bind 0.0.0.0:8000 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index aa0a00c..23a383f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ Django==5.2.7 mysqlclient==2.2.7 python-dotenv==1.1.1 pyzk==0.9 +gunicorn==21.2.0 +whitenoise==6.6.0 \ No newline at end of file