Slide 1

Slide 1 text

An Intro to Docker for Djangonauts Lacey Williams Henschel DjangoCon US 2018 ! @laceynwilliams | @revsys

Slide 2

Slide 2 text

@laceynwilliams | @revsys

Slide 3

Slide 3 text

What is Docker? ! @laceynwilliams | Source: XKCD

Slide 4

Slide 4 text

magic @laceynwilliams | @revsys

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

But... ✓ Learning curve @laceynwilliams | @revsys

Slide 7

Slide 7 text

What about virtualenvs? @laceynwilliams | Source: XKCD

Slide 8

Slide 8 text

Polyjuice Potion Images and Containers @laceynwilliams | @revsys

Slide 9

Slide 9 text

Docker is the potion @laceynwilliams | Source: Karen Roe

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

The container is you @laceynwilliams | @revsys

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

Dockerfile is the DNA @laceynwilliams | @revsys

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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 | @revsys

Slide 17

Slide 17 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 18

Slide 18 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 19

Slide 19 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 20

Slide 20 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 21

Slide 21 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 22

Slide 22 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 23

Slide 23 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 24

Slide 24 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 25

Slide 25 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 26

Slide 26 text

Brew your potion $ docker build . @laceynwilliams | @revsys

Slide 27

Slide 27 text

$ 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 | @revsys

Slide 28

Slide 28 text

Name of your image 80fbc70dc709 @laceynwilliams | @revsys

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

# image:tag python:3.6 hogwarts:latest @laceynwilliams | @revsys

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

• 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 | @revsys

Slide 34

Slide 34 text

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 | @revsys

Slide 35

Slide 35 text

The Standard Book of Spells Grade 1 Docker Edition @laceynwilliams | @revsys

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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 | @revsys

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Advanced Potions Docker Compose @laceynwilliams | @revsys

Slide 49

Slide 49 text

$ docker run -p 8000:8000 hogwarts @laceynwilliams | @revsys

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Hermione's magic bag @laceynwilliams | @revsys

Slide 52

Slide 52 text

# 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 | @revsys

Slide 53

Slide 53 text

# 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 | @revsys

Slide 54

Slide 54 text

# 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 | @revsys

Slide 55

Slide 55 text

# 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 | @revsys

Slide 56

Slide 56 text

then update settings.py @laceynwilliams | @revsys

Slide 57

Slide 57 text

# 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 | @revsys

Slide 58

Slide 58 text

# 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 | @revsys

Slide 59

Slide 59 text

# 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 | @revsys

Slide 60

Slide 60 text

# 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 | @revsys

Slide 61

Slide 61 text

# 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 | @revsys

Slide 62

Slide 62 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 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 | @revsys

Slide 63

Slide 63 text

FROM python:3.6 ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 1 COPY ./requirements.txt /code/requirements.txt RUN pip install -r /code/requirements.txt COPY . /code/ WORKDIR /code/ EXPOSE 8000 ! @laceynwilliams | @revsys

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

$ 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 | @revsys

Slide 66

Slide 66 text

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 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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]: @laceynwilliams | @revsys

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

bit.ly/hogwarts-docker @laceynwilliams | @revsys

Slide 73

Slide 73 text

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 74

Slide 74 text

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, Rafael Benevides · Video: 5 Things About Docker, Jessie Frazelle · Docker CheatSheet · Dockerizing Django, UWISGI, and Postgres the Serious Way, Oliver Eidel · How to use Django, PostgreSQL, and Docker, William S. Vincent · Managing SensiAve Data with Docker Secrets @laceynwilliams | @revsys