Run Wagtail CRX with Docker¶
Wagtail CRX runs well in Docker. When working with Docker, there are two different approaches. This guide will also work with any Wagtail site, or most types of Django sites.
The first step is to install Docker, on both your development environment (i.e. your computer) and on your server (hosting) environment.
For the sake of this guide, we will assume your Django project is named
myproject
.
Step 1: Choose How to Use Docker¶
The Versioned Image Approach¶
The most common way of working with Docker is to create a static Docker image, containing all of your code, which is effectively versioned in tandem with your git repository. Each time you change your project code, you also create a new version of the image. Because this image is effectively static and mirrors version control, there is no way to store dynamic files such as a database or media files. In this setup, you would want to use 3rd party services such as AWS S3 for files, or AWS RDS for database. Nearly all cloud platforms provide similar services.
Next, create a file in your main project folder named Dockerfile
(no file
extension). Copy the contents below into the file:
FROM python:latest
ENV PYTHONUNBUFFERED 1
# Set the Django settings to use.
ENV DJANGO_ENV "dev"
ENV DJANGO_SETTINGS_MODULE "myproject.settings.dev"
# Install a WSGI server into the container image.
RUN pip install waitress
# Code will end up living in /app/
WORKDIR /app/
# Copy and install the project requirements.
COPY ./requirements.txt /app/requirements.txt
RUN pip install -r /app/requirements.txt
# Copy the entire project code.
COPY . /app/
# Prepare the app.
RUN python manage.py migrate
RUN python manage.py collectstatic --noinput
# Create a "coderedcms" user account to run the app.
RUN useradd coderedcms
RUN chown -R coderedcms /app/
USER coderedcms
# Finally, run the app on port 8000.
EXPOSE 8000
CMD exec waitress-serve --listen "*:8000" "myproject.wsgi:application"
The “Image as Environment” Approach¶
The second approach is to use the container as the runtime environment, but store your code and files outside the container. This way you only need to update the container when you want to change your python version, or apply other security updates. For those who like to use the filesystem, such as writing logs, media files, etc. “normally”, this is the recommended way to use Docker, as it will fit within your existing workflow.
First, create a script which will be used as the entry point, meaning it runs
every time the container starts. The entry point will be used to set up the app
each time. Copy the contents below into a filed named docker-entrypoint.sh
.
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
Next, create a file in your main project folder named Dockerfile
(no file
extension). Copy the contents below into the file:
FROM python:latest
ENV PYTHONUNBUFFERED 1
# Set the Django settings to use.
ENV DJANGO_ENV "dev"
ENV DJANGO_SETTINGS_MODULE "myproject.settings.dev"
# Install a WSGI server into the container image.
RUN pip install waitress
# Code will end up living in /app/
WORKDIR /app/
# Create a "coderedcms" user account to run the appp.
RUN useradd coderedcms
RUN chown -R coderedcms /app/
USER coderedcms
# Copy our entrypoint script.
COPY ./docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# Finally, run the app on port 8000.
EXPOSE 8000
ENTRYPOINT ["docker-entrypoint.sh"]
CMD exec waitress serve --listen "*:8000" "myproject.wsgi:application"
Step 2: Build Your Image¶
Next, with Docker running on your machine, create an image by running the
following from your command line, replacing /path/to/Dockerfile
and
/path/to/project/
with the correct paths on your machine.
$ docker build --pull -t myproject:v1 -f /path/to/Dockerfile /path/to/project/
This will likely take a while, as Docker is going to download the FROM
image
(Python in this case) and then run all of those commands in your Dockerfile.
Once complete, this will have created an image named myproject
tagged with
v1
. If you are using the “Versioned Image” approach, you would likely want
to change this tag every time you build the image. Docker image tags work
essentially like version control, as such many people choose to use their
current git commit ID as the tag. If you are using the “Image as Environment”
approach, then this tag would likely be your Python version, e.g. py3.8.1
Step 3: Run a Container Using the Image¶
Now, create a container using the image. If using the “Versioned Image” approach:
$ docker run --publish 8000:8000 --detach --name myproject-run myproject:v1
If using the “Image as Environment” approach, you also need to map a local
directory on your machine to a directory inside the container. This ensures that
the files that get created or modified are shared between your machine and the
container, and they will remain on your machine after the container is deleted.
The command below runs the container, but before doing so mounts the local directory
./
into the container’s /app/
directory:
$ docker run --publish 8000:8000 --detach --name myproject-run --mount type=bind,source=./,target=/app myproject:v1
Either approach will run an instance of your image myproject:v1
named
myproject-run
, and map port 8000 on your machine to port 8000 of the
container. Now going to http://localhost:8000 should serve up your app from the
container.
Read the official Docker guide and documentation at: https://docs.docker.com/get-started/.