This is a short hands-on introduction to docker-compose. If you want to know what docker is, check this link out. This is simply a commented version of the official django with docker-compose.
Tested Configuration:
MacOS: Sierra 10.12.06
Docker: 18.09.2 CE
Docker-compose: 1.23.2
1. Requirements
Make sure you have docker and docker-compose installed on your machine. To do this, simply type
docker --version
and make sure you have something like Docker version 18.09.2-ce, build 6247962
Then type
docker-compose --version
and make sure you have something like docker-compose version 1.23.2, build 1110ad01
2. Dockerfile
First, create your Dockerfile, please type :
mkdir docker_folder
cd docker_folder
touch Dockerfile
Edit your Dockerfile
You are still in the /docker_folder
, type
sudo nano Dockerfile
It will open your Dockerfile. Now copy the following code in your Dockerfile :
FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
What is happening in the Dockerfile:
FROM python:3 will import the python 3 image from the docker hub
ENV PYTHONUNBUFFERED 1 define an environment variable. Later in the script, it will tell python to print STDOUT without buffering anything. that’s useful when you want to print something before the machine crashes
RUN mkdir /code will create a folder on the Image
WORKDIR /code will set the current directory as /code -> acts like a ` cd /code` on the image
COPY requirements.txt /code/ copies the file requirements.txt to the image at the location /code/requirements.txt
RUN pip install -r requirements.txt install all python packages on the image
COPY . /code/ copy the rest of the folder to the folder code
3. Create your requirements
Create your requirements.txt in your folder /docker_folder
and then edit it:
sudo nano requirements.txt
Inside, you can write this:
Django>=2.0,<3.0
psycopg2>=2.7,<3.0
This will tell Docker to install Django and psycopg2 on the image
4. Create docker-compose.yaml
Create a file called docker-compose.yaml in your project directory /docker_folder
and then edit it:
sudo nano docker-compose.yaml
Inside, you can write this:
version: "3"
services:
db:
image: postgres
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
From the documentation:
The docker-compose.yml file describes the services that make your app. In this example those services are a web server and database.
The compose file also describes which Docker images these services use, how they link together, any volumes they might need mounted inside the containers.
Finally, the docker-compose.yml file describes which ports these services expose.
Short analysis:
- we create two services:
web
&db
- we use format version 3 (different from the docker-compose version…). You can see the Compatibility matrix
- service
db
has an image based on thepostgres
image (from docker hub) - service
web
has an image based on theDockerfile
we wrote earlier: that’s thebuild: .
- service
web
launches the command:python manage.py runserver 0.0.0.0:8000
after the image is built - service
web
mounts the folder/docker_folder
to the image folder/code
(ex: modify the code on the fly) - service
web
mounts the ports 8000 [container] to 8000 [image] (simple)
Note: we don’t have any access to the database, exept through the docker network. It means only the service web
can access the database, because this docker network is restricted to db
and web
(type docker network inspect testdjango_default
). Even you, if you want to use a GUI in order to manipulate the Postgres data, you will need to add a line in the db
configuration:
expose:
- 5432
5. Create a Django project
in your terminal type:
sudo docker-compose run web django-admin startproject composeexample .
Explanations:
compose will run django-admin startproject composeexample
in a container, using the web service’s image and configuration. This command instructs Django to create a set of files and directories representing a Django project.
Now, if you look at the files in the /docker_folder
, you have:
Dockerfile (was here before)
composeexample
docker-compose.yaml (was here before)
manage.py
requirements.txt (was here before)
6. Connect the database
In the composeexample/settings.py
file, replace DATABASES = ...
with:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
To know more about the database: docker & postgres
7. Run
Simply run your docker project using
docker-compose up
and see you server working by clicking http://localhost:8000
Monitor
Prints all the running containers
docker container ls
Stop
Two method:
-
Ctrl-C
in the same shell in where you started it -
open a new shell, go to
/docker_folder
directory, and rundocker-compose down
Notes:
docker-compose.yaml VS docker-compose.yml
Shall we use the extension .yml or .yaml ? IT DOESN’T MATTER
Everyone could use .yaml but some Windows developer are afraid of using more than 3 letters extensions…
file ownership
After runnig sudo docker-compose run web django-admin startproject composeexample .
several files were created. Running ls -l
will show who is owning the files. You may need to change their ownership back to you (espcially Linux users) using sudo chown -R $USER:$USER .
Other docker-compose.yaml proposition
This can be interesting for two reasons:
version: "3"
services:
db:
image: postgres
environment:
PGDATA: /var/lib/postgresql/data/django_test_pgdata
POSTGRES_USER: yourusername
POSTGRES_PASSWORD: yourpassword
POSTGRES_DB: test
volumes:
- /usr/local/var/postgres/data/django_test_pgdata:/var/lib/postgresql/data/django_test_pgdata
ports:
- "8002:5432"
web: [SAME CONFIG]
First you may have port 5432
already in use on another Postgres container, or because you already run postgres on your laptop.
Second, you have control on the data. instead of staying inside your postgres container (and beiing deleted when the container stops) you can have persistent data.
Run only one docker
If you want to launch only the database for instance, you can write down:
docker-compose run --service-ports postgres
With --service-ports
meaning you attach the docker to the host network (usually what you want when you don’t launch docker together)
if you have Volumes
Let’s say you have decided to inculde the volume option, like so (probably to cache your node_modules folder):
version: "3"
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- node_modules:/code/node_modules
ports:
- "8000:8000"
Then, if you need to “clean the cache” (because you want to reinstall the dependancies for instance), use this command: docker-compose down --volumes
Ressources:
docker-compose.yaml VS docker-compose.yml: stackoverflow link
More about PYTHONUNBUFFERED
the official docker-compose tuto