repos

blog.bythewood.me-rust

mirror archived upstream

Single-binary self-hosted Markdown blog on Rust axum: no database, live search, Typst PDF export, and strong SEO.

axumblogdockermarkdownminijinjarustself-hostedtypstvite

3.9 KB · 104 lines · markdown Raw History
  1---
  2title: Running a simple Django website in Docker
  3slug: running-a-simple-django-website-in-docker
  4date: 2022-05-14
  5publish_date: 2022-05-14
  6tags: webdev
  7description: Using Docker to run a simple production and development environments with a few extras thrown in. Easily customized to your preferred language or framework.
  8cover_image: django-dockerfile-edited.webp
  9---
 10
 11Docker is a near perfect solution for having project portability across a wide variety of host platforms. I use docker to run my websites on both development computers and servers. For Django my go to Dockerfile looks a little something like this.
 12
 13```shell
 14# django
 15#
 16# I use this to run most of my django projects in a single container in
 17# production. If you wish to seriously reduce the size of this image and you
 18# don't need it you can remove the chromium line. I use it for screenshots and
 19# pdf creation.
 20#
 21# Make sure to change the below ENV variables to fit your needs and the gunicorn
 22# path to your applications asgi file.
 23#
 24# You can run this with:
 25#   docker build --tag overshard/django:latest .
 26#   docker run -d -p 80:8000 -e DJANGO_SETTINGS_MODULE=project.settings.production \
 27#     -v /srv/data:/data django:latest
 28
 29
 30FROM alpine:3.16
 31
 32RUN apk add --update --no-cache \
 33      sqlite \
 34      python3 py3-pip \
 35      nodejs yarn \
 36      chromium libstdc++ nss harfbuzz freetype font-noto font-noto-extra font-noto-emoji && \
 37    pip install pipenv
 38
 39COPY Pipfile Pipfile.lock package.json yarn.lock /app/
 40
 41RUN yarn install && pipenv install --system
 42
 43COPY . .
 44
 45RUN yarn webpack:production && \
 46    rm -rf node_modules && \
 47    python3 manage.py collectstatic --noinput
 48
 49RUN addgroup -S -g 1000 app && \
 50    adduser -S -h /app -s /sbin/nologin -u 1000 -G app app && \
 51    chown -R app:app /app
 52
 53USER app:app
 54
 55WORKDIR /app
 56
 57VOLUME /data
 58
 59EXPOSE 8000
 60
 61ENV DJANGO_SETTINGS_MODULE=project.settings.production
 62
 63CMD ["gunicorn", "project.asgi:application", "-k", "uvicorn.workers.UvicornWorker", "-w", "4", "-b", ":8000", "--access-logfile", "-", "--error-logfile", "-"]
 64```
 65
 66A few notes on my choices:
 67
 68* This assumes you are just using an sqlite database but this can easily scale into using PostgreSQL in coordination with docker-compose
 69* I use webpack to build all of my static files on all of my sites hence why nodejs and yarn are included
 70* Chromium is used in most of my projects for generating PDFs and screenshots, I've found it the most reliable and consistent way of handling that functionality
 71* You'll need both gunicorn and uvicorn installed
 72
 73You could remove Chromium and save ~400MB of space on a roughly ~450MB image if you have no use for it. It is by far the largest dependency here. I also often use docker-compose in conjunction with this Dockerfile.
 74
 75```shell
 76# django
 77#
 78# I create a `.env` file in the same folder as my `Dockerfile` and
 79# `docker-compose.yml` file with the environmental variables below. Generally my
 80# server file struction is `/srv/git/app` for the git bare repository,
 81# `/srv/docker/app` for the git repo cloned from the bare repo, and
 82# `/srv/data/app` for the data directory mounted to the container.
 83#
 84# The ports are `8000:8000` because I often use Caddy or Nginx to reverse proxy
 85# to the container. You could probably just serve the app directly though with
 86# `8000:80` instead if you have no media files.
 87
 88version: "3"
 89
 90services:
 91  web:
 92    build: .
 93    volumes:
 94      - /srv/data/app/:/data/
 95    ports:
 96      - "8000:8000"
 97    command: gunicorn analytics.asgi:application -k uvicorn.workers.UvicornWorker -w 4 -b :8000 --access-logfile - --error-logfile -
 98    restart: unless-stopped
 99    environment:
100      DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE}
101```
102
103This can be used directly in production pretty well however I do put most of my websites behind Caddy using a reverse proxy. If you'd like to see my most up-to-date alpine-docker files you can check them out on my [overshard/dockerfiles GitHub project](https://github.com/overshard/dockerfiles).