{"id":33488,"date":"2022-04-08T12:00:53","date_gmt":"2022-04-08T16:00:53","guid":{"rendered":"https:\/\/blog.logrocket.com\/?p=33488"},"modified":"2024-06-04T17:09:40","modified_gmt":"2024-06-04T21:09:40","slug":"dockerizing-django-app","status":"publish","type":"post","link":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/","title":{"rendered":"Dockerizing a Django app"},"content":{"rendered":"<!DOCTYPE html>\n<html><p>\u200b\u200b<em><strong>Editor\u2019s note:<\/strong> This article was updated on 8 April 2022 to provide more information to some key terms, explain each of the commands in the Dockerfile, and break down the Django app setup into clearer steps.<\/em><\/p><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"487\" src=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png\" class=\"attachment-full size-full wp-post-image\" alt=\"Dockerize Django App\" srcset=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png 730w, https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1-300x200.png 300w\" sizes=\"auto, (max-width: 730px) 100vw, 730px\">\n<p>To actualize a Django project, most of the time you need an off-the-shelf solution in the form of a library or dependency.<\/p>\n<p>This is typically not an issue, and is often documented in the <code>requirements.txt<\/code> file that will contain the list of packages or dependencies along with their respective version that you need to run your project.<\/p>\n<p>The trouble starts when you attempt to share the entire project with another individual who wishes to run and test it because, unfortunately, the user will have to perform the setup from scratch every time you make significant changes in the libraries and dependencies.<\/p>\n<p>This is where containerization and <a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"noopener\">Docker<\/a> come in. Docker isolates your application and its dependencies and ensures consistent runtime protocols for your applications regardless of the configurations of the servers hosting your application.<\/p>\n<p>This guide will walk you through setting up a Django project with Docker, including:<\/p>\n<ul>\n<li><a href=\"#what-is-docker\">What is Docker?<\/a><\/li>\n<li><a href=\"#why-should-you-use-docker\">Why should you use Docker?<\/a><\/li>\n<li><a href=\"#prerequisites-for-using-docker\">Prerequisites for using Docker<\/a><\/li>\n<li><a href=\"#docker-installation\">Docker installation<\/a><\/li>\n<li><a href=\"#setting-up-the-django-app\">Setting up and Dockerizing a Django app<\/a><\/li>\n<li><a href=\"#creating-the-docker-files-and-docker-cli\">Creating the Dockerfiles and Docker CLI<\/a><\/li>\n<li><a href=\"#running-the-app-in-docker\">Running the app in Docker<\/a><\/li>\n<li><a href=\"#running-multiple-containers-with-docker-compose\">Running multiple containers with Docker Compose<\/a><\/li>\n<li><a href=\"#using-docker-compose-with-a-django-app\">Using Docker Compose with a Django app<\/a><\/li>\n<li><a href=\"#building-and-running-docker-compose-scripts\">Building and running Docker Compose scripts<\/a><\/li>\n<li><a href=\"#supporting-files-in-django-application\">Supporting files in a Django application<\/a><\/li>\n<\/ul>\n<h2 id=\"what-is-docker\">What is Docker?<\/h2>\n<p>Docker is an open-source tool that manages the development, testing and deployment of <a href=\"https:\/\/www.docker.com\/resources\/what-container\" target=\"_blank\" rel=\"noopener\">containerized applications<\/a>.<\/p>\n<p>It offers hardware virtualization at the OS level and is suitable for modern architecture. This allows developers to package and ship software and its dependencies in order to distribute it as containers.<\/p>\n<p>It\u2019s an incredibly popular containerization platform that solves the library and dependency issues once and for all.<\/p>\n<p>But its best feature? Regardless of host or underlying infrastructure, your containerized application will always run the same way.<\/p>\n<p>In simple terms, you can now wrap up all the pieces your software needs in a single unit, called a Docker image, then ship or share this image with anyone. As long as the recipient has Docker installed on their machine, they will be able to run or test your project. Gone are the days of wondering why a project works on one machine and not another.<\/p>\n<p>Docker also offers a service called <a href=\"https:\/\/hub.docker.com\/\" target=\"_blank\" rel=\"noopener\">DockerHub<\/a> that allows you to share and manage Docker images among other developers and larger communities \u2014 essentially, it\u2019s a \u201cGitHub\u201d for Docker images.<\/p>\n<p>It shares some similarities with the code repository platform, such as uploading and downloading images via CLI commands contained within the Docker CLI.<\/p>\n<h2 id=\"why-should-you-use-docker\">Why should you use Docker?<\/h2>\n<h3>Remote services<\/h3>\n<p>A developer can pull Docker images from <a href=\"https:\/\/hub.docker.com\/\">Docker Hub<\/a>&nbsp;to any machine that hosts its containers. Implying that you can always retrieve a Docker image, build it, and run an instance of it from wherever you are and whenever you want.<\/p>\n<h3>Cost efficiency<\/h3>\n<p>Docker allows you to support several containers with one infrastructure rather than using multiple virtual machines to run identical copies of the virtual OS managed by the hypervisor, which can be expensive to maintain.<\/p>\n<h3>Scalability<\/h3>\n<p>Docker containers can efficiently scale-up applications to withstand more load and automatically decrease the computing load of your application when the amount of requests reduces.<\/p>\n<h3>Security<\/h3>\n<p>Containers are immutable, meaning that when you change the configuration of an image, you have to rebuild the image and run a new instance.<\/p>\n<h2 id=\"prerequisites-for-using-docker\">Prerequisites for using Docker<\/h2>\n<ul>\n<li>Proficiency in Django development<\/li>\n<li>Intermediate level with CLI and <a href=\"https:\/\/linuxconfig.org\/bash-scripting-tutorial-for-beginners\" target=\"_blank\" rel=\"noopener\">bash<\/a><\/li>\n<\/ul>\n<h2 id=\"docker-installation\">Docker installation<\/h2>\n<p>This tutorial uses YAML files to perform Docker scripting and executes the files via the Docker CLI. This guide will explore setting up Docker on an Ubuntu machine. If you are using a different OS, you can check out the documentation for getting started with <a href=\"https:\/\/docs.docker.com\/docker-for-windows\/install\/\" target=\"_blank\" rel=\"noopener\">Windows<\/a> and <a href=\"https:\/\/docs.docker.com\/docker-for-mac\/install\/\" target=\"_blank\" rel=\"noopener\">macOS<\/a>.<\/p>\n<p>To download and set up Docker, run the command below on your terminal:<\/p>\n<pre class=\"language-shell hljs\">sudo apt-get update  \nsudo apt-get install docker-ce docker-ce-cli containerd.io  \n<\/pre>\n<h2 id=\"setting-up-the-django-app\">Setting up and Dockerizing a Django app<\/h2>\n<p>This guide assumes you are already proficient in Django, so there won\u2019t be any emphasis on the structure of a Django app. If you are new to Django, <a href=\"https:\/\/blog.logrocket.com\/creating-an-app-with-react-and-django\/\" target=\"_blank\" rel=\"noopener\">here<\/a> is a tutorial to get you up to speed.<\/p>\n<p>Let\u2019s skip ahead to the steps for running a basic Django REST framework app in Docker and displaying the default page. Consider it the <code>Hello, world!<\/code> of Django and Docker.<\/p>\n<p>Using the guide provided in this tutorial, you can Dockerize any previous or future Django project you may have, especially one that has libraries listed in <code>requirements.txt<\/code>.<\/p>\n<h3 id=\"step1\">Step 1<\/h3>\n<p>To start, run the below command and follow the steps afterwards:<\/p>\n<pre class=\"language-shell hljs\">django-admin startproject dj_docker_drf\n<\/pre>\n<ul>\n<li>Navigate into your project folder<\/li>\n<li>Start an app named <code>sample<\/code><\/li>\n<li>Add <code>rest_framework<\/code> and <code>sample<\/code> to the <code>INSTALLED_APPS<\/code> list in <code>settings.py<\/code><\/li>\n<\/ul>\n<h3 id=\"step2\">Step 2<\/h3>\n<p>In the <code>views.py<\/code> file, add the below code snippet that returns the message, \u201cHELLO WORLD FROM DJANGO AND DOCKER\u201d.<\/p>\n<pre class=\"language-python hljs\">from rest_framework.views import APIView  \nfrom django.http import JsonResponse  \n\nclass HomeView(APIView):  \n\n def get(self, request, format=None):\n    return JsonResponse({\"message\":\n    'HELLO WORLD FROM DJANGO AND DOCKER'})  \n<\/pre>\n<h3 id=\"step3\">Step 3<\/h3>\n<p>Connect the main URL file and the app URL file so that <code>HomeView<\/code> is the default view when a user accesses the app on the browser.<\/p>\n<p>In order to allow access to the Django app from any server or IP address, ensure that <code>ALLOWED_HOSTS<\/code> in the <code>settings.py<\/code> file is set to <code>*<\/code>, as shown in the snippet below:<\/p>\n<pre>ALLOWED_HOSTS = [\u2018*\u2019]\n<\/pre>\n<h3 id=\"step4\">Step 4<\/h3>\n<p>Finally, create a <code>requirements.txt<\/code> file in your root project folder and add the DRF library:<\/p>\n<pre>django-rest-framework==0.1.0  \n<\/pre>\n<p>The app is now ready to be Dockerized.<\/p>\n<h2 id=\"creating-the-docker-files-and-docker-cli\">Creating the Dockerfiles and Docker CLI<\/h2>\n<p>Notice that the Dockerfile is named. This is to allow the Docker CLI to track it.<\/p>\n<p>In your project root, create a file named <code>Dockerfile<\/code> without an extension and add the following snippet to the file:<\/p>\n<pre># base image  \nFROM python:3.8   \n# setup environment variable  \nENV DockerHOME=\/home\/app\/webapp  \n\n# set work directory  \nRUN mkdir -p $DockerHOME  \n\n# where your code lives  \nWORKDIR $DockerHOME  \n\n# set environment variables  \nENV PYTHONDONTWRITEBYTECODE 1\nENV PYTHONUNBUFFERED 1  \n\n# install dependencies  \nRUN pip install --upgrade pip  \n\n# copy whole project to your docker home directory. \nCOPY . $DockerHOME  \n# run this command to install all dependencies  \nRUN pip install -r requirements.txt  \n# port where the Django app runs  \nEXPOSE 8000  \n# start server  \nCMD python manage.py runserver  \n<\/pre>\n<p>Let\u2019s explore the Dockerfile and what each of the commands do.<\/p>\n<ul>\n<li><code>FROM python:3.8<\/code> : This installs a Python image into the Docker image. This is also the version of Python that will run the application in the container<\/li>\n<li><code>ENV DockerHOME=\/home\/app\/webapp<\/code>: Here we declare the working directory and assign it to the variable name <code>DockerHOME<\/code>. This will be the root directory of the Django app in the container<\/li>\n<li><code>RUN mkdir -p $DockerHOME<\/code>: This creates the directory with the specified path assigned to the <code>DockerHOME<\/code> variable within the image<\/li>\n<li><code>WORKDIR $DockerHOME<\/code>: This explicitly tells Docker to set the provided directory as the location where the application will reside within the container<\/li>\n<li><code>RUN pip install --upgrade pip<\/code>: This updates the <code>pip<\/code> version that will be used to install the dependencies for the application<\/li>\n<li><code>COPY . $DockerHOME<\/code>: This copies every other necessary file and its respective contents into the app folder that is the root directory of the application within the container<\/li>\n<li><code>RUN pip install -r requirements.txt<\/code>: This command installs all the dependencies defined in the <code>requirements.txt<\/code> file into your application within the container<\/li>\n<li><code>EXPOSE 8000<\/code>: This command releases port 8000 within the container, where the Django app will run<\/li>\n<li><code>CMD python manage.py runserver<\/code>: This command starts the server and runs the application<\/li>\n<\/ul>\n<h2 id=\"running-the-app-in-docker\">Running the app in Docker<\/h2>\n<p>To run the app, you need to perform two steps:<\/p>\n<ol>\n<li>Build the image: This is done using the <code>build<\/code> command, which uses the <code>Dockerfile<\/code> you just created. To build the image, run the command below:<code>docker build . -t docker-django-v0.0<\/code>.This command should be executed in the directory where the Docker file lives. The <code>-t<\/code> flag tags the image so that it can be referenced when you want to run the container.<\/li>\n<li>Run the image: This is done using the <code>docker run<\/code> command. This will convert the built image into a running container. To run the app, execute the below command:<code>docker run docker-django-v0.0<\/code><\/li>\n<\/ol>\n<p>You can proceed to view your app in the browser at localhost:8000.<\/p>\n<h2 id=\"running-multiple-containers-with-docker-compose\">Running multiple containers with Docker Compose<\/h2>\n<p>There are instances where you may want to run multiple containers in Docker and execute them in a specific order.<\/p>\n<p>This is where <a href=\"https:\/\/docs.docker.com\/compose\/\" target=\"_blank\" rel=\"noopener\">Docker Compose<\/a> comes in handy.<\/p>\n<p>Docker Compose is a tool for defining and running multi-container applications of any kind. If you have an application comprising several containers, you will use the Docker Compose CLI to run them all in the required order that you specify.<\/p>\n<p>Take, for example, a web application with the following components:<\/p>\n<ol>\n<li>Web server container such as <a href=\"https:\/\/www.nginx.com\/\" target=\"_blank\" rel=\"noopener\">Nginx<\/a><\/li>\n<li>Application container that hosts the Django app<\/li>\n<li>Database container that hosts the production database, such as PostgreSQL<\/li>\n<li>A message container that hosts the message broker, such as <a href=\"https:\/\/www.rabbitmq.com\/\" target=\"_blank\" rel=\"noopener\">RabbitMQ<\/a><\/li>\n<\/ol>\n<p>To run such a system, you will declare the directives in a Docker Compose YAML file. Here, you define how the images will be built, on which port will each of the images will be accessible, and most importantly, the order in which the containers should execute (i.e., which container depends on another container for the project to run successfully).<\/p>\n<h2 id=\"using-docker-compose-with-a-django-app\">Using Docker Compose with a Django app<\/h2>\n<p>Let\u2019s explore Docker Compose using the scenario demonstrated above: a Django app with a PostgreSQL database, RabbitMQ message broker, and an Nginx load balancer. Follow this <a href=\"https:\/\/docs.docker.com\/compose\/install\/\" target=\"_blank\" rel=\"noopener\">guide<\/a> to install the CLI tool on your host operating system.<\/p>\n<p>With Docker Compose (and, similarly to Docker), a particular file with a specific name is required. The CLI tool reads this file and uses it to spin up the Docker images and run them.<\/p>\n<p>To create a Docker Compose file, create a YAML file and name it <code>docker-compose.yml<\/code>. This ideally should exist at the root directory of your project.<\/p>\n<pre class=\"language-yaml hljs\">version: '3.7'\n\nservices: # the different images that will be running as containers\n  nginx: # service name\n\n# location of the dockerfile that defines the nginx image. The dockerfile will be used to spin up an image during the build stage.\n    build: .\/nginx \n\n# map the machine port 1339 to the container port 80. Any traffic from 1339 externally will be passed to port 80 of the NGINX container. You can access this container viea localhost:1339\n    ports: - 1339:80 \n\n\n# static storages provisioned since django does not handle static files in production\n    volumes:  - static_volume:\/home\/app\/microservice\/static \n\n# will only start if web is up and running\n    depends_on: - web \n\n# restart service when it fails\n    restart: \"on-failure\" \n\n  web: # service name\n\n#build the image for the web service from the dockerfile in parent directory.  \n    build: . \n\n# command directive passes the parameters to the service and they will be executed by the service. In this example, these are django commands which will be executed in the container where django lives.\n    command: sh -c \"python manage.py makemigrations &amp;&amp;\n                    python manage.py migrate &amp;&amp;\n                    gunicorn microservice_sample_app.wsgi:application --bind 0.0.0.0:${APP_PORT}\" \n\n# map data and files from parent directory in host to microservice directory in docker container\n    volumes: - .:\/microservice \n\n    - static_volume:\/home\/app\/microservice\/static\n\n# file where env variables are stored. Used as best practice so as not to expose secret keys\n    env_file: - .env # name of the env file\n\n# name of the image\n    image: microservice_app \n\n# expose the port to other services defined here so that they can access this service via the exposed port. In the case of Django, this is 8000 by default\n    expose: \n      - ${APP_PORT} # retrieved from the .env file\n\n    restart: \"on-failure\"\n\n# cannot start if db service is not up and running\n    depends_on: - db\n\n\n  db: # service name\n\n# image name of the postgres database. during build, this will be pulled from dockerhub and a container spun up from it.\n    image: postgres:11-alpine \n\n    volumes:\n      - .\/init.sql:\/docker-entrypoint-initdb.d\/init.sql\n      - postgres_data:\/var\/lib\/postgresql\/data\/\n\n# access credentials from the .env file\n    environment: \n      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\n      - POSTGRES_DB=${DB_NAME}\n      - PGPORT=${DB_PORT}\n      - POSTGRES_USER=${POSTGRES_USER}\n\n    restart: \"on-failure\"\n\n\n  rabbitmq:\n    image: \n      rabbitmq:3-management-alpine #image to be pulled from dockerhub during building\n    container_name: rabbitmq # container name\n    volumes: # assign static storage for rabbitmq to run\n      rabbitmq: - .\/.docker\/rabbitmq\/etc\/:\/etc\/rabbitmq\/\n        - .\/.docker\/rabbitmq\/data\/:\/var\/lib\/rabbitmq\/\n    rabbitmq_logs:  - .\/.docker\/rabbitmq\/logs\/:\/var\/log\/rabbitmq\/\n    environment: # environment variables from the referenced .env file\n      RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE}\n         # auth cretendials\n      RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER} \n      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS}\n    ports: # map external ports to this specific container's internal ports\n      - 5672:5672\n      - 15672:15672\n\n# can only start if web service is running\n    depends_on: \n      - web\n\n\nvolumes:\n  postgres_data:\n  static_volume:\n  rabbitmq:\n  rabbitmq_logs:\n<\/pre>\n<p>One of the highlights of Docker Compose is the <code>depends_on<\/code> directive. From the above script, we can deduce that:<\/p>\n<ul>\n<li>Nginx depends on web<\/li>\n<li>Web depends on DB<\/li>\n<li>RabbitMQ depends on web<\/li>\n<\/ul>\n<p>With this setup, DB is the first service we need to start up, followed by web, then RabbitMQ, and lastly, Nginx.<\/p>\n<p>When you decide to terminate the environment and stop the running containers, the order will be in reverse \u2014 that is, Nginx will be the first to run and DB the last.<\/p>\n<h2 id=\"building-and-running-docker-compose-scripts\">Building and running Docker Compose scripts<\/h2>\n<p>Just like a Docker script, the Docker Compose script has a similar structure in that it has <code>build<\/code> and <code>run<\/code> commands.<\/p>\n<p>The <code>build<\/code> command will build all the images defined under <code>services<\/code> within the <code>docker-compose.yml<\/code> in the order of the dependency hierarchy.<\/p>\n<p>Luckily, there is also a command that combines both <code>build<\/code> and <code>run<\/code> \u2014 this is called <code>up<\/code>. To run this command, execute the command here:<\/p>\n<pre> docker-compose up\n<\/pre>\n<p>You can also add the <code>--build<\/code> flag. This is useful when you\u2019ve run this command before and want to build new images.<\/p>\n<pre>docker-compose up --build\n<\/pre>\n<p>Once you\u2019re done with the containers, you may wish to shut them all down and remove any static storage they were using, such as the PostgreSQL static volume. To do this, run the following command:<\/p>\n<pre>docker-compose down -V\n<\/pre>\n<p>The <code>-V<\/code> flag stands for volumes. This ensures that the containers and attached volumes are shut down.<\/p>\n<p>Follow the official <a href=\"https:\/\/docs.docker.com\/compose\/reference\/\" target=\"_blank\" rel=\"noopener\">documentation<\/a> to learn more about various Docker Compose commands and their usage.<\/p>\n<h2 id=\"supporting-files-in-django-application\">Supporting files in a Django application<\/h2>\n<p>There are some files referenced in the script above that make the file less bulky, thus making code management easier. These include the <code>.env<\/code> file, the Nginx\u2019s Dockerfile and config files. Below are samples of what each entails:<\/p>\n<h3 id=\"envfile\"><code>.env<\/code> file<\/h3>\n<p>The main purpose of this file is to store variables, such as keys and credentials. Environment variables are a set of key-value pairs for the current user environment. This is a safe coding practice that ensures your personal keys are not exposed.<\/p>\n<pre class=\"language-python hljs\">#Django\nSECRET_KEY=\"my_secret_key\"\nDEBUG=1\nALLOWED_HOSTS=localhost 127.0.0.1 0.0.0.0 [::1] *\n\n\n# database access credentials\nENGINE=django.db.backends.postgresql\nDB_NAME=testdb\nPOSTGRES_USER=testuser\nPOSTGRES_PASSWORD=testpassword\nDB_HOST=db\nDB_PORT=5432\nAPP_PORT=8000\n#superuser details\nDJANGO_SU_NAME=test\nDJANGO_SU_EMAIL=admin12@admin.com\nDJANGO_SU_PASSWORD=mypass123\n#rabbitmq\nRABBITMQ_ERLANG_COOKIE: test_cookie\nRABBITMQ_DEFAULT_USER: default_user\nRABBITMQ_DEFAULT_PASS: sample_password\n<\/pre>\n<h3 id=\"thenginxdockerfile\">The Nginx Dockerfile<\/h3>\n<p>This is hosted in an <code>nginx<\/code> folder within the root directory. It mainly contains two directives: the image name pulled from Dockerhub; and the location of the configuration files.<\/p>\n<p>Create a folder with the name <code>nginx<\/code>. In this folder, create another <code>Dockerfile<\/code> and add the code snippet below:<\/p>\n<pre>FROM nginx:1.19.0-alpine\n\nRUN rm \/etc\/nginx\/conf.d\/default.conf\nCOPY nginx.conf \/etc\/nginx\/conf.d\n<\/pre>\n<h3 id=\"thenginxconfigfile\">The Nginx config file<\/h3>\n<p>This is where you write the Nginx configuration logic. This file should be located in the same folder \u2014 the <code>Nginx<\/code> folder, as the Nginx Dockerfile.<\/p>\n<p>This config file dictates how the Nginx container will behave. Below is a sample script that lives in a file typically named <code>nginx.conf<\/code>.<\/p>\n<pre>upstream microservice { # name of our web image\n    server web:8000; # default django port\n}\n\nserver {\n\n    listen 80; # default external port. Anything coming from port 80 will go through NGINX\n\n    location \/ {\n        proxy_pass http:\/\/microservice_app;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header Host $host;\n        proxy_redirect off;\n    }\n    location \/static\/ {\n        alias \/home\/app\/microservice\/static\/; # where our static files are hosted\n    }\n\n}\n<\/pre>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Docker is a convenient tool for backend developers. The Docker tips and guidelines in this tutorial are vital for DevOps and full-stack developer positions in any organization.<\/p>\n<p>This tutorial demonstrates how you can setup your Docker in your Django application, build a Docker image and run an instance of the image as a container.<\/p>\n<p>We also discussed how to use the <code>docker compose<\/code> commands, through the <code>Docker-compose.yml<\/code> file to build and run multiple containers in a specific order.<\/p>\n<p>If you\u2019ll like to learn more about Docker and integrate it in your applications, this <a href=\"http:\/\/docs.docker.com\" target=\"_blank\" rel=\"noopener\">documentation<\/a> is a good resource to explore. You can also explore how to integrate Docker with other tools <a href=\"https:\/\/blog.logrocket.com\/tag\/docker\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>The <a href=\"https:\/\/docs.djangoproject.com\/en\/4.0\/\" target=\"_blank\" rel=\"noopener\">Django documentation<\/a> is a useful resource if you\u2019re also interested in honing or building your skills in Django.<\/p>\n<p>Thanks for reading!<\/p>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>This short guide, filled with tips and tricks, will walk you through how to set up a Django project with Docker. <\/p>\n","protected":false},"author":156415653,"featured_media":105159,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2147999,1],"tags":[2109789,2109732],"class_list":["post-33488","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-uncategorized","tag-django","tag-docker"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Dockerizing a Django app - LogRocket Blog<\/title>\n<meta name=\"description\" content=\"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dockerizing a Django app - LogRocket Blog\" \/>\n<meta property=\"og:description\" content=\"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/\" \/>\n<meta property=\"og:site_name\" content=\"LogRocket Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-08T16:00:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-04T21:09:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"730\" \/>\n\t<meta property=\"og:image:height\" content=\"487\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Kimaru Thagana\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kimaru Thagana\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/\",\"url\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/\",\"name\":\"Dockerizing a Django app - LogRocket Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.logrocket.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png\",\"datePublished\":\"2022-04-08T16:00:53+00:00\",\"dateModified\":\"2024-06-04T21:09:40+00:00\",\"author\":{\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/2e4419ce9b9a541f7d10eaad34225a6d\"},\"description\":\"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage\",\"url\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png\",\"contentUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png\",\"width\":730,\"height\":487,\"caption\":\"Dockerize Django App\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.logrocket.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dockerizing a Django app\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.logrocket.com\/#website\",\"url\":\"https:\/\/blog.logrocket.com\/\",\"name\":\"LogRocket Blog\",\"description\":\"Resources to Help Product Teams Ship Amazing Digital Experiences\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.logrocket.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/2e4419ce9b9a541f7d10eaad34225a6d\",\"name\":\"Kimaru Thagana\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/77b394fdda6dcf52e0332846a8f4315689d063b9265af9897e9c8c64b31b31c8?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/77b394fdda6dcf52e0332846a8f4315689d063b9265af9897e9c8c64b31b31c8?s=96&d=mm&r=g\",\"caption\":\"Kimaru Thagana\"},\"description\":\"Seasoned Python\/Django developer with vast experience working on web and backend applications. Remote work enthusiast and practitioner. Developer by calling, tech-guide-writer by passion.\",\"sameAs\":[\"https:\/\/github.com\/KimaruThagna\"],\"url\":\"https:\/\/blog.logrocket.com\/author\/kimaruthagana\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Dockerizing a Django app - LogRocket Blog","description":"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/","og_locale":"en_US","og_type":"article","og_title":"Dockerizing a Django app - LogRocket Blog","og_description":"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.","og_url":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/","og_site_name":"LogRocket Blog","article_published_time":"2022-04-08T16:00:53+00:00","article_modified_time":"2024-06-04T21:09:40+00:00","og_image":[{"width":730,"height":487,"url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png","type":"image\/png"}],"author":"Kimaru Thagana","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Kimaru Thagana","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/","url":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/","name":"Dockerizing a Django app - LogRocket Blog","isPartOf":{"@id":"https:\/\/blog.logrocket.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage"},"image":{"@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png","datePublished":"2022-04-08T16:00:53+00:00","dateModified":"2024-06-04T21:09:40+00:00","author":{"@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/2e4419ce9b9a541f7d10eaad34225a6d"},"description":"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.","breadcrumb":{"@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.logrocket.com\/dockerizing-django-app\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#primaryimage","url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png","contentUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2021\/01\/dockerize-django-app-1.png","width":730,"height":487,"caption":"Dockerize Django App"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.logrocket.com\/dockerizing-django-app\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.logrocket.com\/"},{"@type":"ListItem","position":2,"name":"Dockerizing a Django app"}]},{"@type":"WebSite","@id":"https:\/\/blog.logrocket.com\/#website","url":"https:\/\/blog.logrocket.com\/","name":"LogRocket Blog","description":"Resources to Help Product Teams Ship Amazing Digital Experiences","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.logrocket.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/2e4419ce9b9a541f7d10eaad34225a6d","name":"Kimaru Thagana","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/77b394fdda6dcf52e0332846a8f4315689d063b9265af9897e9c8c64b31b31c8?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/77b394fdda6dcf52e0332846a8f4315689d063b9265af9897e9c8c64b31b31c8?s=96&d=mm&r=g","caption":"Kimaru Thagana"},"description":"Seasoned Python\/Django developer with vast experience working on web and backend applications. Remote work enthusiast and practitioner. Developer by calling, tech-guide-writer by passion.","sameAs":["https:\/\/github.com\/KimaruThagna"],"url":"https:\/\/blog.logrocket.com\/author\/kimaruthagana\/"}]}},"yoast_description":"Docker isolates your application and its dependencies and ensures consistent runtime protocols regardless of server configurations.","_links":{"self":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/33488","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/users\/156415653"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/comments?post=33488"}],"version-history":[{"count":15,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/33488\/revisions"}],"predecessor-version":[{"id":105193,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/33488\/revisions\/105193"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media\/105159"}],"wp:attachment":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media?parent=33488"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/categories?post=33488"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/tags?post=33488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}