2. Set up your project locally¶
In this section we will build the new project you’ve created in the local development environment; that is, we will set it up on your own computer.
Obtain the project’s slug (its unique ID) from the Dashboard:

Alternatively you can use the divio
command to list your cloud project, which will show their slugs:
divio project list
2.1. Build the project locally¶
Run the divio project setup
command (for example if your project slug is tutorial-project
):
divio project setup tutorial-project
The Divio CLI will execute a number of steps - this may take a few minutes, depending on how much needs to be downloaded and processed. The Divio CLI tool will build your project locally (see The deployment process for a more detailed description of what’s happening here). Note that depending on the project, you won’t necessarily see all the intermediate steps here:
Creating workspace
cloning project repository
[...]
downloading remote docker images
[...]
building local docker images
[...]
creating new database container
[...]
syncing and migrating database
[...]
Your workspace is setup and ready to start.
As well as cloning the repository and attempting to build the project, the setup
command will add a .divio
directory containing some Divio-related configuration that connects it to the Control Panel.
cd
into the newly-created project directory, where you will find your project code.
2.2. Install Python and Django using the Dockerfile
¶
This project requires that we have Python installed in the container. By using an official Docker base image that
includes Python, we can speed up build times and rely on a lightweight and expertly-constructed foundation. The
Dockerfile
that defines the project is currently empty. We will use Python 3.8, so add:
FROM python:3.8
This will use the official Docker python
base image as the foundation for everything else that we build on top.
Let’s check that Docker can build an image from our newly-created Dockerfile, by running:
docker build .
This project will use Django 3.1.x. We can install Django and its Python dependencies by using pip
to process a
list of requirements. Create a new file requirements.txt
in the project and list Django:
django>=3.1,<3.2
The requirements file needs to be made accessible inside the Docker application. So, we will copy it (and everything
else in the root of this project) into the image’s filesystem at /app
(it doesn’t need to be there in particular,
but /app
is a useful convention), and for convenience, we can set Docker to use /app
as its base directory.
Finally, we will run the pip
command.
FROM python:3.8
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
Check again that the project builds as expected with docker build .
.
2.3. Create a docker-compose.yml
file for convenience¶
The docker
command is concerned merely with images and containers - not applications as a whole. An application
will typically include a number of components and resources, such as a database and media storage as well as code, and
all these various parts need to be orchestrated to function as an application. Docker Compose provides a very
convenient way to manage and interact with Docker applications. For example, it’s convenient to have port-mapping set
up locally, and to have direct access to files inside the container while developing.
docker-compose.yml
configures Docker Compose. Create a new docker-compose.yml
file in the project:
version: "2"
services:
web:
# the application's web service (container) will use an image based on our Dockerfile
build: "."
# map the internal port 80 to port 8000 on the host
ports:
- "8000:80"
# map the host directory to app (which allows us to see and edit files inside the container)
volumes:
- ".:/app:rw"
# the default command to run whenever the container is launched
command: python manage.py runserver 0.0.0.0:80
This now provides a convenient way to run commands inside the Dockerised environment, and also gives us access to a
number of useful docker-compose
commands. For example, now you can use docker-compose build
to build the entire
application, not just one image, and to run commands inside the application. Try docker-compose build
now.
2.4. Create a new Django project in the application¶
Next we need to create a new Django project in the application (with django-admin startproject
), so run:
docker-compose run web django-admin startproject myapp .
This starts up a container (web
, which according to docker-compose.yml
will be based on the Dockerfile
in
the same directory) and executes the django-admin
command inside it. It’s important to note that the command is
executed inside the Docker application environment, and not in the host environment.
The command will add a new myapp
directory and a manage.py
file. Although they were created inside the
container, so you wouldn’t normally be able to see them, the volumes
directive in the docker-compose.yml
file
maps /app
to the host filesystem, so you can see them and edit them without having to be inside the Docker
environment yourself.
2.5. Start the local project¶
Start the project by running docker-compose up
in the terminal:
➜ docker-compose up
Starting tutorial-project_web_1 ... done
Attaching to tutorial-project_web_1
web_1 | Watching for file changes with StatReloader
Open the project in your web browser by visiting http://127.0.0.1:8000, where you should see the default Django success page.
Notice above that although the the Django runserver is running on port 80, the project is accessible on port 8000. The
docker-compose.yml
configuration file is responsible for this port-mapping.
If you amend or even just save any Python file in the Django project, the runserver will reload the Python modules and restart.
2.6. Add a start-up instruction to the Dockerfile
¶
Docker Compose is only used locally, not in our cloud deployments. Moreover, the Django runserver that we’re using here is fine for local development but unsuitable for use in production. For production, we will use uWSGI (uWSGI is a WSGI gateway server for Python).
Add:
uwsgi==2.0.19.1
to requirements.txt
. These dependencies are baked into the image, so every time you amend the requirements, you
will need to rebuild with the new dependency list (we’ll do that in a moment).
The Django project can be started with uWSGI. This should be baked into the Dockerfile
itself, as a start-up command. To the end of the file, add:
CMD uwsgi --module=myapp.wsgi --http=0.0.0.0:80
Run:
docker-compose build
once more. Now when the web container is launched it will run the command automatically, to start it up in - for example - a cloud deployment.
However, when we start it locally with docker-compose up
, the command
line in the docker-compose.yml
file
overrides that, and uses python manage.py runserver 0.0.0.0:80
instead.
Try running the project locally using uWSGI rather than the runserver, by temporarily commenting out the command
line in the docker-compose.yml
file. Note that it’s not necessary to rebuild after making changes to
docker-compose.yml
- Docker Compose uses images, but doesn’t affect what’s in them.
Restore the command
line in the docker-compose.yml
file before continuing.
2.7. Local commands¶
So far, we have used the divio
, docker-compose
and docker
commands. It’s good to have a basic familiarity
with them and what they do. As you proceed through this tutorial, you may encounter the occasional issue. These
commands will help you when this happens.
2.7.1. Using divio
¶
The divio
command is used mainly to manage your local project’s resources and to interact with our Control Panel.
You have already used divio project setup
and divio project list
; you can also use it to do things like push
and pull database and media content. Try:
divio project dashboard
See the Divio CLI reference for more.
2.7.2. Using docker
¶
The docker
command is mostly used to manage Docker processes, images and containers (rather than applications as a
whole) and Docker itself. You will rarely need to use it, but it can be useful when you need to understand what Docker
is doing on your machine, or for certain operations.
For example, if you have your project running locally (with docker-compose up
) open a new terminal window to run:
docker ps
This will show you the Docker processes that are running - you will see something like this (note that the details will differ depending on what you actually have running):
➜ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAME
d6007edbaf32 tutorialproject_web "/tini -g -- pytho..." 17 minutes ago Up 8 seconds 0.0.0.0:8000->80/tcp tutorialproject_web_
27ff3e661027 postgres:9.6 "docker-entrypoint..." 17 minutes ago Up 8 seconds 5432/tcp tutorialproject_db_
In this example, the first container is an instance of the image that you built (when deployed, a similar container will be running in a cloud environment). The second shown here is a Postgres database, running in its own Docker container.
You have already used docker ps
. Try:
docker info
2.7.3. Using docker-compose
¶
The docker-compose
command is used mainly to control and interact with your local project. You will mostly use it
to start the local project and open a shell in the local web container. You have already used docker-compose build
and docker-compose up
.
Just for example, try:
docker-compose run web python manage.py shell
which will open a Django shell in the web
container.
You have now set up a project in the local environment, and launched it. The next step is to do some further development work in the project, test it, and deploy it to the cloud.