Tous les articles

Comment déployer une application Django au Canada

Ross Hill · 10 septembre 2026

Django se déploie sans complications sur un simple serveur Linux. Ce qui fait passer un projet Django de « ça marche en local » à « ça tourne en production » est partout la même chose : un vrai serveur WSGI, des paramètres lus depuis l'environnement, des fichiers statiques collectés, une base PostgreSQL et des migrations exécutées au bon moment. Faire tout cela sur une infrastructure canadienne n'ajoute aucune étape. Vous choisissez où se trouve la machine virtuelle (VM). La méthode, elle, ne change pas.

Ce billet parcourt l'ensemble du processus sur un serveur Coolify, avec l'application et sa base de données sur la même machine à Toronto.

Pourquoi au Canada

Certaines équipes ont une exigence contractuelle ou une politique interne qui impose que les données des clients restent au Canada. D'autres préfèrent simplement que leur infrastructure relève du droit canadien plutôt que d'une société mère américaine. Chacune de ces raisons suffit à elle seule. Notre dossier complet sur l'hébergement canadien couvre le volet juridictionnel, y compris pourquoi la région torontoise d'un fournisseur américain n'est pas la même chose qu'un fournisseur canadien.

La conséquence pratique pour une application Django est mince : choisissez un serveur dans une ville canadienne, et placez la base de données dessus ou juste à côté. Le reste de ce billet, c'est le déploiement.

Étape 1 : préparer le projet

La liste de vérification de déploiement de Django fait autorité ici, et elle est courte. Les points qui comptent le plus pour un déploiement en conteneur :

Utilisez un vrai serveur WSGI. manage.py runserver est un outil de développement. Gunicorn est le choix habituel, et le guide Gunicorn de Django tient sur une page. Un détail que cette page énonce explicitement et qui piège beaucoup de monde en conteneur : par défaut, Gunicorn démarre un processus, un fil d'exécution, à l'écoute sur 127.0.0.1:8000. Dans Docker, rien à l'extérieur du conteneur ne peut l'atteindre. Liez-le à 0.0.0.0.

Lisez les paramètres depuis l'environnement. La liste précise que la clé secrète doit être une grande valeur aléatoire et rester secrète, et que lorsque DEBUG = False, Django ne fonctionne tout simplement pas sans une valeur adéquate pour ALLOWED_HOSTS. Une version minimale :

import os
import dj_database_url

SECRET_KEY = os.environ["SECRET_KEY"]
DEBUG = os.environ.get("DEBUG", "false").lower() == "true"
ALLOWED_HOSTS = os.environ["ALLOWED_HOSTS"].split(",")
CSRF_TRUSTED_ORIGINS = [f"https://{h}" for h in ALLOWED_HOSTS]
DATABASES = {"default": dj_database_url.config(conn_max_age=600)}

Django n'analyse pas nativement une chaîne DATABASE_URL. dj-database-url, maintenu par Jazzband, lit cette variable et la convertit en dictionnaire DATABASES, ce qui tombe bien puisque c'est sous cette forme que la plupart des plateformes vous remettent une base de données. Les entrées de CSRF_TRUSTED_ORIGINS doivent inclure le protocole, donc https://exemple.com et non exemple.com.

Réglez la question des fichiers statiques. La liste de vérification est catégorique : en production, vous devez définir un répertoire STATIC_ROOT vers lequel collectstatic copiera les fichiers. La façon la plus simple de les servir depuis le conteneur de l'application est WhiteNoise, qui demande une seule entrée d'intergiciel placée juste après le SecurityMiddleware de Django, si vous l'utilisez, et avant tous les autres.

Installez le bon pilote PostgreSQL. Les notes de Django sur les bases de données indiquent que Django prend en charge PostgreSQL 15 et versions ultérieures, et qu'il faut psycopg 3.1.12+ ou psycopg2 2.9.9+, psycopg 3.1.12+ étant recommandé.

Étape 2 : choisir une méthode de build

Coolify peut construire à partir d'un Dockerfile, par détection automatique avec Nixpacks, ou à partir d'un fichier Docker Compose. Notre guide de déploiement Coolify compare les build packs plus en détail, et le résumé s'applique bien à Django : Nixpacks détecte habituellement un projet standard doté d'un requirements.txt, et un Dockerfile reste plus prévisible parce que c'est vous qui l'avez écrit.

Pour Django, j'écrirais le Dockerfile. Une dizaine de lignes suffisent :

FROM python:3.13-slim
ENV PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
CMD ["gunicorn", "myproject.wsgi", "--bind", "0.0.0.0:8000"]

Un piège s'y cache. collectstatic importe votre module de paramètres, alors tout ce que ces paramètres lisent dans l'environnement au moment de l'importation doit exister pendant le build. Si SECRET_KEY = os.environ["SECRET_KEY"] déclenche une KeyError dans vos journaux de build, passez une valeur jetable en argument de build ou déplacez collectstatic dans la commande de démarrage du conteneur.

Étape 3 : créer la base PostgreSQL

Dans Coolify, ajoutez une ressource PostgreSQL au même projet que votre application. Elle s'exécute comme un conteneur sur la même VM, et Coolify vous montre une URL de connexion interne dans la forme habituelle :

postgres://user:password@<container-name>:5432/dbname

La documentation de Coolify pose clairement la condition : si la base de données et l'application sont sur le même réseau, vous l'atteignez avec cette URL interne, sinon vous devez rendre la base accessible depuis Internet et utiliser l'URL publique. Gardez-les dans le même projet pour utiliser l'URL interne et laisser la base non exposée.

Collez cette URL dans la variable d'environnement DATABASE_URL de votre application et dj_database_url.config() s'en occupe. Cohéberger l'application et la base de cette façon signifie aussi qu'il n'y a qu'un seul emplacement à vérifier pour la résidence des données au lieu de deux, ce qui est l'argument de notre billet sur le PostgreSQL géré au Canada.

Étape 4 : déployer

Définissez les variables d'environnement de l'application dans Coolify : SECRET_KEY, DATABASE_URL, ALLOWED_HOSTS, et tout ce que vos paramètres lisent d'autre. Réglez Ports Exposes à 8000 pour correspondre à la liaison Gunicorn ci-dessus, puis déployez. Coolify récupère le dépôt, construit l'image, démarre le conteneur et vous donne une URL temporaire pour tester avant même qu'un DNS existe.

Si vous n'avez jamais déployé sur Coolify, déployez votre première application explique plus en détail la connexion du fournisseur Git et la lecture des journaux de build.

Étape 5 : exécuter les migrations

Les applications Coolify disposent de champs de commande Pre-deployment et Post-deployment. Mettez votre migration dans celle de post-déploiement :

python manage.py migrate --noinput

Les noms suggèrent l'inverse, mais Coolify exécute la commande de pré-déploiement dans le conteneur déjà en cours d'exécution, et la saute entièrement s'il n'y en a aucun. C'est donc l'ancien code, pas les migrations que vous déployez, et lors d'un premier déploiement il ne se passe rien du tout. La commande de post-déploiement s'exécute dans le conteneur fraîchement construit, celui qui contient vos nouveaux fichiers de migration.

Ce conteneur sert déjà le trafic au moment où la commande s'exécute, alors gardez chaque migration compatible avec la version qu'elle remplace. Pour un cas ponctuel comme createsuperuser au premier démarrage, ouvrez le terminal de Coolify sur le conteneur de l'application et lancez-la là.

Étape 6 : domaine et TLS

Pointez un enregistrement A vers l'adresse IP de votre serveur, puis inscrivez l'URL complète dans le champ Domains de l'application, par exemple https://exemple.com. Le proxy Traefik de Coolify demande un certificat Let's Encrypt dès que le DNS résout vers le serveur, et le renouvelle.

Deux paramètres Django découlent de cette position derrière un proxy. Le TLS se termine à Traefik, alors Django voit une requête HTTP ordinaire à moins que vous ne lui indiquiez le contraire, et c'est le rôle de SECURE_PROXY_SSL_HEADER :

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

La condition posée par Django est plus étroite qu'il n'y paraît : ne définissez ce paramètre que si vous contrôlez votre proxy ou si vous avez une autre garantie qu'il pose et retire cet en-tête correctement. Vous avez un accès root sur la VM, donc le proxy est à vous d'inspecter. La page des paramètres vous demande ensuite de vérifier deux choses à son sujet : qu'il rejette tout X-Forwarded-Proto envoyé par le client, et qu'il pose lui-même l'en-tête uniquement pour les requêtes arrivées en HTTPS. Vérifiez les deux sur votre instance avant d'activer le paramètre. Ajoutez ensuite votre domaine à ALLOWED_HOSTS, qui alimente aussi CSRF_TRUSTED_ORIGINS dans l'extrait de code plus haut.

Terminez en exécutant python manage.py check --deploy avec vos paramètres de production. La commande signale ce qui reste, dont SESSION_COOKIE_SECURE et CSRF_COOKIE_SECURE, que la liste de vérification recommande de mettre à True pour que ces témoins ne circulent jamais en HTTP.

Ce que MapleDeploy gère, et ce que vous gérez

« Géré » ne veut pas dire la même chose d'une plateforme à l'autre.

Nous gérons : la VM à Toronto, le système d'exploitation et ses mises à jour de sécurité (les redémarrages du noyau se font dans une fenêtre fixe à 8 h UTC), l'installation de Coolify et ses mises à jour, la surveillance de disponibilité du serveur lui-même plutôt que de votre application, et des instantanés hebdomadaires du serveur complet.

Vous gérez : votre code Django, votre Dockerfile ou votre configuration de build, vos variables d'environnement, vos migrations, le schéma de votre base et son horaire de sauvegarde, ainsi que la répartition de la RAM et du processeur entre ce que vous y faites tourner.

Ces instantanés relèvent de la reprise après sinistre, pas de la sauvegarde de base de données. Un instantané peut dater de jusqu'à sept jours, et votre base se trouve sur la même VM que l'application, alors configurez la sauvegarde de base intégrée de Coolify vers un stockage compatible S3 comme deuxième couche. Notre guide des sauvegardes précise les limites de chacune.

Nous n'examinons pas vos paramètres Django ni les versions de vos dépendances. Cette liste vous appartient chez n'importe quel hébergeur, celui-ci compris. La couche en dessous, elle, nous revient. Si le problème vient de la VM, de Coolify ou du réseau, écrivez à hello@mapledeploy.ca.

Les forfaits vont de 45 $ CA par mois pour 4 Go de RAM et 2 vCPU jusqu'à 695 $ CA pour 64 Go, à prix mensuel fixe et sans facturation par service pour la base de données. Les forfaits Starter et Pro comprennent un essai gratuit de 30 jours. C'est assez de temps pour y installer le vrai projet et voir si 4 Go est la bonne taille avant de payer quoi que ce soit.

Déployez Django sur un serveur canadien

Votre application et sa base PostgreSQL sur une VM dédiée à Toronto. 30 jours gratuits sur les forfaits Starter et Pro.