Запускаем django-приложение в Docker на Vagrant под Windows

  • Tutorial
Привет Хабр! Несколько лет я находился в readonly-режиме на сайте Хабрахабр, изредка оставляя комментарии к чужим публикациям, и за несколько недель до нового года, мне захотелось поменять это положение вещей. Этому послужило мое недавнее задание на работе. А когда начал искать информацию, понял, что ее, как всегда, много, написано запутанно и не то что мне хотелось бы найти. А как быть, если этот человек новичок в этом вопросе? Вот и решил попробовать себя на этом поприще. Сделать туториал, который был бы полезен мне в первую очередь.

Поехали.

Уже несколько лет Docker был на слуху у меня, но никак не доводилось с ним поработать. А тут как раз менеджменту захотелось поменять свой стек. Начали говорить такие слова как Docker, контейнеры и облака. Чем не повод изучить что-то новое? Я работаю DevOps инженером на радио. Мой список технологий очень прост: Octopus Deploy + TeamCity + и тележка самописных приложений. Работает безотказно.

В этой статье я хочу поделиться информацией в том виде, в котором мне самому лично хотелось бы ее найти. Цель запустить Docker на Vagrant, создать образ с Django проектом по умолчанию, инициализировать контейнер и достучаться к сайту с основной ОС.

На работе я работаю под Windows. Для начала нам понадобится Chocolatey, чтобы установить необходимые софт.

Установим удобный терминал (cmder), VirtualBox и Vagrant:

C:\> choco install cmder
C:\> choco install vagrant
C:\> choco install virtualbox

Если не хотите использовать Chocolatey, можно поставить все вручную.

Создадим папку для нашего проекта, и добавим в него Vagrantfile файл:

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.network "forwarded_port", guest: 5000, host: 8080, host_ip: "127.0.0.1"
end

Обычно, этот файл можно сгенерировать одной командой vagrant init ubuntu/xenial64. Я добавил одну строчку для переадресации портов между основной и гостевой ОС на виртуальной машине. Это понадобится позже, когда мы захотим зайти на наш сайт, запущенный в контейнере.

Запустим виртуальную машину и подключимся к терминалу с помощью следующих двух Vagrant команд:

vagrant up
vagrant ssh

Мы должны успешно подключиться к терминалу виртуальной машине.

Перейдем к установке Docker:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce

Проверим, что Docker установлен успешно и сервис запущен. Выполним следующую команду:

sudo systemctl status docker

Создадим Dockerfile файл со следующим содержанием:

FROM python:latest

ENV PYTHONUNBUFFERED 1

RUN apt-get update
RUN mkdir /code

WORKDIR /code

RUN pip install django==1.11.8
RUN django-admin startproject mysite

RUN python mysite/manage.py migrate
RUN echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@example.com', 'pass')" | python mysite/manage.py shell

ADD . /code/

CMD python mysite/manage.py runserver 0.0.0.0:5000

Мы создали описание будущего образа с Django приложением по умолчанию. В этом описании, мы используем Python образ, и добавляем наших приправ, а именно: установка Django, создание проекта по умолчанию, запуск скриптов для инициализации базы данных и создание админ пользователя.

Давайте соберем образ, выполнив:

sudo docker build -t my/app:latest .

Эта команда подтягивает все необходимые образы из Docker реестра, и добавляет нашу конфигурацию в итоговый с названием my/app.

Запустите команду, и вы увидите свой собранный образ локально:

sudo docker images

Это всего лишь навсего образ как класс, который нам необходимо инициализировать. При инициализации мы создаем контейнер (объект). Контейнер это запущенный образ в Docker.

Создаем контейнер на базе нашего образа:

sudo docker run -d -p 5000:5000 my/app

Docker вернет вам сгенерированный уникальный идентификатор (guid) запущенного контейнера. Только что мы запустили наше приложение в контейнере. В команде мы указали Docker произвести сопоставление портов внутри контейнера и внешнего у гостевой ос.

Сверните удаленный терминал, и запустите браузер в основной системе. Перейдите по адресу: http://localhost:8080/

Вы увидите заглавную страницу Django приложения. Вы можете перейти на admin страницу, и войти в контрольную панель с admin/pass данными.

Почему Vagrant? Для экспериментов я никогда не устанавливаю ничего на основную систему, и работаю с виртуальными машинами. Если что-то пошло не так, всегда можно удалить и начать все сначала. Лучшая документация для меня — код.

Вернемся к консоли. Чтобы просмотреть логи, выполните команду:

sudo docker logs <guid контейнера> | head

Команда выведет output консоли, запущенного Django внутреннего сервера. Все то же, что вы видите обычно запустив python manage.py runserver у себя локально.

Выключим контейнер следующей командой:

sudo docker stop <guid контейнера>

Опять возвращаемся к нашему запущенному браузеру в основной системе, и перегружаем вебсайт. Он недоступен.

Когда контейнер остановлен, воспринимайте это как выключенный сервер. Состояние контейнера сохранено, как если бы вы сделали хибейрнет на своем десктопе.

Эта команда выведет список всех инициализированных контейнеров:

sudo docker ps -a

Давайте запустим наш контейнер снова:

sudo docker start <guid контейнера>

Браузер возвращает нам все тот же вебсайт. Можете залогиниться в контрольную панель, создать пользователя, и потом выключить и включить контейнер. Вы увидите, что пользователь сохранен и доступен, когда контейнер снова запущен.

Я специально использовал старую версию Django, чтобы показать следующий момент. Откройте Dockerfile, и отредактируйте его. Уберите версию Django, когда мы его устанавливаем с помощью pip команды.

Соберите новый образ командой:

sudo docker build -t my/app:latest .

Заметьте, мы не останавливали запущенный контейнер. Командой выше мы обновили образ, который хранится локально.

Давайте удалим текущий контейнер командой:

sudo docker kill <guid>

И запустим новый контейнер:

sudo docker run -d -p 5000:5000 my/app

Каждый раз, когда вы запускаете новый контейнер на базе образа, Docker генерирует ему уникальный идентификатор, по которому вы можете с ним работать (выключать, включать, подключаться по терминалу и т.д.)

На этом все, давайте подчистим за собой и уберем все лишнее.

Выйдите из SSH сессии в терминале, набрав:

exit

И вы снова у себя в домашней директории основной системы. Vagrant все еще запущен, Docker и ваш контейнер соответственно. Проверить это можно опять же через браузер, убедиться, что сайт еще запущен.

Чтобы удалить запущенную виртуальную машину в Vagrant, запустите:

vagrant halt
vagrant destroy

Первая команда выключает виртуальную машину и сохраняет ее состояние, а вторая производит удаление виртуальной машины из VirtualBox.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 24
  • +3
    django-приложение в Docker на Vagrant под Windows

    Яйцо в утке, утка в зайце, заяц в шоке…
    Docker работает и под Windows, зачем ещё прослойка? Да и что мешает использовать virtualenv?
    • +3
      Прослойку я использовал для того, что если в процессе что-то пойдет не так, всегда можно начать сначала. Это одна причина. Вторая, в силу параноидального менеджмента, доустанавливать необходимые компоненты на основную систему нельзя без администраторов. Да да, DevOps инжинер без административных прав на своем локальном компьютере. Поэтому все эксперименты я провожу на виртуальных машинах, где нет ограничений.

      Почему не virtualenv? В прошлом сталкивался с тем, что редкие пакеты просто отказывались устанавливаться под Windows. И нахожу хорошей практикой всегда запускать приложение в среде, приблеженней к Production.
      • +1
        Да да, DevOps инжинер без административных прав на своем локальном компьютере.

        Классика кровавого энтерпрайза параноидального менеджмента.
        Так может тогда Docker лишний?
        • +1
          Это была инициатива менеджмента. Они хотят поднять новый стек и использовать Docker. Так как я занимался CI/CD процессом на проекте для прошлого стека, меня назначили и на новый стек. Так что, Docker в моем случае обязательное звено.
          • 0
            Понял вас, спасибо.
            • +1
              А так да, забавно получилось. Матрешка.

              Правда это еще что. Вон на митапе пару лет назад парень запускал OpenStack в Vagrant, и потом несколько виртуальных машин уже на самом OpenStack. Было забавно наблюдать.
              • 0
                несколько виртуальных машин уже на самом OpenStack
                Для полного счастья надо было ещё внутри докер запустить.
                У нас облако на OpenStack, поэтому Vagrant и не используем, зато внутри крутятся gitlab-runner`ы и docker. Так что в принципе мы недалеко от «матрёшки» ушли. Но для локальной разработки используем только tox+virtalenv.
        • +1
          На рабочем компьютере менеджментом в виртуальных машинах вам разрешено запускать всё, что угодно, со свободным доступом к корпоративной сети?
          • 0
            Получается, что да. Любые сторонние процессы могут быть запущены из директории C:\Dev с ограничениями.
        • 0
          когда начинал экспериментировать с Docker, тоже выбрал связку vagrant + docker inside. Вполне себе неплохая песочница для экспериментов. Правда тогда еще не было «нативной» реализации Docker под Windows/macOS. А ставить docker-machine самому было сложнее, чем воспользоваться vagrant.
          • 0
            Более того, одно время у нас все проекты содержали в корне Vagrantfile в котором полностью описывалась инфраструктура для запуска проекта (включая БД, queue, nginx, uwsgi и пр.) — каждый проект в своей ВМ, каждый компонент в своём Docker контейнере внутри этой ВМ.

            Такой способ позволял легко поднять любой проект на любом хосте, включая компы тестировщиков. А заодно, позволил нам набрать экспертизу использования Docker.

            У нас есть даже история, когда мы ездили к нашему заказчику со своим Mac mini, чтобы развернуть у него тестовый стенд. В таком виде он проработал почти до окончания проекта.
            • –2
              Отлично, значит я на правильном пути. Спасибо.
        • +1

          Рассматривался ли вариант с docker-machine вместо vagrant?

          • +1
            Не рассматривался, но после этого комментария, обязательно посмотрю. Я только начал во всем этом разбираться. Спасибо.
          • +1
            У vagrant есть встроенный provisioner docker. И для установки Docker внутри гостевой системы достаточно в Vagrantfile прописать такую строчку:
            config.vm.provision "docker"
            

            И в качестве образов для виртуалок лучше подойдут образы из репозитария bento. Пруф.
            • 0
              Спасибо за информацию, обязательно посмотрю.
            • +1
              Это мануал про то как запустить docker в декабре 2017? При чем здесь вагрант, чем запуск отличается например от virtualbox?
              • –2
                Да, знаю, что поздно. Сам кинулся изучать, а толкового для начинающих не нашел, вот и написал. Запуск ничем не отличается, я воспользовался такой связкой. Вариантов на самом деле много, меня этот устраивает. В Production конечно же все будет настроено по другому.
              • 0
                Я в свое время очень огромное, с кучей зависимостей, приложение на Django деплоил под Windows через официальную штуку с bash. Согласен, NodeJS, пакеты в виртуальное окружение, PostgreSQL коряво ставятся до версии 1703 (в итоге PostgreSQL стоял отдельно в системе Windows), однако, начиная с нее все деплоиться аналогично любому Linux дистрибутиву. Если этот компонент Windows включен, то по сути права администратора не должны понадобится. Советую попробовать, хотя бы в качестве эксперимента. Минус только один в этом все — скорость работы. Как показывает практика — Docker быстрее работает.
                • 0
                  … используя ansible :)
                  Шутка шуткой, но возможно, позволит автоматизировать кое-какие вещи, если ещё не используете средств оркестрации. Мы у себя используем для некоторых тестов и обновления своего ПО на виртуалках.
                  • 0
                    Да, я хотел его использовать, но оказалось, что Vagrant требует его инсталяцию на основной ОС. А ждать службы поддержки, когда они мне его поставят, было неохота. Возможно, настою и установят в ближайшее время.
                  • 0
                    Простите за оффтоп, а зачем на радио DevOps? Интерес вполне рабочий, так как сам работаю на радио.
                    • 0
                      У нас несколько вебсайтов, корпоративный вебсайт, много сторонних сервисов для статистики. В CI/CD pipeline сейчас около 20 проектов, которые деплоятся несколько раз в неделю.
                    • 0

                      В свое время была такая же матрешка, сейчас с bash on windows(win 10) и нативным докером намного проще живется.

                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.