An Intro to Docker for Djangonauts Lacey Williams Henschel DjangoCon Europe 2018 @laceynwilliams
A presentation at DjangoCon Europe 2018 in May 2018 in Heidelberg, Germany by Lacey Williams Henschel
An Intro to Docker for Djangonauts Lacey Williams Henschel DjangoCon Europe 2018 @laceynwilliams
@laceynwilliams
What is Docker? ! @laceynwilliams | Source: XKCD
magic @laceynwilliams
Docker ✓ Separate dependencies ✓ Shares your OS ✓ All team members on the same page ✓ No Python installs needed! @laceynwilliams
But... ✓ Learning curve @laceynwilliams
What about virtualenvs? @laceynwilliams | Source: XKCD
Polyjuice Potion Images and Containers @laceynwilliams
Docker is the potion @laceynwilliams | Source: Karen Roe
The image is the person you want to turn into @laceynwilliams | Source: Harry Po5er Wiki
The container
is you @laceynwilliams
image executable that contains all the packages for your project container run6me instance of image @laceynwilliams
The Dockerfile is the hair of the person you want to turn into @laceynwilliams | Source: Beth Purchases
Dockerfile is the DNA @laceynwilliams
image executable that contains all the packages for your project container run6me instance of image Dockerfile file that defines your image @laceynwilliams
Use hair to tell the po-on how to change into someone else . Drink it to transform your body . Use Dockerfile to tell Docker how to build your image . Run project in a container . @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , "runserver" ,
"0.0.0.0:8000" , "--settings=mysite.settings" ] @laceynwilliams
Brew your potion $ docker build . @laceynwilliams
$ docker build . Sending build context to Docker daemon 246.8kB Step 1/8 : FROM python:3.6 ---> c1e459c00dc3 Step 2/8 : ENV PYTHONUNBUFFERED 1 ---> 4a0a06578949 Step 3/8 : COPY ./requirements.txt /code/requirements.txt ---> 5295a62d7c36 Step 4/8 : RUN pip install -r /code/requirements.txt ---> Running in 18b4fa19c07e Collecting Django (from -r /code/requirements.txt (line 1)) Downloading https://.../Django-2.0.5-py3-none-any.whl (7.1MB) Installing collected packages: Django Successfully installed Django-2.0.5 Removing intermediate container 18b4fa19c07e ---> 371f3b29d141 Step 5/8 : COPY . /code/ ---> 5443237e1306 Step 6/8 : WORKDIR /code/ Removing intermediate container cbafa8b61bd9 ---> 5a50cee784e7 Step 7/8 : EXPOSE 8000 ---> Running in a0b9b3f4da6f Removing intermediate container a0b9b3f4da6f ---> 80fbc70dc709 Step 8/8 : CMD [ "python", "./manage.py", "runserver", "0.0.0.0:8000", "--settings=mysite.settings" ] ---> Running in 351cfbc91fa2 Removing intermediate container 351cfbc91fa2 Successfully built 80fbc70dc709 @laceynwilliams
Name of your image 80fbc70dc709 @laceynwilliams
$ docker build -t hogwarts . Successfully built 4521a153fa19 Successfully tagged hogwarts:latest @laceynwilliams
python: 3.6 hogwarts:latest @laceynwilliams
Layers @laceynwilliams | S/ll from Harry Po5er and the Chamber of Secrets
Step 1/8 : FROM python:3.6 ... Step 2/8 : ENV PYTHONUNBUFFERED 1 ... @laceynwilliams
• First (me through: Docker builds each layer by hand • Second (me through: Docker uses a cache if nothing has changed • Docker rebuilds changed layers and all layers a;er them
@laceynwilliams
Step 1/8 : FROM python:3.6 ---> c1e459c00dc3 Step 2/8 : ENV PYTHONUNBUFFERED 1 ---> Using cache ---> 4a0a06578949 Step 3/8 : COPY ./requirements.txt /code/requirements.txt ---> 630e64f66d85 Step 4/8 : RUN pip install -r /code/requirements.txt ---> Running in b9ef1258f655 Collecting Django (from -r /code/requirements.txt (line 1)) Downloading https://.../Django-2.0.5-py3-none-any.whl (7.1MB) ... Step 8/8 : CMD [ "python", "./manage.py", "runserver", "0.0.0.0:8000", "--settings=mysite.settings" ] ---> Running in 351cfbc91fa2 Removing intermediate container 351cfbc91fa2 Successfully built a5392bb186c4 Successfully tagged hogwarts:latest @laceynwilliams
The Standard Book of Spells Grade 1 Docker Edition @laceynwilliams
Imago Revelio $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hogwarts latest 4521a153fa19 42 hours ago 734MB @laceynwilliams ✨ spell to reveal images
Continens Revelio $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES @laceynwilliams ✨ spell to reveal containers
Drink your potion $ docker run -p 8000:8000 hogwarts @laceynwilliams
Continens Revelio
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
2021341641d7 hogwarts "python ./manage.py …"About a minute ago
STATUS PORTS NAMES
Up About a minute 0.0.0.0:8000->8000/tcp fervent_allen
@laceynwilliams
✨
spell to reveal containers
Apparate $ docker exec -it 2021341641d7 shell root@2021341641d7:/code# @laceynwilliams ✨ magical teleporta2on into container
root@2021341641d7:/code# ls
Dockerfile blog mysite requirements.txt
README.md manage.py
@laceynwilliams
root@2021341641d7:/code# cd .. root@2021341641d7:/# ls bin code etc lib media opt root sbin sys usr boot dev home lib64 mnt proc run srv tmp var @laceynwilliams
Disapparate ctrl + d @laceynwilliams ✨ magical teleporta2on out of container shell
$ docker container ls
CONTAINER ID IMAGE COMMAND
2021341641d7 hogwarts "python ./manage.py …"
@laceynwilliams
Stupefy $ docker stop 2021341641d7 @laceynwilliams ✨ stunning spell to stop container
Rennervate $ docker start 2021341641d7 @laceynwilliams ✨ spell to revive a stupefied container
Avada Kedavra $ docker kill 2021341641d7 @laceynwilliams ☠ spell to kill a container
Advanced Potions Docker Compose @laceynwilliams
$ docker run -p 8000:8000 hogwarts @laceynwilliams
Docker Compose ✓ Free ✓ Included with Mac, extra download otherwise ✓ Run more than one container at once ✓ Relate containers to each other @laceynwilliams
Hermione's magic bag @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
then update settings.py @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
version:
'3' services: db: image:
postgres web: build:
. command:
bash
-c
"python /code/manage.py migrate --noinput && python /code/manage.py runserver 0.0.0.0:8000" volumes: -
.:/code ports: -
"8000:8000" depends_on: -
db @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 CMD [ "python" , "./manage.py" , ... ] @laceynwilliams
FROM python: 3.6 ENV PYTHONUNBUFFERED 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE
8000 ! @laceynwilliams
Lumos $ docker-compose up $ docker-compose up --build @laceynwilliams ✨ spell to start compose containers
$ docker-compose up Creating network "hogwarts_default" with the default driver Creating hogwarts_db_1 ... done Creating hogwarts_web_1 ... done Attaching to hogwarts_db_1, hogwarts_web_1 db_1 | The files belonging to this database system will be owned by user "postgres". db_1 | This user must also own the server process. web_1 | Operations to perform: web_1 | Apply all migrations: admin, auth, blog, contenttypes, sessions web_1 | Running migrations: web_1 | No migrations to apply. db_1 | LOG: database system is ready to accept connections db_1 | LOG: autovacuum launcher started web_1 | Performing system checks... web_1 | web_1 | System check identified no issues (0 silenced). web_1 | May 03, 2018 - 12:12:57 web_1 | Django version 2.0.5, using settings 'mysite.settings' web_1 | Starting development server at http://0.0.0.0:8000/ web_1 | Quit the server with CONTROL-C. @laceynwilliams
Continens Revelio $ docker container ls CONTAINER ID IMAGE ... NAMES f78a4fac4772 hogwarts_web ... hogwarts_web_1 1fdf3604ce5c postgres:9.6.8 ... hogwarts_db_1 @laceynwilliams ✨ spell to reveal containers
$ docker-compose run --rm web ./manage.py makemigrations Starting hogwarts_db_1 ... done No changes detected @laceynwilliams
--rm Remove this container when I'm done with it @laceynwilliams
apparate into the shell $ docker-compose run --rm web ./manage.py shell Starting hogwarts_db_1 ... done ... In [1]: from spells.models import Spell In [2]: Spell.objects.all() Out[2]: <QuerySet ['Accio', 'Alohomora', 'Expelliarmus']> @laceynwilliams
stop and start at will $ docker-compose stop web Stopping hogwarts_web_1 ... done $ docker-compose start web Starting web ... done @laceynwilliams
Nox $ docker-compose down Removing hogwarts_web_1 ... done Removing hogwarts_db_1 ... done Removing network hogwarts_default @laceynwilliams ✨ spell to darken containers
bit.ly/hogwarts-docker @laceynwilliams
It is the unknown we fear when we look upon Docker, nothing more. — Albus Dumbledore, probably @laceynwilliams | S/ll from Harry Po5er and the Order of the Phoenix
Hogwarts Library · An Intro to Docker for Djangonauts · Docker: Useful Command Line Stuff · Docker tutorial
· Docker Compose tutorial , Compose and Django tutorial · Best PracAces for WriAng Dockerfiles · 10 Things to Avoid in Docker Containers
· Video: 5 Things About Docker · Docker CheatSheet · Dockerizing Django, UWISGI, and Postgres the Serious Way · Managing SensiAve Data with Docker Secrets @laceynwilliams