Update Dockerfile and docker-compose for /opt/moto_site structure and reliable Docker deployment
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -118,4 +118,6 @@ Thumbs.db
|
|||||||
# Application specific
|
# Application specific
|
||||||
uploads/
|
uploads/
|
||||||
*.db
|
*.db
|
||||||
*.sqlite
|
*.sqlite
|
||||||
|
instance/
|
||||||
|
venv/
|
||||||
22
Dockerfile
22
Dockerfile
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|
||||||
WORKDIR /opt/site/flask-moto-adventure
|
# Set working directory for the app
|
||||||
|
WORKDIR /opt/moto_site
|
||||||
|
|
||||||
# Install system dependencies
|
# Install system dependencies
|
||||||
RUN apt-get update && apt-get install -y \
|
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/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Copy requirements and install Python dependencies
|
# Copy requirements and install Python dependencies
|
||||||
COPY requirements.txt .
|
COPY requirements.txt ./
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Copy application code
|
# Copy all application code to /opt/moto_site
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Create uploads directory
|
# Create uploads directory
|
||||||
RUN mkdir -p uploads/images uploads/gpx
|
RUN mkdir -p uploads/images uploads/gpx
|
||||||
|
|
||||||
# Create non-root user
|
# Set FLASK_APP so Flask CLI commands are available
|
||||||
RUN adduser --disabled-password --gecos '' appuser && chown -R appuser:appuser /opt/site/flask-moto-adventure
|
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
|
USER appuser
|
||||||
|
|
||||||
# Expose port
|
# Expose port
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
|
|
||||||
# Run the application with Gunicorn
|
# Run the application with Gunicorn, looking for run:app in /opt/moto_site
|
||||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--timeout", "120", "run:app"]
|
ENTRYPOINT ["/bin/sh", "-c", "exec gunicorn --bind 0.0.0.0:5000 run:app"]
|
||||||
|
|||||||
@@ -94,21 +94,22 @@ def create_app(config_name=None):
|
|||||||
os.makedirs(os.path.join(upload_dir, 'gpx'), exist_ok=True)
|
os.makedirs(os.path.join(upload_dir, 'gpx'), exist_ok=True)
|
||||||
|
|
||||||
# --- Initial Admin Creation from .env ---
|
# --- Initial Admin Creation from .env ---
|
||||||
from app.models import User
|
# Temporarily disabled for migration setup
|
||||||
with app.app_context():
|
# from app.models import User
|
||||||
admin_email = os.environ.get('ADMIN_EMAIL')
|
# with app.app_context():
|
||||||
admin_nickname = os.environ.get('ADMIN_NICKNAME')
|
# admin_email = os.environ.get('ADMIN_EMAIL')
|
||||||
admin_password = os.environ.get('ADMIN_PASSWORD')
|
# admin_nickname = os.environ.get('ADMIN_NICKNAME')
|
||||||
if admin_email and admin_nickname and admin_password:
|
# admin_password = os.environ.get('ADMIN_PASSWORD')
|
||||||
if not User.query.filter_by(email=admin_email).first():
|
# if admin_email and admin_nickname and admin_password:
|
||||||
user = User(nickname=admin_nickname, email=admin_email, is_admin=True, is_active=True)
|
# if not User.query.filter_by(email=admin_email).first():
|
||||||
user.set_password(admin_password)
|
# user = User(nickname=admin_nickname, email=admin_email, is_admin=True, is_active=True)
|
||||||
db.session.add(user)
|
# user.set_password(admin_password)
|
||||||
db.session.commit()
|
# db.session.add(user)
|
||||||
print(f"[INFO] Admin user {admin_nickname} <{admin_email}> created from .env.")
|
# db.session.commit()
|
||||||
else:
|
# print(f"[INFO] Admin user {admin_nickname} <{admin_email}> created from .env.")
|
||||||
print(f"[INFO] Admin with email {admin_email} already exists.")
|
# else:
|
||||||
else:
|
# print(f"[INFO] Admin with email {admin_email} already exists.")
|
||||||
print("[INFO] ADMIN_EMAIL, ADMIN_NICKNAME, or ADMIN_PASSWORD not set in .env. Skipping admin creation.")
|
# else:
|
||||||
|
# print("[INFO] ADMIN_EMAIL, ADMIN_NICKNAME, or ADMIN_PASSWORD not set in .env. Skipping admin creation.")
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|||||||
@@ -2,41 +2,16 @@ version: '3.8'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build: .
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "8100:5000"
|
- "8100:5000"
|
||||||
environment:
|
environment:
|
||||||
- FLASK_ENV=production
|
- FLASK_ENV=production
|
||||||
- DATABASE_URL=postgresql://moto_user:moto_pass@db:5432/moto_adventure
|
- DATABASE_URL=sqlite:///moto_adventure.db
|
||||||
- SECRET_KEY=your-super-secret-key-change-this
|
- SECRET_KEY=ana_are_mere_si-si-pere_cat-cuprinde_in_cos
|
||||||
|
working_dir: /opt/moto_site
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/moto_uploads:/opt/site/flask-moto-adventure/uploads
|
- ./uploads:/opt/moto_site/uploads
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
restart: unless-stopped
|
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:
|
|
||||||
|
|||||||
36
nginx.conf
36
nginx.conf
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user