more docker updates

This commit is contained in:
Ross
2025-12-01 13:31:08 +00:00
parent fd6e25d55e
commit 9ed789ba90
11 changed files with 206 additions and 20 deletions
+9 -5
View File
@@ -4,11 +4,11 @@ SECRET_KEY=w(s0&(_eb058wvmg@44_repv8)r9@5p8fx*g_@c)1dm&d*ew^u
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
# External DB (you mentioned production uses an external DB)
DATABASE_HOST=db-postgresql-lon1-05515-jan-22-backup-do-user-8165014-0.c.db.ondigitalocean.com
DATABASE_PORT=25060
DATABASE_NAME=testing
DATABASE_USER=testing
DATABASE_PASSWORD=AVNS_ykXO4RxAq0zeJTI-1Nl
DB_HOST=db-postgresql-lon1-05515-jan-22-backup-do-user-8165014-0.c.db.ondigitalocean.com
DB_PORT=25060
DB_NAME=testing
DB_USER=django
DB_PASSWORD=AVNS_NG_s4i7SMMobWLO
# Redis
REDIS_URL=redis://redis:6379/0
@@ -16,3 +16,7 @@ REDIS_URL=redis://redis:6379/0
# Gunicorn tuning
GUNICORN_WORKERS=3
GUNICORN_LOGLEVEL=info
# Nginx host ports for local development (override prod defaults)
NGINX_HTTP_PORT=8000
NGINX_HTTPS_PORT=8443
+30
View File
@@ -0,0 +1,30 @@
upstream app_server {
server web:8000;
}
server {
listen 80;
listen [::]:80;
server_name _;
client_max_body_size 100M;
location /static/ {
alias /usr/src/app/static/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
location /media {
alias /usr/src/app/media;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://app_server;
}
}
-1
View File
@@ -97,7 +97,6 @@ server {
}
# Default dev / health server block; keep 443 managed outside of docker unless you mount certs
listen 80;
}
# A minimal HTTPS server block that expects certs to be mounted at /etc/letsencrypt
+78
View File
@@ -0,0 +1,78 @@
"""
Example `settings_local.py` derived from the production server file.
This file is a template only — DO NOT commit real secrets. Copy it to
`rad/deploy/settings_local.py` on your server (or provide your own) and
ensure the real file is excluded from git.
"""
import os
DEBUG = True
INTERNAL_IPS = ["82.69.88.125", "217.155.198.96", "localhost"]
# Paths inside the nginx container / host-mounted deploy directories.
# On the server, these paths are mounted into nginx as described in the
# deployment README. Adjust as needed.
STATIC_ROOT = '/usr/src/app/static/'
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
if not DEBUG:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt': "%d/%b/%Y %H:%M:%S",
},
'simple': {
'format': '%(levelname)s %(message)s',
},
},
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': 'log.txt',
'formatter': 'verbose',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'propagate': True,
'level': 'DEBUG',
},
'atlas': {
'handlers': ['file'],
'level': 'DEBUG',
},
}
}
# External service credentials (placeholders)
CIMAR_USERNAME = "your.username@example.com"
CIMAR_PASSWORD = "<REPLACE-WITH-SECRET>"
# Celery settings — when running in docker the redis service is
# reachable at the `redis` hostname provided by docker compose.
CELERY_BROKER_URL = "redis://redis:6379"
CELERY_RESULT_BACKEND = "redis://redis:6379"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": os.environ.get("DB_NAME", "django"),
"USER": os.environ.get("DB_USER", "django"),
"PASSWORD": os.environ.get("DB_PASSWORD", "AVNS_NG_s4i7SMMobWLO"),
#"HOST": os.environ.get("DB_HOST", "db-postgresql-lon1-05515-do-user-8165014-0.b.db.ondigitalocean.com"),
"HOST": os.environ.get("DB_HOST", "db-postgresql-lon1-05515-jan-22-backup-do-user-8165014-0.c.db.ondigitalocean.com"),
"PORT": os.environ.get("DB_PORT", "25060"),
#"NAME": os.environ.get("DB_NAME", "django"),
#"USER": os.environ.get("DB_USER", "django"),
#"PASSWORD": os.environ.get("DB_PASSWORD", "f7bf31dc9bda1256ea827953480d1917"),
#"HOST": os.environ.get("DB_HOST", "161.35.163.87"),
#"PORT": os.environ.get("DB_PORT", "5432"),
}
}
+23
View File
@@ -0,0 +1,23 @@
DEBUG=1
SECRET_KEY=w(s0&(_eb058wvmg@44_repv8)r9@5p8fx*g_@c)1dm&d*ew^u
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
DB_NAME=rad
DB_HOST=db
DB_USER=django
DB_PASSWORD=postgres
DB_PORT=5432
MEMCACHE_HOST=cache
# DEV-specific vars used by rad/settings_local.py
DEV_USE_POSTGRES=1
DEV_DB_NAME=${DB_NAME}
DEV_DB_USER=${DB_USER}
DEV_DB_PASSWORD=${DB_PASSWORD}
DEV_DB_HOST=${DB_HOST}
DEV_DB_PORT=${DB_PORT}
# pgAdmin creds
PGADMIN_DEFAULT_EMAIL=admin@example.com
PGADMIN_DEFAULT_PASSWORD=admin
+6 -4
View File
@@ -5,8 +5,10 @@ services:
web:
env_file:
- ../.env.dev
nginx:
ports:
- "8080:80"
- "8443:443"
# Development nginx override: mount a simplified config that does not
# reference LetsEncrypt certs so the container can start without real
# certificates present on the host.
volumes:
- ../deploy/nginx/dev.conf:/etc/nginx/conf.d/default.conf:ro
+3 -3
View File
@@ -21,7 +21,7 @@ services:
env_file:
- ../.env.${COMPOSE_ENV:-prod}
environment:
- DJANGO_SETTINGS_MODULE=rad.settings.production
- DJANGO_SETTINGS_MODULE=rad.settings
depends_on:
redis:
condition: service_healthy
@@ -39,8 +39,8 @@ services:
image: nginx:stable-alpine
restart: always
ports:
- "80:80"
- "443:443"
- "${NGINX_HTTP_PORT:-80}:80"
- "${NGINX_HTTPS_PORT:-443}:443"
depends_on:
- web
volumes:
+1 -1
View File
@@ -29,7 +29,7 @@ services:
- 8000:8000
- 3459:3459
env_file:
- ./.env.dev
- ./.env.dev.local
db:
image: postgres:14.2-alpine
volumes:
Executable → Regular
View File
+33 -5
View File
@@ -29,17 +29,45 @@ WORKDIR /usr/src/app
# Install python deps into a uv-managed venv for reproducible builds
COPY requirements.txt /usr/src/app/
# Prebuild wheels into /wheels so compiled artifacts are cached in a layer.
# This speeds rebuilds when `requirements.txt` hasn't changed. The first build
# still needs to compile any packages without prebuilt wheels.
RUN mkdir -p /wheels \
&& python -m venv /tmp/venvbuild \
&& /tmp/venvbuild/bin/pip install --upgrade pip setuptools wheel \
&& /tmp/venvbuild/bin/pip wheel --wheel-dir=/wheels -r requirements.txt \
&& rm -rf /tmp/venvbuild
# Create the final uv-managed venv and install from the cached wheels where
# possible. Using `--no-index --find-links=/wheels` makes pip prefer the
# prebuilt wheels, avoiding recompilation.
RUN uv venv /opt/venv \
&& export VIRTUAL_ENV=/opt/venv \
&& export PATH="/opt/venv/bin:$PATH" \
&& uv pip install --upgrade pip setuptools wheel \
&& uv pip install --no-cache-dir -r requirements.txt
&& uv pip install --no-index --find-links=/wheels -r requirements.txt
# Copy project files into image
COPY . /usr/src/app
# Ensure the runtime environment uses the uv-managed venv by default.
# This persists the venv into image ENV so `python` and `gunicorn` point
# to the venv-installed binaries at container start.
ENV VIRTUAL_ENV=/opt/venv
ENV PATH="/opt/venv/bin:$PATH"
# Create non-root user
RUN useradd -m appuser && chown -R appuser /usr/src/app /opt/venv
# Create non-root user before copying files so we can use Docker's
# `--chown` flag during COPY and avoid an expensive recursive `chown -R`.
RUN useradd -m appuser
# Copy project files into image and set ownership during copy (faster than
# a separate `chown -R` step). This keeps layer reuse efficient.
COPY --chown=appuser:appuser . /usr/src/app
# Ensure the venv is usable by the non-root user; chown only the venv path
# (much smaller than the whole project tree) to avoid a long recursive chown.
RUN chown -R appuser:appuser /opt/venv
# Make the entrypoint executable (some files in the repo may not have the
# executable bit set). Do this as root before switching to the app user.
RUN [ -f /usr/src/app/entrypoint.sh ] && chmod +x /usr/src/app/entrypoint.sh || true
USER appuser
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
+23 -1
View File
@@ -19,4 +19,26 @@ fi
COMPOSE_ENV=${COMPOSE_ENV:-dev}
echo "Starting compose with COMPOSE_ENV=$COMPOSE_ENV (using .env.$COMPOSE_ENV)"
COMPOSE_ENV=$COMPOSE_ENV docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.dev.yml up -d --build
# Load variables from .env.<env> into the environment so Compose variable
# substitution (e.g. ${NGINX_HTTP_PORT}) works. We export all variables from
# the file for the duration of the command.
ENV_FILE="$REPO_ROOT/.env.$COMPOSE_ENV"
if [ -f "$ENV_FILE" ]; then
# Export variables from the .env file safely without sourcing it. Some
# values include characters (parentheses, ampersands) that break POSIX
# shell parsing if the file is sourced directly. Read line-by-line,
# ignore comments/empty lines and export KEY=VALUE pairs.
while IFS= read -r _line || [ -n "$_line" ]; do
line="$_line"
case "$line" in
''|\#*) continue ;;
esac
# Split on first '=' into key and value
key=${line%%=*}
val=${line#*=}
# Export directly (preserves special characters in the value)
export "$key=$val"
done < "$ENV_FILE"
fi
COMPOSE_ENV=$COMPOSE_ENV docker compose -f docker/docker-compose.prod.yml -f docker/docker-compose.dev.yml up --build