I recently spent a few painful hours deploying Django on Azure App Service. Documentation was lacking and I lost way too much time with trivial issues, so here’s a summary of the problems I encountered.
The setup:
- Linux Development server with Django 1.11.3 on Python 2.7, and MySQL
- A relatively cheap Azure App Service plan for Python
- A MySQL database hosted by ClearDB for Azure
Getting the MySQL driver for Django to work on Azure App Service
The standard MySQL driver used in Django is MySQL-python
, which needs compiling when installed via pip
. Since you can’t install a compiler in your App Service account, you need to provide a compiled version of the library, which means you have two options:
- compiling it yourself, or
- downloading it from somewhere.
Compiling it on Windows was not an option, so I downloaded a wheel
from Christoph Gohlke’s very useful site.
The following was useful to know:
- If you chose one of the cheaper App Service plans and didn’t fiddle with the configuration, your plan runs 32 bit, and you need one of the packages that end in
-win32.whl
. MySQL-python
looks outdated, butmysqlclient
replaces it, so that’s what I used.- In your
requirements.txt
, you can specify the path to awhl
file instead of the name of a package. In my case that wasmysqlclient-1.3.10-cp27-cp27m-win32.whl
, which I had downloaded from the site mentioned above. - If on deployment to Azure you get an error about the
wheel
file (I forgot the exact wording), it could be because your App Service plan runs an old version ofpip
. In that case navigate the Azure portal maze until you find a usable console, and upgradepip
from the command line. The install went smoothly after that. - In order to avoid all the problems with compilation or wheels, you might be tempted to go for a pure python library like
PyMySQL
. I didn’t go down that route for two reasons:PyMySQL
requires some rather ugly hacks at the top of various files in order to provide the same API asMySQL-python
.- In the future, you might want to use packages such as
NumPy
for which there are no pure Python versions. If so, you will have install packages from wheels anyway, so you might as well figure it out now.
The curious wonders of web.config
If you happen to develop on Windows, it’s probably easiest to just start with the sample Django project that Microsoft provides, and follow along with their tutorials using Visual Studio and whatever tools they recommend. You’ll have better chances of getting a working configuration, including a working web.config
, than if you follow some random blogger’s advice from the depths of the internet (irony detected).
Having little experience with IIS, I wasn’t familiar with the strange web.config
syntax. Anyway, one thing you need to get right is the appSettings
part, which in my case looked like this:
<appSettings>
<add key="WSGI_ALT_VIRTUALENV_HANDLER" value="django.core.wsgi.get_wsgi_application()" />
<add key="WSGI_ALT_VIRTUALENV_ACTIVATE_THIS" value="D:\home\site\wwwroot\env\Scripts\activate_this.py" />
<add key="WSGI_HANDLER" value="ptvs_virtualenv_proxy.get_virtualenv_handler()" />
<add key="PYTHONPATH" value="D:\home\site\wwwroot" />
<add key="DJANGO_SETTINGS_MODULE" value="src.settings" />
</appSettings>
Since I was developing on Linux, I didn’t have ptvs_virtualenv_proxy.py
in my folder, but I downloaded it from the official example repository. I’m not sure why it’s needed, but it seems to do be doing whatever job it needs to do.
Accessing your MySQL database on ClearDB
Your Azure portal will provide a link to a plain-looking but functional dashboard by ClearDB. That dashboard will give you all parameters you need in the database section of your settings.py
, which looks something like this:
'ENGINE': 'django.db.backends.mysql',
'NAME': 'DATABASE-NAME-HERE',
'USER': 'USERNAME-HERE',
'PASSWORD': 'PASSWORD-HERE',
'HOST': 'eu-cdbr-azure-west-b.cloudapp.net',
'PORT': '3306',
'OPTIONS': {'ssl': {'ca': 'ssl/cleardb-ca.pem',
'cert': 'ssl/YOUR-RANDOM-CODE-cert.pem',
'key': 'ssl/YOUR-RANDOM-CODE-key2.pem'}
}
The three PEM files used for SSL were also provided for download on the ClearDB dashboard. However, both the mysqlclient
library and the actual command line mysql
client refused to read the key file:
SSL error: Unable to get private key from ‘ssl/YOUR-RANDOM-CODE-key.pem’ ERROR 2026 (HY000): SSL connection error: Unable to get private key
The issue was that the PEM file containing the private key did not have the exact format required. This was fixed using:
The private key file downloaded from ClearDB had the header
-----BEGIN PRIVATE KEY-----
with the file
command somewhat helplessly identifying the format as ASCII text
. After the conversion using the command above, the header became
-----BEGIN RSA PRIVATE KEY-----
and the file
command gave the format as PEM RSA private key
.
The infuriating case of failed request tracing on Azure
The unfortunate reality of using Python is that you’ll have to deal with exceptions at runtime. When they happen on the server, it’s crucial to get some visibility into what went wrong, usually in the form of a traceback.
There is this very useful option called Failed request tracing
that you can activate on the Azure Dashboard under Diagnostic logs
.
However, the most infuriating thing about this entire Python on Azure experience is that this crucial little option just turns itself off with no warning. Some sources say it happens after 24 hours, but it was clearly less than that in my case. Why doesn’t the user interface say anything about that?
Summary
- If you have any choice, avoid running code on platforms where the language is clearly not a first-class citizen. Everything sounds great when you read the glossy marketing materials, but a good experience with Python/Django on Azure is clearly not Microsoft’s priority. It’s no surprise then that AWS is a more popular choice than Azure for Django apps.
- Remember your Python installation on Azure App service could be 32 bit.
- Try upgrading
pip
if it has issues installing awheel
file. - The fact that a file ends in PEM doesn’t tell you much about the format of its content. If you encounter problems, check the exact format of the file.