Blog Refresh: Django
by Aaron Crowder on
I have tinkered with this blog on and off for years. In fact, I've had a blog at some URL in some form going back over two decades. My inability to stick with a single URL or publishing platform should be documented and studied.
Nevertheless here I am writing about yet another blog refresh. I won't say this will be the last, nor will I pontificate about how this platform was custom built for me by me to grow with me. I will simply continue to write here or I won't. Only time will tell.
If you would like to know more about this blog and the technology used to develop and deploy it read on!
Code
This blog is built using Django. I have a few things I want to build into this blog and a web framework like Django will make that easier. The Django admin interface is also a nice addition.
I decided to try uv for this project instead of pip. UV is a python package and project manager written in Rust. UV significantly improved the workflow I remember from last time I used Django (at Teem).
Infrastructure
I decided to host this on Digital Ocean using their app platform. It's connected to a GitHub repository and deploys any time I push to the main branch. Digital Ocean's app platform can deploy all kinds of different apps but to make it easier and give me more control I added a Dockerfile to the repository.
# Dockerfile
FROM python:3.14-alpine
# Python runtime tweaks
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/app/.venv/bin:${PATH}" \
UV_NO_DEV=1
WORKDIR /app
# Install uv once, no pip cache left behind
RUN pip install --no-cache-dir uv
# Copy project metadata first to leverage layer caching
COPY pyproject.toml uv.lock* ./
# Install only prod deps into a local .venv
RUN uv sync --no-dev --group prod && \
rm -rf /root/.cache
# Copy the rest of your app
COPY . .
# Non root user
RUN addgroup -S app && adduser -S -G app app
USER app
EXPOSE 8000
# Run migrations on every start, then launch gunicorn
CMD ["sh", "-c", "uv run manage.py migrate && gunicorn config.wsgi:application -b 0.0.0.0:8000"]
The most import part here is the CMD at the end. It's running migrations (uv run manage.py migrate) on every startup. This ensures that my prod environment always has the latest database schema.
Future Plans
Going forward I plan to add a number of things to this blog like:
- Posting using Micropub
- Webmentions to interact with other blogs
- POSSE so I can post here and have those posts automatically published to other channels.
and lots more! But for now... let's just see if I can keep writing here consistently.