I know we are living in the era of zero-downtime deploy but given my website user base and the fact that it’s really simple and small, I thought an old school “maintenance page” would be enough for me at the moment.
My deployment process is executed by a single command, so it’s quite stable and fast.
For the sake of completeness, I would talk a bit about my deployment process.
I use Fabric, so I have a few micro tasks in a Python script. Tasks like config_nginx
, config_monit
etc.
I also have other bigger tasks that call those micro tasks in sequence, my two main tasks are config
and deploy
. I almost never use the config
task, let’s talk about what the deploy
task do:
- Set the
settings.py
environment variables; - Execute
git pull
; - Activate the
virtualenv
; - Install and upgrade the requirements packages with
pip
; - Execute the Django migrations;
- Collect the static files;
- Compress the static files with django-compressor;
- Notify Opbeat about the new release.
It’s really straight forward and simple to implement.
The maintenance mode
The following is a simplified version of my nginx configuration file:
server {
listen 80;
root /var/www/maintenance; [1]
location / {
if (-f $document_root/index.html) { [2]
return 503;
}
# the rest of you configuration goes here
}
error_page 503 @maintenance; [3]
location @maintenance { [4]
rewrite ^(.*)$ /index.html break; [5]
}
}
Let’s go to a basic definition of each point:
- Sets the root path for requests. I don’t use the root for any request, so I set it to a specific directory used for the maintenance mode;
- Check if there’s an
index.html
file in root directory. If the file exists I return the 503 Service Unavailable code; - The error_page directive is used to specify the
@maintenance
location to be used to process the request; - The
@
prefix means this location is a named location, as such it’s not accessible by the client, being used only by other directives aserror_page
; - Finally we simply serve the
index.html
document.
After altering the nginx configuration file for the website I created two other micro tasks in my Fabric script.
The first task simple copy the HTML document with an informative text about the maintenance process. This micro task is executed before every other task within the deploy task.
The other task is used to remove the index.html
document, setting back the website to it’s normal state. This task is executed as the last process within that major deploy task.
Now everytime I execute my deploy task the website is put into a maintenance mode and automatically pulled out from it.
I’ve also added the Google Analytics tracking code in this maintenance page. This way if the number of requests during the maintenance process consistently grow, I’ll start to focus on a zero-downtime deployment process.
I hope this could help you!