Deploying your first Django App
Tags: django, beginners, python, fly
Published: 2024-01-02 14:12:11

When you create a Django project using the `startproject` command, settings are default for local development, many of which are not appropriate in production. 

As a simple starter I want to learn how to deploy a Django application into production using a Platform as a Service provider (PaaS). 

For that I will need a [Python WSGI](https://www.fullstackpython.com/wsgi-servers.html)(Web Server Gateway Interface). I will be using [Gunicorn](https://gunicorn.org/) for this. 

### Gunicorn

Gunicorn replaces the Django local development server and is installable with pip: 

```
python3 -m pip install gunicorn==20.1.0
```

### Requirements file

Once installed, in my Django projects virtual environment, I need to ensure that a valid `requirements.txt` file exists containing all the python packages needed to run our project: 

```
python3 -m pip freeze > requirements.txt
```
 
### Django project settings

I now need to update the `ALLOWED_HOSTS` list in my `django-project/settings.py` to represent which host/domain that my site can serve. 

This is a security measure to prevent HTTP Host header attacks. When getting started you can simply use "*" wildcard in order to allow all domains, but make sure you configure this more specifically for your projects going forwards. 

### Docker ignore file

Finally I am going to create a `.dockerignore` file in the project root directory. As a minimum, I want to ignore our local virtual environment, SQLite database an Git repo. 

```
# .dockerignore file contents
.venv/
*.sqlite3
.git
```

### Fly.io 

I have previously used Heroku for side project hosting, however as of Nov 2022, Heroku (understandably) no longer offer a free tier. 

I will therefore be using [Fly.io](https://fly.io/) to host my app. You will need to sign up for an account and a payment method. In my experience, provided you site isn't attracting traffic and costs less than $5 per month, then Fly.io wave the fees and it is free. 

Fly has its own CLI (Command Line Interface) which you can install following the [official docs](https://fly.io/docs/hands-on/install-flyctl/)

Once installed we login: 
```
flyctl auth login
```

I then run the `fly launch` command to configure and launch my site: 

```
fly launch
```
Provided you do this in the terminal within your virtual environment at the root of your project, Fly should automatically detect you are running a Django app. Make sure you don't overwrite the `.dockerignore` file. 

Once complete you should see two new files in your project directory. 
- `fly.toml`
- `Dockerfile`

The `fly.toml` is a Fly-specific config file and the Dockerfile contains instructions for creating a Docker image on Fly servers. 

#### deploying on Fly
To deploy our app onto Fly servers run the following 

```
flyctl deploy
```
The initial deploy will take a few seconds as it comprises  of uploading your application, verifies the app configuration, builds the Docker image and then monitors to ensure the app starts successfully. 

Once complete, you can visit your app in production with `fly open` command:

```
fly apps open
```
If you have any issues you can view the logs via `fly logs`.

**Note:** I'm not quite sure why some Fly commands require `flyctl` while others require `fly`, if in doubt check their docs.

### Summary of deployment

Our Django site is running on a Docker virtual machine created via the `Dockerfile` in our project. The `fly.toml` configures our website settings and can be modified as needed. 

You can run `fly dashboard` via the command line to load uour browser-based view to manage your Fly deployments. 


## Caveats 

I have taken several security shortcuts here as my goal is purely to push my first project into production in as few steps as possible. This steps are not advisable for real production systems that will be used in anger.

I intend to document proper security around deployments in the future as my learning continues. 

I also haven't compiled static files into one location for production. That too is something I will explore as I continue to learn. This really was about deploying the most minimal app to production.