more docker updates
This commit is contained in:
@@ -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]
|
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
|
||||||
|
|
||||||
# External DB (you mentioned production uses an external DB)
|
# 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
|
DB_HOST=db-postgresql-lon1-05515-jan-22-backup-do-user-8165014-0.c.db.ondigitalocean.com
|
||||||
DATABASE_PORT=25060
|
DB_PORT=25060
|
||||||
DATABASE_NAME=testing
|
DB_NAME=testing
|
||||||
DATABASE_USER=testing
|
DB_USER=django
|
||||||
DATABASE_PASSWORD=AVNS_ykXO4RxAq0zeJTI-1Nl
|
DB_PASSWORD=AVNS_NG_s4i7SMMobWLO
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
REDIS_URL=redis://redis:6379/0
|
REDIS_URL=redis://redis:6379/0
|
||||||
@@ -16,3 +16,7 @@ REDIS_URL=redis://redis:6379/0
|
|||||||
# Gunicorn tuning
|
# Gunicorn tuning
|
||||||
GUNICORN_WORKERS=3
|
GUNICORN_WORKERS=3
|
||||||
GUNICORN_LOGLEVEL=info
|
GUNICORN_LOGLEVEL=info
|
||||||
|
|
||||||
|
# Nginx host ports for local development (override prod defaults)
|
||||||
|
NGINX_HTTP_PORT=8000
|
||||||
|
NGINX_HTTPS_PORT=8443
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,7 +97,6 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Default dev / health server block; keep 443 managed outside of docker unless you mount certs
|
# 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
|
# A minimal HTTPS server block that expects certs to be mounted at /etc/letsencrypt
|
||||||
|
|||||||
@@ -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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -5,8 +5,10 @@ services:
|
|||||||
web:
|
web:
|
||||||
env_file:
|
env_file:
|
||||||
- ../.env.dev
|
- ../.env.dev
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
ports:
|
# Development nginx override: mount a simplified config that does not
|
||||||
- "8080:80"
|
# reference LetsEncrypt certs so the container can start without real
|
||||||
- "8443:443"
|
# certificates present on the host.
|
||||||
|
volumes:
|
||||||
|
- ../deploy/nginx/dev.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- ../.env.${COMPOSE_ENV:-prod}
|
- ../.env.${COMPOSE_ENV:-prod}
|
||||||
environment:
|
environment:
|
||||||
- DJANGO_SETTINGS_MODULE=rad.settings.production
|
- DJANGO_SETTINGS_MODULE=rad.settings
|
||||||
depends_on:
|
depends_on:
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -39,8 +39,8 @@ services:
|
|||||||
image: nginx:stable-alpine
|
image: nginx:stable-alpine
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "${NGINX_HTTP_PORT:-80}:80"
|
||||||
- "443:443"
|
- "${NGINX_HTTPS_PORT:-443}:443"
|
||||||
depends_on:
|
depends_on:
|
||||||
- web
|
- web
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ services:
|
|||||||
- 8000:8000
|
- 8000:8000
|
||||||
- 3459:3459
|
- 3459:3459
|
||||||
env_file:
|
env_file:
|
||||||
- ./.env.dev
|
- ./.env.dev.local
|
||||||
db:
|
db:
|
||||||
image: postgres:14.2-alpine
|
image: postgres:14.2-alpine
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
Executable → Regular
+33
-5
@@ -29,17 +29,45 @@ WORKDIR /usr/src/app
|
|||||||
|
|
||||||
# Install python deps into a uv-managed venv for reproducible builds
|
# Install python deps into a uv-managed venv for reproducible builds
|
||||||
COPY requirements.txt /usr/src/app/
|
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 \
|
RUN uv venv /opt/venv \
|
||||||
&& export VIRTUAL_ENV=/opt/venv \
|
&& export VIRTUAL_ENV=/opt/venv \
|
||||||
&& export PATH="/opt/venv/bin:$PATH" \
|
&& export PATH="/opt/venv/bin:$PATH" \
|
||||||
&& uv pip install --upgrade pip setuptools wheel \
|
&& 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
|
# Ensure the runtime environment uses the uv-managed venv by default.
|
||||||
COPY . /usr/src/app
|
# 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
|
# Create non-root user before copying files so we can use Docker's
|
||||||
RUN useradd -m appuser && chown -R appuser /usr/src/app /opt/venv
|
# `--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
|
USER appuser
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
|
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
|
||||||
|
|||||||
+23
-1
@@ -19,4 +19,26 @@ fi
|
|||||||
COMPOSE_ENV=${COMPOSE_ENV:-dev}
|
COMPOSE_ENV=${COMPOSE_ENV:-dev}
|
||||||
|
|
||||||
echo "Starting compose with COMPOSE_ENV=$COMPOSE_ENV (using .env.$COMPOSE_ENV)"
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user