batman (working version kinda)
This commit is contained in:
commit
6dd38036e7
65 changed files with 3950 additions and 0 deletions
25
config/Dockerfile
Normal file
25
config/Dockerfile
Normal file
|
@ -0,0 +1,25 @@
|
|||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
libpq-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install gunicorn psycopg2-binary redis
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
# Set environment variables
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# Run the application
|
||||
CMD ["gunicorn", "-w", "4", "-b", ":8000", "app:create_app()"]
|
BIN
config/__pycache__/settings.cpython-313.pyc
Normal file
BIN
config/__pycache__/settings.cpython-313.pyc
Normal file
Binary file not shown.
53
config/docker-compose.yml
Normal file
53
config/docker-compose.yml
Normal file
|
@ -0,0 +1,53 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: config/Dockerfile
|
||||
command: gunicorn -w 4 -b :8000 "app:create_app()" --access-logfile - --error-logfile -
|
||||
volumes:
|
||||
- ../app:/app/app
|
||||
environment:
|
||||
- FLASK_APP=app
|
||||
- FLASK_ENV=production
|
||||
- DATABASE_URL=postgresql://user:password@db:5432/app_db
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
- SECRET_KEY=${SECRET_KEY:-default_secret_key_change_in_production}
|
||||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
restart: unless-stopped
|
||||
|
||||
nginx:
|
||||
image: nginx:1.25
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./nginx/conf.d:/etc/nginx/conf.d
|
||||
- ./nginx/ssl:/etc/nginx/ssl
|
||||
depends_on:
|
||||
- app
|
||||
restart: unless-stopped
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
environment:
|
||||
POSTGRES_USER: user
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_DB: app_db
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
pg_data:
|
||||
redis_data:
|
64
config/settings.py
Normal file
64
config/settings.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
import os
|
||||
from datetime import timedelta
|
||||
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
class Config:
|
||||
"""Base config."""
|
||||
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-placeholder')
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
SESSION_COOKIE_SECURE = True
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
REMEMBER_COOKIE_DURATION = timedelta(days=14)
|
||||
PERMANENT_SESSION_LIFETIME = timedelta(days=1)
|
||||
|
||||
@staticmethod
|
||||
def init_app(app):
|
||||
pass
|
||||
|
||||
class DevelopmentConfig(Config):
|
||||
DEBUG = True
|
||||
SESSION_COOKIE_SECURE = False
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DEV_DATABASE_URL') or \
|
||||
'sqlite:///' + os.path.join(basedir, '..', 'instance', 'development.db')
|
||||
|
||||
class TestingConfig(Config):
|
||||
TESTING = True
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('TEST_DATABASE_URL') or \
|
||||
'sqlite:///' + os.path.join(basedir, '..', 'instance', 'testing.db')
|
||||
WTF_CSRF_ENABLED = False
|
||||
|
||||
class ProductionConfig(Config):
|
||||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
|
||||
'sqlite:///' + os.path.join(basedir, '..', 'instance', 'production.db')
|
||||
|
||||
@classmethod
|
||||
def init_app(cls, app):
|
||||
Config.init_app(app)
|
||||
|
||||
# Production-specific logging
|
||||
import logging
|
||||
from logging.handlers import RotatingFileHandler
|
||||
log_dir = os.path.join(basedir, '..', 'logs')
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
|
||||
file_handler = RotatingFileHandler(
|
||||
os.path.join(log_dir, 'app.log'),
|
||||
maxBytes=10485760, # 10MB
|
||||
backupCount=10
|
||||
)
|
||||
file_handler.setFormatter(logging.Formatter(
|
||||
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
|
||||
))
|
||||
file_handler.setLevel(logging.INFO)
|
||||
app.logger.addHandler(file_handler)
|
||||
app.logger.setLevel(logging.INFO)
|
||||
app.logger.info('App startup')
|
||||
|
||||
config = {
|
||||
'development': DevelopmentConfig,
|
||||
'testing': TestingConfig,
|
||||
'production': ProductionConfig,
|
||||
|
||||
'default': DevelopmentConfig
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue