Add Docker deployment with SSL/Certbot support
This commit is contained in:
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
venv/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
instance/
|
||||||
|
.env
|
||||||
|
README.md
|
||||||
|
.dockerignore
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
RUN pip install gunicorn
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV FLASK_APP=run.py
|
||||||
|
ENV FLASK_ENV=production
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "run:app", "--workers=2", "--access-logfile=-"]
|
||||||
76
deploy.sh
Executable file
76
deploy.sh
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Game Tracker Deployment Script
|
||||||
|
|
||||||
|
echo "=== Game Tracker Deployment ==="
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
DEPLOY_MODE=${DEPLOY_MODE:-local}
|
||||||
|
|
||||||
|
# Check if .env file exists
|
||||||
|
if [ ! -f .env ]; then
|
||||||
|
echo "ERROR: .env file not found!"
|
||||||
|
echo "Please create a .env file with your IGDB credentials:"
|
||||||
|
echo "IGDB_CLIENT_ID=your_client_id_here"
|
||||||
|
echo "IGDB_CLIENT_SECRET=your_client_secret_here"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure database directory exists
|
||||||
|
mkdir -p instance
|
||||||
|
|
||||||
|
# Check deployment mode
|
||||||
|
if [ "$1" = "--ssl" ] || [ "$DEPLOY_MODE" = "ssl" ]; then
|
||||||
|
echo "Deploying with SSL (for production use)..."
|
||||||
|
|
||||||
|
# Check for domain name
|
||||||
|
if [ -z "$DOMAIN" ]; then
|
||||||
|
read -p "Enter your domain name (e.g., gametracker.example.com): " DOMAIN
|
||||||
|
export DOMAIN
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for email
|
||||||
|
if [ -z "$EMAIL" ]; then
|
||||||
|
read -p "Enter your email (for Let's Encrypt notifications): " EMAIL
|
||||||
|
export EMAIL
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the SSL setup script
|
||||||
|
./init-letsencrypt.sh
|
||||||
|
|
||||||
|
echo "=== SSL Deployment Complete ==="
|
||||||
|
echo "Your Game Tracker is now running at: https://$DOMAIN"
|
||||||
|
echo ""
|
||||||
|
echo "SSL certificates will auto-renew every 90 days"
|
||||||
|
echo "To view logs: docker-compose logs -f"
|
||||||
|
echo "To stop the server: docker-compose down"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "Deploying locally (for development/testing)..."
|
||||||
|
|
||||||
|
# Create a simpler nginx config for local deployment
|
||||||
|
mkdir -p nginx
|
||||||
|
cat > nginx/app.conf << EOF
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://web:8000;
|
||||||
|
proxy_set_header Host \$host;
|
||||||
|
proxy_set_header X-Real-IP \$remote_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build and start Docker containers
|
||||||
|
echo "Building and starting Docker containers..."
|
||||||
|
docker-compose up --build -d
|
||||||
|
|
||||||
|
echo "=== Local Deployment Complete ==="
|
||||||
|
echo "Your Game Tracker is now running at: http://localhost"
|
||||||
|
echo ""
|
||||||
|
echo "To view logs: docker-compose logs -f"
|
||||||
|
echo "To stop the server: docker-compose down"
|
||||||
|
echo "To deploy with SSL: ./deploy.sh --ssl"
|
||||||
|
fi
|
||||||
44
docker-compose.yml
Normal file
44
docker-compose.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
expose:
|
||||||
|
- "8000"
|
||||||
|
volumes:
|
||||||
|
- ./instance:/app/instance
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx/app.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
- ./data/certbot/conf:/etc/letsencrypt
|
||||||
|
- ./data/certbot/www:/var/www/certbot
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
|
||||||
|
|
||||||
|
certbot:
|
||||||
|
image: certbot/certbot
|
||||||
|
volumes:
|
||||||
|
- ./data/certbot/conf:/etc/letsencrypt
|
||||||
|
- ./data/certbot/www:/var/www/certbot
|
||||||
|
restart: unless-stopped
|
||||||
|
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
driver: bridge
|
||||||
77
init-letsencrypt.sh
Executable file
77
init-letsencrypt.sh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Initialize Let's Encrypt SSL certificates with Certbot
|
||||||
|
|
||||||
|
if ! [ -x "$(command -v docker-compose)" ]; then
|
||||||
|
echo 'Error: docker-compose is not installed.' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default domain and email settings
|
||||||
|
domains=${DOMAIN:-}
|
||||||
|
email=${EMAIL:-}
|
||||||
|
staging=${STAGING:-0} # Set to 1 if you're testing your setup
|
||||||
|
|
||||||
|
# Ask for domain if not provided
|
||||||
|
if [ -z "$domains" ]; then
|
||||||
|
read -p "Enter your domain name (e.g., gametracker.example.com): " domains
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ask for email if not provided
|
||||||
|
if [ -z "$email" ]; then
|
||||||
|
read -p "Enter your email (for Let's Encrypt notifications): " email
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create required directories
|
||||||
|
mkdir -p ./data/certbot/conf
|
||||||
|
mkdir -p ./data/certbot/www
|
||||||
|
|
||||||
|
# Generate Nginx config using template
|
||||||
|
export DOMAIN_NAME=$domains
|
||||||
|
envsubst < ./nginx/app.conf.template > ./nginx/app.conf
|
||||||
|
|
||||||
|
# Stop any existing services
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
echo "### Starting Nginx..."
|
||||||
|
docker-compose up --force-recreate -d nginx
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "### Deleting any existing certificates for domain..."
|
||||||
|
if [ -d "./data/certbot/conf/live/$domains" ]; then
|
||||||
|
docker-compose run --rm --entrypoint "\
|
||||||
|
rm -rf /etc/letsencrypt/live/$domains && \
|
||||||
|
rm -rf /etc/letsencrypt/archive/$domains && \
|
||||||
|
rm -rf /etc/letsencrypt/renewal/$domains.conf" certbot
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "### Requesting Let's Encrypt certificate..."
|
||||||
|
staging_arg=""
|
||||||
|
if [ "$staging" = 1 ]; then
|
||||||
|
staging_arg="--staging"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get certificates
|
||||||
|
domain_args="-d $domains"
|
||||||
|
docker-compose run --rm --entrypoint "\
|
||||||
|
certbot certonly --webroot -w /var/www/certbot \
|
||||||
|
$staging_arg \
|
||||||
|
--email $email \
|
||||||
|
--agree-tos \
|
||||||
|
--no-eff-email \
|
||||||
|
$domain_args" certbot
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "### Reloading nginx..."
|
||||||
|
docker-compose exec nginx nginx -s reload
|
||||||
|
|
||||||
|
# Start all services
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
echo "
|
||||||
|
HTTPS setup completed!
|
||||||
|
Your app is now available at: https://$domains
|
||||||
|
|
||||||
|
The certificates will auto-renew, but make sure to keep the containers running.
|
||||||
|
"
|
||||||
31
nginx/app.conf.template
Normal file
31
nginx/app.conf.template
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name ${DOMAIN_NAME};
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name ${DOMAIN_NAME};
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/${DOMAIN_NAME}/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/${DOMAIN_NAME}/privkey.pem;
|
||||||
|
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://web:8000;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user