$30 off During Our Annual Pro Sale. View Details »

An Intro to Docker for Djangonauts

An Intro to Docker for Djangonauts

If you’ve never used it before, Docker can be a little overwhelming. There is new vocabulary to learn, new commands to memorize, and new files to add to each project. Most resources fall into one of two camps: they teach you the bare bones of Docker but still leave you with too many questions to comfortably try it on your own, or they throw you into the deep end by assuming you’re more familiar with Docker than you are.

In this talk, you will find that middle ground: a talk that doesn’t assume you’re familiar with Docker and so keeps everything simple, but leaves you with enough information that you can get started as soon as you leave the room. Together, we will step through the parts of a Dockerfile and learn what they do. Then, I’ll introduce you to Docker Compose and explain why using it to run multiple containers is helpful. Finally, you will learn to run commands and execute scripts from the command line using Docker, how to enter a container and why you might need to, and what to do before you go home for the day.

Lacey Williams Henschel

October 15, 2018
Tweet

More Decks by Lacey Williams Henschel

Other Decks in Technology

Transcript

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

    View Slide

  2. @laceynwilliams | @revsys

    View Slide

  3. What is
    Docker?
    !
    @laceynwilliams | Source: XKCD

    View Slide

  4. magic
    @laceynwilliams | @revsys

    View Slide

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

    View Slide

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

    View Slide

  7. What about
    virtualenvs?
    @laceynwilliams | Source: XKCD

    View Slide

  8. Polyjuice Potion
    Images and Containers
    @laceynwilliams | @revsys

    View Slide

  9. Docker is the potion
    @laceynwilliams | Source: Karen Roe

    View Slide

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

    View Slide

  11. The
    container
    is you
    @laceynwilliams | @revsys

    View Slide

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

    View Slide

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

    View Slide

  14. Dockerfile is
    the DNA
    @laceynwilliams | @revsys

    View Slide

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

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

    View Slide

  17. 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

    View Slide

  18. 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

    View Slide

  19. 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

    View Slide

  20. 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

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. 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

    View Slide

  24. 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

    View Slide

  25. 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

    View Slide

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

    View Slide

  27. $ 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

    View Slide

  28. Name of your image
    80fbc70dc709
    @laceynwilliams | @revsys

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  33. • 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

    View Slide

  34. 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

    View Slide

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

    View Slide

  36. Imago Revelio
    $ docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    hogwarts latest 4521a153fa19 42 hours ago 734MB
    @laceynwilliams

    spell to reveal images

    View Slide

  37. Continens Revelio
    $ docker container ls
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    @laceynwilliams

    spell to reveal containers

    View Slide

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

    View Slide

  39. 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

    View Slide

  40. Apparate
    $ docker exec -it 2021341641d7 shell
    root@2021341641d7:/code#
    @laceynwilliams

    magical teleporta2on into container

    View Slide

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

    View Slide

  42. 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

    View Slide

  43. Disapparate
    ctrl + d
    @laceynwilliams

    magical teleporta2on out of container shell

    View Slide

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

    View Slide

  45. Stupefy
    $ docker stop 2021341641d7
    @laceynwilliams

    stunning spell to stop container

    View Slide

  46. Rennervate
    $ docker start 2021341641d7
    @laceynwilliams

    spell to revive a stupefied container

    View Slide

  47. Avada Kedavra
    $ docker kill 2021341641d7
    @laceynwilliams

    spell to kill a container

    View Slide

  48. Advanced
    Potions
    Docker Compose
    @laceynwilliams | @revsys

    View Slide

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

    View Slide

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

    View Slide

  51. Hermione's
    magic bag
    @laceynwilliams | @revsys

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

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

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

    View Slide

  55. # 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

    View Slide

  56. then update
    settings.py
    @laceynwilliams | @revsys

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

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

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

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

    View Slide

  61. # 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

    View Slide

  62. 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

    View Slide

  63. 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

    View Slide

  64. Lumos
    $ docker-compose up
    $ docker-compose up --build
    @laceynwilliams

    spell to start compose containers

    View Slide

  65. $ 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

    View Slide

  66. 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

    View Slide

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

    View Slide

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

    View Slide

  69. 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

    View Slide

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

    View Slide

  71. Nox
    $ docker-compose down
    Removing hogwarts_web_1 ... done
    Removing hogwarts_db_1 ... done
    Removing network hogwarts_default
    @laceynwilliams

    spell to darken containers

    View Slide

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

    View Slide

  73. 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

    View Slide

  74. 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

    View Slide