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.

2c7f0a1020fbd01942166122190180f8?s=128

Lacey Williams Henschel

October 15, 2018
Tweet

Transcript

  1. An Intro to Docker for Djangonauts Lacey Williams Henschel DjangoCon

    US 2018 ! @laceynwilliams | @revsys
  2. @laceynwilliams | @revsys

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

  4. magic @laceynwilliams | @revsys

  5. Docker ✓ Separate dependencies ✓ Shares your OS ✓ All

    team members on the same page ✓ No Python installs needed! @laceynwilliams | @revsys
  6. But... ✓ Learning curve @laceynwilliams | @revsys

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

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

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

  10. The image is the person you want to turn into

    @laceynwilliams | Source: Harry Po5er Wiki
  11. The container is you @laceynwilliams | @revsys

  12. image executable that contains all the packages for your project

    container run6me instance of image @laceynwilliams | @revsys
  13. The Dockerfile is the hair of the person you want

    to turn into @laceynwilliams | Source: Beth Purchases
  14. Dockerfile is the DNA @laceynwilliams | @revsys

  15. image executable that contains all the packages for your project

    container run6me instance of image Dockerfile file that defines your image @laceynwilliams | @revsys
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  26. Brew your potion $ docker build . @laceynwilliams | @revsys

  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
  28. Name of your image 80fbc70dc709 @laceynwilliams | @revsys

  29. $ docker build -t hogwarts . Successfully built 4521a153fa19 Successfully

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

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

    of Secrets
  32. Step 1/8 : FROM python:3.6 ... Step 2/8 : ENV

    PYTHONUNBUFFERED 1 ... @laceynwilliams | @revsys
  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
  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
  35. The Standard Book of Spells Grade 1 Docker Edition @laceynwilliams

    | @revsys
  36. Imago Revelio $ docker images REPOSITORY TAG IMAGE ID CREATED

    SIZE hogwarts latest 4521a153fa19 42 hours ago 734MB @laceynwilliams ✨ spell to reveal images
  37. Continens Revelio $ docker container ls CONTAINER ID IMAGE COMMAND

    CREATED STATUS PORTS NAMES @laceynwilliams ✨ spell to reveal containers
  38. Drink your potion $ docker run -p 8000:8000 hogwarts @laceynwilliams

    | @revsys
  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
  40. Apparate $ docker exec -it 2021341641d7 shell root@2021341641d7:/code# @laceynwilliams ✨

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

    @revsys
  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
  43. Disapparate ctrl + d @laceynwilliams ✨ magical teleporta2on out of

    container shell
  44. $ docker container ls CONTAINER ID IMAGE COMMAND 2021341641d7 hogwarts

    "python ./manage.py …" @laceynwilliams | @revsys
  45. Stupefy $ docker stop 2021341641d7 @laceynwilliams ✨ stunning spell to

    stop container
  46. Rennervate $ docker start 2021341641d7 @laceynwilliams ✨ spell to revive

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

    kill a container
  48. Advanced Potions Docker Compose @laceynwilliams | @revsys

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

  50. Docker Compose ✓ Free ✓ Included with Mac, extra download

    otherwise ✓ Run more than one container at once ✓ Relate containers to each other @laceynwilliams | @revsys
  51. Hermione's magic bag @laceynwilliams | @revsys

  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
  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
  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
  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
  56. then update settings.py @laceynwilliams | @revsys

  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
  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
  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
  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
  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
  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
  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
  64. Lumos $ docker-compose up $ docker-compose up --build @laceynwilliams ✨

    spell to start compose containers
  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
  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
  67. $ docker-compose run --rm web ./manage.py makemigrations Starting hogwarts_db_1 ...

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

    | @revsys
  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]: <QuerySet ['Accio', 'Alohomora', 'Expelliarmus']> @laceynwilliams | @revsys
  70. stop and start at will $ docker-compose stop web Stopping

    hogwarts_web_1 ... done $ docker-compose start web Starting web ... done @laceynwilliams | @revsys
  71. Nox $ docker-compose down Removing hogwarts_web_1 ... done Removing hogwarts_db_1

    ... done Removing network hogwarts_default @laceynwilliams ✨ spell to darken containers
  72. bit.ly/hogwarts-docker @laceynwilliams | @revsys

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