Django Deployment on Caprover by Docker Image

Using Only Docker & Serving Static Files Without Any Extra Tools — NO Captain CLI Commands or the Definition File.

3 min readJan 17, 2024


In this text we’ll explore how we can deploy and serve Django application on Caprover. The codebase that we are going to use is below.

Image by

The Problem

I deployed the codebase for several clients. However, I used Docker Compose to manage the deployment. When I try to deploy on Caprover, I thought I could serve static files by binding a volume. It didn’t work 🥲 I also have another repository for the frontend and we are going to see how we can manage requests with Nginx (proxy).

Digging The Problem

I setup my static locations to start with /django-static/ and /django-media/ for media files to have the chance to deploy 2 different codebase under the same domain. /static/ requests will go to React app and /django-*/ requests will go to the Django app.

Potential Solutions

Additional Nginx For Proxy

One of the solutions is to deploy another Nginx to proxy requests to appropriate pathes like below. However, I do not think this is acceptable by the best practices.

│ │
┌───────►│ app-python │
│ │ │
┌────────────────┤ └───────────────┘
┌─────────────────┐ │ │
│ captain-nginx ├──────────────►│ app-nginx │
└─────────────────┘ │ │ ┌────────────────┐
└────────────────┤ │ │
│ │ static files │
└───────►│ │

Captain Definition File

We can also create a definition file to use with the CLI. However, this is not appropriate for my CI & CD pipelines.


I deployed 2 services for each side of my app; frontend and backend. I bind /captain/data/nginx-shared/my-django-app-staticfiles to my backend service’s /app/static and /app/media folders that contain the collected staticfiles. If you wonder why I bind the folders specifically on my host, you should check the link below.

Long story short, it is because of we can not expose our volumes into the main Nginx service which is created by Caprover to map requests to the services we deployed. However, services’ Nginx configurations look under /captain/data/nginx-shared path and uses the files under the path if we set in the service’s Nginx configuration to use them.

In my backend service, I added the configuration lines below to my Nginx configuration.

location /django-static/ {
alias /nginx-shared/my-django-app-staticfiles/static/;

location /django-media/ {
alias /nginx-shared/my-django-app-staticfiles/media/;

I modified my frontend service too to manage the requests.

# out of the server block
upstream donation_app_be {
server srv-captain--my-django-app-be:8000; # this is the name of backend service

# inside the server block, we redirect our requests to the upstream
location /django-static/ {
alias /nginx-shared/babialem-donation-be/static/;

location /django-media/ {
alias /nginx-shared/babialem-donation-be/media/;


Hopefully, it helps you to deploy your Django apps easily. I also uploaded a video on my YouTube channel to explain how we can deploy FastAPI IoT gateway to Caprover. You can access it by using the link below.



Writer for

Lifelong learner & Developer. I use technology that helps me.