6.1. Write a Dockerfile#
A Dockerfile
packages your application to be run as a container. This lab will show you how to create a Dockerfile
that runs your application.
Ignoring Files#
Just like git, Docker should ignore some of the files in your project. In the root directory of your repo, create a new file called .dockerignore
. The contents of .dockerignore
should be:
**/*.sqlite3
**/__pycache__
The database does not belong in the image.
Python Version#
Applications should run in production the same way they run in development environments. Docker makes that possible by having different versions of containers available. Use the following command to discover the version of Python you use in your dev environment:
$ python --version
Python 3.9.2
If you see output like that you should use the 3.9.2
tag of the official python
container.
Starter Dockerfile
#
In the root directory of your repo, create a new file called Dockerfile
. The initial contents of Dockerfile
should be:
# Start with the base Python container
# FIXME: Update the version
FROM docker.io/python:PUT-PYTHON-VERSION-HERE
# Install packages that are required.
RUN pip install Django==4.2.9
# Copy the Python code into the container
COPY mysite /mysite
# Set environment variables
ENV PORT=8000
# Set the working directory
WORKDIR /mysite
# Default command to execute in the container
CMD python ./manage.py runserver 0.0.0.0:$PORT
The initial Dockerfile
expects that the mysite
directory exists in the root of your repo. Note that it runs the pip install Django==4.2.9
command that we ran in the 4.1. Start a Django Application lab.
Container Build and Run#
Build your application by pointing Docker to the Dockerfile
. It’s typical to run the command from the directory with the Dockerfile
:
$ docker build -t mysite .
The build will take a few minutes. Once it’s done verify that the container has been built:
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
mysite latest 812b4be50628 6 seconds ago 927MB
Now let’s run it:
$ docker run -it --rm -p 8000:8000 mysite
Error
There’s an error in startup! What did we forget?
Debugging a Container That Won’t Start#
Sometimes a container builds but won’t start. Problems like this arise when there are problems with the WORKDIR
or CMD
lines in the Dockerfile
or when a COPY
moved files to the wrong place. When a container won’t start it can be hard to figure out what went wrong. When you run a container you can override the CMD
in the Dockerfile to get a shell. The shell lets you look around and try to see what’s wrong.
$ docker run -it --rm -p 8000:8000 mysite /bin/bash
root@083afb59e29e:/mysite#
Inside the container try to start the Django server:
$ python manage.py runserver 0.0.0.0:$PORT
Notice the error? We forgot to put psutil
in the Dockerfile
. We can test to make sure that’s the only fix needed:
root@083afb59e29e:/mysite# pip install psutil
With bash running you can look around the container with cd
and ls
and also try to start your application manually:
root@9e30cbcaa3af:/mysite# python manage.py runserver 0.0.0.0:$PORT
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
February 15, 2023 - 01:14:12
Django version 4.1.7, using settings 'mysite.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
Note
The changes you make inside of a container are not permanent! Update your Dockerfile
and re-run docker build
to permanently fix this issue.
Initialize the Database#
Error
If you did everything correctly you will receive and OperationalError
while trying to login.
Your container should not contain a database to start with, so it won’t let you login if you just run it as shown above. The following commands have to be run inside the container to get it to initialize the database:
root@28b4b0cf16b6:/mysite# python manage.py migrate
root@28b4b0cf16b6:/mysite# python manage.py createsuperuser
Remember these commands. You need them every time you start a new container.