An Intro to Docker for Djangonauts

A presentation at DjangoCon Europe 2018 in May 2018 in Heidelberg, Germany by Lacey Williams Henschel

Slide 1

Slide 1

An Intro to Docker for Djangonauts Lacey Williams Henschel DjangoCon Europe 2018 @laceynwilliams

Slide 2

Slide 2

@laceynwilliams

Slide 3

Slide 3

What is Docker? ! @laceynwilliams | Source: XKCD

Slide 4

Slide 4

magic @laceynwilliams

Slide 5

Slide 5

Docker ✓ Separate dependencies ✓ Shares your OS ✓ All team members on the same page ✓ No Python installs needed! @laceynwilliams

Slide 6

Slide 6

But... ✓ Learning curve @laceynwilliams

Slide 7

Slide 7

What about virtualenvs? @laceynwilliams | Source: XKCD

Slide 8

Slide 8

Polyjuice Potion Images and Containers @laceynwilliams

Slide 9

Slide 9

Docker is the potion @laceynwilliams | Source: Karen Roe

Slide 10

Slide 10

The image is the person you want to turn into @laceynwilliams | Source: Harry Po5er Wiki

Slide 11

Slide 11

The container

is you @laceynwilliams

Slide 12

Slide 12

image executable that contains all the packages for your project container run6me instance of image @laceynwilliams

Slide 13

Slide 13

The Dockerfile is the hair of the person you want to turn into @laceynwilliams | Source: Beth Purchases

Slide 14

Slide 14

Dockerfile is the DNA @laceynwilliams

Slide 15

Slide 15

image executable that contains all the packages for your project container run6me instance of image Dockerfile file that defines your image @laceynwilliams

Slide 16

Slide 16

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

Slide 17

Slide 17

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

Slide 18

Slide 18

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

Slide 19

Slide 19

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

Slide 20

Slide 20

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

Slide 21

Slide 21

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

Slide 22

Slide 22

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

Slide 23

Slide 23

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

Slide 24

Slide 24

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

Slide 25

Slide 25

Brew your potion $ docker build . @laceynwilliams

Slide 26

Slide 26

$ 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

Slide 27

Slide 27

Name of your image 80fbc70dc709 @laceynwilliams

Slide 28

Slide 28

$ docker build -t hogwarts . Successfully built 4521a153fa19 Successfully tagged hogwarts:latest @laceynwilliams

Slide 29

Slide 29

image:tag

python: 3.6 hogwarts:latest @laceynwilliams

Slide 30

Slide 30

Layers @laceynwilliams | S/ll from Harry Po5er and the Chamber of Secrets

Slide 31

Slide 31

Step 1/8 : FROM python:3.6 ... Step 2/8 : ENV PYTHONUNBUFFERED 1 ... @laceynwilliams

Slide 32

Slide 32

• 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

Slide 33

Slide 33

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

Slide 34

Slide 34

The Standard Book of Spells Grade 1 Docker Edition @laceynwilliams

Slide 35

Slide 35

Imago Revelio $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hogwarts latest 4521a153fa19 42 hours ago 734MB @laceynwilliams ✨ spell to reveal images

Slide 36

Slide 36

Continens Revelio $ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES @laceynwilliams ✨ spell to reveal containers

Slide 37

Slide 37

Drink your potion $ docker run -p 8000:8000 hogwarts @laceynwilliams

Slide 38

Slide 38

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

Slide 39

Slide 39

Apparate $ docker exec -it 2021341641d7 shell root@2021341641d7:/code# @laceynwilliams ✨ magical teleporta2on into container

Slide 40

Slide 40

root@2021341641d7:/code# ls Dockerfile blog mysite requirements.txt README.md manage.py
@laceynwilliams

Slide 41

Slide 41

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

Slide 42

Slide 42

Disapparate ctrl + d @laceynwilliams ✨ magical teleporta2on out of container shell

Slide 43

Slide 43

$ docker container ls CONTAINER ID IMAGE COMMAND
2021341641d7 hogwarts "python ./manage.py …"
@laceynwilliams

Slide 44

Slide 44

Stupefy $ docker stop 2021341641d7 @laceynwilliams ✨ stunning spell to stop container

Slide 45

Slide 45

Rennervate $ docker start 2021341641d7 @laceynwilliams ✨ spell to revive a stupefied container

Slide 46

Slide 46

Avada Kedavra $ docker kill 2021341641d7 @laceynwilliams ☠ spell to kill a container

Slide 47

Slide 47

Advanced Potions Docker Compose @laceynwilliams

Slide 48

Slide 48

$ docker run -p 8000:8000 hogwarts @laceynwilliams

Slide 49

Slide 49

Docker Compose ✓ Free ✓ Included with Mac, extra download otherwise ✓ Run more than one container at once ✓ Relate containers to each other @laceynwilliams

Slide 50

Slide 50

Hermione's magic bag @laceynwilliams

Slide 51

Slide 51

docker-compose.yml

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

Slide 52

Slide 52

docker-compose.yml

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

Slide 53

Slide 53

docker-compose.yml

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

Slide 54

Slide 54

docker-compose.yml

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

Slide 55

Slide 55

then update settings.py @laceynwilliams

Slide 56

Slide 56

docker-compose.yml

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

Slide 57

Slide 57

docker-compose.yml

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

Slide 58

Slide 58

docker-compose.yml

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

Slide 59

Slide 59

docker-compose.yml

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

Slide 60

Slide 60

docker-compose.yml

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

Slide 61

Slide 61

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

Slide 62

Slide 62

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

Slide 63

Slide 63

Lumos $ docker-compose up $ docker-compose up --build @laceynwilliams ✨ spell to start compose containers

Slide 64

Slide 64

$ 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

Slide 65

Slide 65

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

Slide 66

Slide 66

$ docker-compose run --rm web ./manage.py makemigrations Starting hogwarts_db_1 ... done No changes detected @laceynwilliams

Slide 67

Slide 67

--rm Remove this container when I'm done with it @laceynwilliams

Slide 68

Slide 68

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

Slide 69

Slide 69

stop and start at will $ docker-compose stop web Stopping hogwarts_web_1 ... done $ docker-compose start web Starting web ... done @laceynwilliams

Slide 70

Slide 70

Nox $ docker-compose down Removing hogwarts_web_1 ... done Removing hogwarts_db_1 ... done Removing network hogwarts_default @laceynwilliams ✨ spell to darken containers

Slide 71

Slide 71

bit.ly/hogwarts-docker @laceynwilliams

Slide 72

Slide 72

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

Slide 73

Slide 73

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