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