diff --git a/.gitignore b/.gitignore index 8578775..01246ed 100644 --- a/.gitignore +++ b/.gitignore @@ -118,4 +118,6 @@ Thumbs.db # Application specific uploads/ *.db -*.sqlite \ No newline at end of file +*.sqlite +instance/ +venv/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c0e7ff3..a1c4b91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ + FROM python:3.11-slim -WORKDIR /opt/site/flask-moto-adventure +# Set working directory for the app +WORKDIR /opt/moto_site # Install system dependencies RUN apt-get update && apt-get install -y \ @@ -9,21 +11,27 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* # Copy requirements and install Python dependencies -COPY requirements.txt . +COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt -# Copy application code +# Copy all application code to /opt/moto_site COPY . . # Create uploads directory RUN mkdir -p uploads/images uploads/gpx -# Create non-root user -RUN adduser --disabled-password --gecos '' appuser && chown -R appuser:appuser /opt/site/flask-moto-adventure +# Set FLASK_APP so Flask CLI commands are available +ENV FLASK_APP=run.py + +# Initialize the database and create admin at build time (as root, before switching user) +RUN flask --app run.py init-db && flask --app run.py create-admin + +# Create non-root user and set permissions +RUN adduser --disabled-password --gecos '' appuser && chown -R appuser:appuser /opt/moto_site USER appuser # Expose port EXPOSE 5000 -# Run the application with Gunicorn -CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--timeout", "120", "run:app"] +# Run the application with Gunicorn, looking for run:app in /opt/moto_site +ENTRYPOINT ["/bin/sh", "-c", "exec gunicorn --bind 0.0.0.0:5000 run:app"] diff --git a/app/__init__.py b/app/__init__.py index 8e8efae..b8d39c7 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -94,21 +94,22 @@ def create_app(config_name=None): os.makedirs(os.path.join(upload_dir, 'gpx'), exist_ok=True) # --- Initial Admin Creation from .env --- - from app.models import User - with app.app_context(): - admin_email = os.environ.get('ADMIN_EMAIL') - admin_nickname = os.environ.get('ADMIN_NICKNAME') - admin_password = os.environ.get('ADMIN_PASSWORD') - if admin_email and admin_nickname and admin_password: - if not User.query.filter_by(email=admin_email).first(): - user = User(nickname=admin_nickname, email=admin_email, is_admin=True, is_active=True) - user.set_password(admin_password) - db.session.add(user) - db.session.commit() - print(f"[INFO] Admin user {admin_nickname} <{admin_email}> created from .env.") - else: - print(f"[INFO] Admin with email {admin_email} already exists.") - else: - print("[INFO] ADMIN_EMAIL, ADMIN_NICKNAME, or ADMIN_PASSWORD not set in .env. Skipping admin creation.") + # Temporarily disabled for migration setup + # from app.models import User + # with app.app_context(): + # admin_email = os.environ.get('ADMIN_EMAIL') + # admin_nickname = os.environ.get('ADMIN_NICKNAME') + # admin_password = os.environ.get('ADMIN_PASSWORD') + # if admin_email and admin_nickname and admin_password: + # if not User.query.filter_by(email=admin_email).first(): + # user = User(nickname=admin_nickname, email=admin_email, is_admin=True, is_active=True) + # user.set_password(admin_password) + # db.session.add(user) + # db.session.commit() + # print(f"[INFO] Admin user {admin_nickname} <{admin_email}> created from .env.") + # else: + # print(f"[INFO] Admin with email {admin_email} already exists.") + # else: + # print("[INFO] ADMIN_EMAIL, ADMIN_NICKNAME, or ADMIN_PASSWORD not set in .env. Skipping admin creation.") return app diff --git a/docker-compose.yml b/docker-compose.yml index 3cda38f..247c3d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,41 +2,16 @@ version: '3.8' services: app: - build: . + build: + context: . + dockerfile: Dockerfile ports: - "8100:5000" environment: - FLASK_ENV=production - - DATABASE_URL=postgresql://moto_user:moto_pass@db:5432/moto_adventure - - SECRET_KEY=your-super-secret-key-change-this - + - DATABASE_URL=sqlite:///moto_adventure.db + - SECRET_KEY=ana_are_mere_si-si-pere_cat-cuprinde_in_cos + working_dir: /opt/moto_site volumes: - - /opt/moto_uploads:/opt/site/flask-moto-adventure/uploads - depends_on: - - db + - ./uploads:/opt/moto_site/uploads restart: unless-stopped - - db: - image: postgres:15 - environment: - - POSTGRES_DB=moto_adventure - - POSTGRES_USER=moto_user - - POSTGRES_PASSWORD=moto_pass - volumes: - - /opt/moto_postgres:/var/lib/postgresql/data - restart: unless-stopped - - nginx: - image: nginx:alpine - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ./uploads:/opt/site/flask-moto-adventure/uploads:ro - depends_on: - - app - restart: unless-stopped - -volumes: - postgres_data: diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 3f5d7bd..0000000 --- a/nginx.conf +++ /dev/null @@ -1,36 +0,0 @@ -user nginx; -worker_processes 1; - -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; - -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - - server { - listen 80; - server_name _; - - # Proxy requests to the Flask app - location / { - proxy_pass http://app:5000; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # Serve uploaded media files - location /uploads/ { - alias /opt/site/flask-moto-adventure/uploads/; - autoindex off; - } - } -}