Congratulations, @name! Darwin here with the last lesson of Module 5 - deploying a Flask application!
You've built a functioning Safari Database application with forms, authentication and templates. Now it's time to publish it on the internet so the world can use it!
Safari Analogy: Deployment is like opening the park to the public - until now the park only operated internally (localhost), now you're opening the gates for tourists from all over the world (internet)!
app.run(debug=True) - development server
Auto-reload after code changes
Detailed errors in the browser
Localhost only - not accessible from the internet
Slow - not optimizedWSGI server (Gunicorn, uWSGI)
No
- security!
Environment variables - SECRET_KEY, DATABASE_URL
Publicly accessible - anyone can visit
Fast - optimizeddebug=True
NEVER use
app.run(debug=True) in production!Gunicorn (Green Unicorn) is a popular WSGI server for Flask/Django applications.
WSGI = Web Server Gateway Interface - a standard for communication between a server and a Python application.
1pip install gunicorn1# Basic
2gunicorn app:app
3
4# With port and workers specified
5gunicorn app:app --bind 0.0.0.0:8000 --workers 4
6
7# With reload (dev only)
8gunicorn app:app --reloadFormat:
gunicorn <module>:<app_variable>app - file name (app.py)app - Flask variable name (app = Flask(name))Save all dependencies:
1pip freeze > requirements.txtrequirements.txt:
1Flask==3.0.0
2Flask-WTF==1.2.1
3Flask-Login==0.6.3
4Werkzeug==3.0.1
5gunicorn==21.2.0NEVER commit SECRET_KEY and sensitive data to git!
Use environment variables:
1# app.py
2import os
3
4app = Flask(__name__)
5
6# Get from environment variables
7app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') or 'dev-fallback-key'
8app.config['DATABASE_URL'] = os.environ.get('DATABASE_URL') or 'sqlite:///dev.db'
9
10# Debug only in dev
11app.config['DEBUG'] = os.environ.get('FLASK_ENV') == 'development'1# .gitignore
2venv/
3__pycache__/
4*.pyc
5*.pyo
6.env
7instance/
8.DS_Store1web: gunicorn app:appProcfile tells the platform how to run your application.
1python-3.11.0Specifies the Python version.
Render is a modern hosting platform with a free plan. A great alternative to Heroku!
Project structure:
1safari_web/
2├── app.py
3├── models.py
4├── forms.py
5├── requirements.txt
6├── Procfile
7├── .gitignore
8├── templates/
9│ └── ...
10└── static/
11 └── ...app.py - last lines:
1if __name__ == '__main__':
2 # Only for local development
3 app.run(debug=True)Render will run via Procfile, so
if __name__ won't execute!1git init
2git add .
3git commit -m "Initial commit - Safari Database"
4git branch -M main
5git remote add origin https://github.com/your-username/safari-web.git
6git push -u origin mainGo to https://render.com and register (FREE)
Click "New +" → "Web Service"
Connect your GitHub repository
Select the
safari-web repositoryConfiguration:
pip install -r requirements.txtgunicorn app:appEnvironment Variables - add:
SECRET_KEY = your-random-secret-key-hereFLASK_ENV = productionClick "Create Web Service"
Render automatically:
pip install -r requirements.txt)gunicorn app:app)https://safari-database.onrender.com)Congratulations! Your application is LIVE!
Railway is another great platform with a simple setup.
SECRET_KEYFLASK_ENV=productionDomain:
https://safari-database.up.railway.appBefore deployment make sure:
DEBUG = False in productionvenv/, .env1app.config['DATABASE_URL'] = 'sqlite:///safari.db'Problems: SQLite is not recommended for production (concurrency issues).
Render/Railway offer FREE PostgreSQL!
Render: Add PostgreSQL Database → copy DATABASE_URL
1import os
2
3database_url = os.environ.get('DATABASE_URL')
4
5if database_url and database_url.startswith('postgres://'):
6 # Render uses postgres://, but SQLAlchemy needs postgresql://
7 database_url = database_url.replace('postgres://', 'postgresql://', 1)
8
9app.config['SQLALCHEMY_DATABASE_URI'] = database_url or 'sqlite:///dev.db'Flask automatically serves files from
static/, but in production it's better to use a CDN or Nginx.Basic Flask configuration:
1# app.py
2app = Flask(__name__)
3
4# Flask automatically serves static files from /static/
5# http://yourapp.com/static/css/style.cssIn templates:
1<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
2<script src="{{ url_for('static', filename='js/script.js') }}"></script>Dashboard → Your Web Service → Logs
Project → Your Service → Logs
1[2024-01-15 10:23:45] INFO: Starting gunicorn 21.2.0
2[2024-01-15 10:23:45] INFO: Listening at: http://0.0.0.0:10000
3[2024-01-15 10:23:45] INFO: Using worker: sync
4[2024-01-15 10:23:45] INFO: Booting worker with pid: 421git add .
2git commit -m "Update: Add new feature"
3git push origin mainAuto-deploy = push to GitHub → automatic deploy!
Instead of
safari-database.onrender.com you can use your own domain:safaridatabase.com)https://safaridatabase.com → Your application1# app.py
2import os
3from flask import Flask, render_template, redirect, url_for, flash
4from flask_login import LoginManager, login_user, logout_user, login_required, current_user
5from flask_sqlalchemy import SQLAlchemy
6
7app = Flask(__name__)
8
9# Configuration from environment variables
10app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY') or 'dev-key-change-in-production'
11app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL') or 'sqlite:///dev.db'
12app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
13
14# Fix for Render PostgreSQL URL
15if app.config['SQLALCHEMY_DATABASE_URI'].startswith('postgres://'):
16 app.config['SQLALCHEMY_DATABASE_URI'] = app.config['SQLALCHEMY_DATABASE_URI'].replace('postgres://', 'postgresql://', 1)
17
18db = SQLAlchemy(app)
19login_manager = LoginManager(app)
20login_manager.login_view = 'login'
21
22# Models, routes, etc...
23
24if __name__ == '__main__':
25 # Only for local development
26 port = int(os.environ.get('PORT', 5000))
27 app.run(host='0.0.0.0', port=port, debug=os.environ.get('FLASK_ENV') == 'development')In this lesson you learned:
Final Safari Analogy: Deployment is like the grand opening of a safari park - you prepared the infrastructure (code), hired staff (WSGI server), secured the park (SECRET_KEY, HTTPS), and opened the gates for tourists from all over the world (internet)! Your Flask application lives and runs 24/7 in the cloud!
You've built a complete web application with:
Safari Database is now LIVE and accessible to everyone on the internet!
Darwin is proud of you! Get ready for the next modules, where you'll learn advanced Python and AI techniques!