
Creating a simple Dockerized Django Blog App
Creating a simple Dockerized Django Blog App
Docker is an invaluable tool for developers. It allows you to create lightweight, portable development environments called containers that match your production setup. With Docker, you can quickly spin up a dev environment with the tools, dependencies, and configurations you need to build your application. In this comprehensive guide, we’ll go through all the steps to set up a Dockerized development environment for a Django app.
Creating a Django Project
First, let’s create a new Django project. We’ll use the django-admin command-line utility to create a new project called myproject:
django-admin startproject myproject This creates a new directory called myproject with the following files:
myproject/
├── manage.py
└── myproject
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py The manage.py file is a command-line utility that lets you interact with your Django project. You can use it to run development servers, create new apps, and more.
The myproject directory contains the actual Python package for your project. It’s a Python module that contains all the settings, URLs, and other configurations for your project.
Now we create the ‘requirements.txt’ file:
pip freeze > requirements.txt Creating a Dockerfile
A Dockerfile defines the steps to assemble your image. Create a new file called Dockerfile and add:
FROM python:3.8-buster
ENV PYTHONUNBUFFERED=1
WORKDIR /django
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD python manage.py runserver 0.0.0.0:8000
Creating a Docker Compose File
Docker Compose is a tool for defining and running multi-container Docker applications. It uses a YAML file to configure the application’s services, networks, and volumes. We’ll use it to define our Django app and PostgreSQL database.
Create a new file called docker-compose.yml and add:
version: '3.8'
services:
app:
build: .
volumes:
- .:/django
ports:
- 8000:8000
image: app:django
container_name: django_container
command: python manage.py runserver 0.0.0.0:8000 Building the Docker Image
Now that we have our Dockerfile and docker-compose.yml file, we can build the Docker image. Run the following command:
docker-compose build This builds the image and tags it as app:django. You can verify it was built by running:
docker images Running the Docker Container
Now that we have our image, we can run a container using it. Run the following command:
docker-compose up This starts the container and runs the Django development server. You can verify it’s running by visiting http://localhost:8000 in your browser.
We can also run the container in detached mode by adding the -d flag:
docker-compose up -d This runs the container in the background. You can view the logs by running:
docker-compose logs Running Django Commands
You can run Django commands inside the container using the docker-compose run command. For example, to create a new app called blog, run:
docker-compose run app python manage.py startapp blog This creates a new directory called blog with the following files:
blog/
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py You can also run the Django shell by running:
docker-compose run app python manage.py shell This starts the Django shell where you can interact with your project’s models and database.
Connecting to PostgreSQL
Now that we have our Django app running, let’s connect it to a PostgreSQL database. First, we need to add the psycopg2 package to our requirements.txt file:
psycopg2==2.8.6 or
pip install psycopg2 Next, we need to update the settings.py file to use PostgreSQL as the database backend.
By default, Django uses SQLite for the database backend. However, for production use, it’s recommended to use a more robust database such as PostgreSQL. For this tutorial, we’ll use PostgreSQL.
Open the myproject/settings.py file in your text editor and replace the following code:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
With the following code:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'mypassword',
'HOST': 'db',
'PORT': 5432,
}
}
This will configure Django to use a PostgreSQL database named myproject with a username of myprojectuser and a password of mypassword.
Next, we need to update the docker-compose.yml file to include a PostgreSQL service. Add the following code:
version: '3.8'
services:
app:
build: .
volumes:
- .:/django
ports:
- 8000:8000
image: app:django
container_name: django_container
command: python manage.py runserver
db:
image: postgres:13.1
volumes:
- postgres_data:/var/lib/postgresql/data/
environment:
- POSTGRES_DB=myproject
- POSTGRES_USER=myprojectuser
- POSTGRES_PASSWORD=mypassword
volumes:
postgres_data: This code does the following:
- Defines two services:
dbandapp - Uses the official PostgreSQL Docker image for the
dbservice - Sets the environment variables for the
dbservice to configure the PostgreSQL database - Maps port 5432 on the host to port 5432 in the container for the
dbservice - Builds the Docker image for the
appservice using theDockerfilein the current directory - Runs the
python3 manage.py runservercommand to start the Django development server - Maps port 8000 on the host to port 8000 in the container for the
appservice - Specifies that the
appservice depends on thedbservice
Now that we’ve updated the docker-compose.yml file, we need to rebuild the Docker image and start the container. Run the following command:
docker-compose up -d --build This rebuilds the Docker image and starts the container in detached mode. You can verify it’s running by visiting http://localhost:8000 in your browser.
Next, we need to create the database tables by running the following command:
docker-compose run app python manage.py migrate This creates the database tables for the default Django models, including the auth and admin models.
Creating an Admin User
Next, we need to create an admin user so we can log in to the Django admin dashboard. Run the following command:
docker-compose run app python manage.py createsuperuser You’ll be prompted to enter a username, email, and password for the admin user.
Adding a Blog Model
Now that we have our Django app running and connected to a PostgreSQL database, let’s add a blog model. We’ll use this model to create blog posts.
Open the blog/models.py file in your text editor and add the following code:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.title This defines a Post model with the following fields:
title- The title of the blog postslug- The slug of the blog post. This is used in the URL of the blog postauthor- The author of the blog post. This is a foreign key to theUsermodelbody- The body of the blog postcreated- The date and time the blog post was createdupdated- The date and time the blog post was last updated
Next, we need to create a database migration for the Post model. Run the following command:
docker-compose run app python manage.py makemigrations blog This creates a database migration for the blog app. Next, we need to apply the migration to the database by running the following command:
docker-compose run app python manage.py migrate This creates the Post model in the database.
Registering the Blog Model in the Admin Dashboard
Next, we need to register the Post model in the admin dashboard. Open the blog/admin.py file in your text editor and add the following code:
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'author', 'created', 'updated')
prepopulated_fields = {'slug': ('title',)} This registers the Post model in the admin dashboard and specifies which fields are displayed in the list of blog posts.
Next, we can test the admin dashboard by creating a blog post visitin http://localhost:8000/admin in your browser. Log in using the admin user you created earlier.
Next, click on the + Add button next to Posts. Enter a title, slug, author, and body for the blog post and click Save. You should see the blog post listed on the next page.
Creating a Homepage
Now that we have a blog model, let’s create a homepage that lists all the blog posts. Open the blog/views.py file in your text editor and replace the following code:
from django.shortcuts import render
# Create your views here. With the following code:
from django.views.generic import ListView
from .models import Post
class HomePageView(ListView):
model = Post
template_name = 'home.html' This defines a HomePageView class that extends Django’s ListView class. This class will query the database for all the blog posts and render them using the home.html template.
Next, we need to create the home.html template. Create a new directory named templates in the blog directory. Then, create a new file named home.html in the templates directory and add the following code:
{% extends 'base.html' %} {% block title %}Blog{% endblock %} {% block content %} {% for post in
object_list %}
<h2><a href="{% url 'post_detail' post.slug %}">{{ post.title }}</a></h2>
<p>{{ post.body|truncatewords:30 }}</p>
<p>Created: {{ post.created }}</p>
<p>Updated: {{ post.updated }}</p>
<hr />
{% endfor %} {% endblock %} This extends the base.html template and displays the title, body, created date, and updated date for each blog post.
Next, we need to create a URL route for the homepage. Open the blog/urls.py file in your text editor and add the following code:
from django.urls import path
from .views import HomePageView
urlpatterns = [
path('', HomePageView.as_view(), name='home'),
] This defines a URL route for the homepage that renders the HomePageView class.
Next, we need to update the mysite/urls.py file to include the URL routes for the blog app. Open the mysite/urls.py file in your text editor and replace the following code:
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
] With the following code:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
] This includes the URL routes for the blog app.
Next, we need to create a base template that the home.html template can extend. Create a new file named base.html in the templates directory and add the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %} {% endblock %}
</body>
</html> This defines a base template that the home.html template can extend.
Creating a Blog Post Detail Page
Next, we need to create a URL route for the blog post detail page. Open the blog/urls.py file in your text editor and add the following code:
from django.urls import path
from .views import HomePageView, PostDetailView
urlpatterns = [
path('', HomePageView.as_view(), name='home'),
path('<slug:slug>/', PostDetailView.as_view(), name='post_detail'),
] This defines a URL route for the blog post detail page that renders the PostDetailView class.
Next, we need to create the PostDetailView class. Open the blog/views.py file in your text editor and add the following code:
from django.views.generic import ListView, DetailView
from .models import Post
class HomePageView(ListView):
model = Post
template_name = 'home.html'
class PostDetailView(DetailView):
model = Post
template_name = 'post_detail.html' This defines a PostDetailView class that extends Django’s DetailView class. This class will query the database for a single blog post and render it using the post_detail.html template.
Next, we need to create the post_detail.html template. Create a new file named post_detail.html in the templates directory and add the following code:
{% extends 'base.html' %} {% block title %}{{ object.title }}{% endblock %} {% block content %}
<h2>{{ object.title }}</h2>
<p>{{ object.body }}</p>
<p>Created: {{ object.created }}</p>
<p>Updated: {{ object.updated }}</p>
{% endblock %} This extends the base.html template and displays the title, body, created date, and updated date for a single blog post.
Conclusion
That’s it! You’ve successfully created a blog app with Django in Docker.
Happy coding!