Поехали.
Уже несколько лет 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.
Комментарии (23)
renskiy
13.12.2017 10:04У vagrant есть встроенный provisioner docker. И для установки Docker внутри гостевой системы достаточно в Vagrantfile прописать такую строчку:
config.vm.provision "docker"
И в качестве образов для виртуалок лучше подойдут образы из репозитария bento. Пруф.
EgorLyutov
13.12.2017 12:51Это мануал про то как запустить docker в декабре 2017? При чем здесь вагрант, чем запуск отличается например от virtualbox?
stagor Автор
13.12.2017 12:56Да, знаю, что поздно. Сам кинулся изучать, а толкового для начинающих не нашел, вот и написал. Запуск ничем не отличается, я воспользовался такой связкой. Вариантов на самом деле много, меня этот устраивает. В Production конечно же все будет настроено по другому.
balyko
13.12.2017 12:52Я в свое время очень огромное, с кучей зависимостей, приложение на Django деплоил под Windows через официальную штуку с bash. Согласен, NodeJS, пакеты в виртуальное окружение, PostgreSQL коряво ставятся до версии 1703 (в итоге PostgreSQL стоял отдельно в системе Windows), однако, начиная с нее все деплоиться аналогично любому Linux дистрибутиву. Если этот компонент Windows включен, то по сути права администратора не должны понадобится. Советую попробовать, хотя бы в качестве эксперимента. Минус только один в этом все — скорость работы. Как показывает практика — Docker быстрее работает.
skymal4ik
13.12.2017 13:33… используя ansible :)
Шутка шуткой, но возможно, позволит автоматизировать кое-какие вещи, если ещё не используете средств оркестрации. Мы у себя используем для некоторых тестов и обновления своего ПО на виртуалках.stagor Автор
13.12.2017 14:06Да, я хотел его использовать, но оказалось, что Vagrant требует его инсталяцию на основной ОС. А ждать службы поддержки, когда они мне его поставят, было неохота. Возможно, настою и установят в ближайшее время.
bkv
15.12.2017 00:32Простите за оффтоп, а зачем на радио DevOps? Интерес вполне рабочий, так как сам работаю на радио.
stagor Автор
15.12.2017 00:34У нас несколько вебсайтов, корпоративный вебсайт, много сторонних сервисов для статистики. В CI/CD pipeline сейчас около 20 проектов, которые деплоятся несколько раз в неделю.
onegreyonewhite
Яйцо в утке, утка в зайце, заяц в шоке…
Docker работает и под Windows, зачем ещё прослойка? Да и что мешает использовать virtualenv?
stagor Автор
Прослойку я использовал для того, что если в процессе что-то пойдет не так, всегда можно начать сначала. Это одна причина. Вторая, в силу параноидального менеджмента, доустанавливать необходимые компоненты на основную систему нельзя без администраторов. Да да, DevOps инжинер без административных прав на своем локальном компьютере. Поэтому все эксперименты я провожу на виртуальных машинах, где нет ограничений.
Почему не virtualenv? В прошлом сталкивался с тем, что редкие пакеты просто отказывались устанавливаться под Windows. И нахожу хорошей практикой всегда запускать приложение в среде, приблеженней к Production.
onegreyonewhite
Классика
кровавого энтерпрайзапараноидального менеджмента.Так может тогда Docker лишний?
stagor Автор
Это была инициатива менеджмента. Они хотят поднять новый стек и использовать Docker. Так как я занимался CI/CD процессом на проекте для прошлого стека, меня назначили и на новый стек. Так что, Docker в моем случае обязательное звено.
onegreyonewhite
Понял вас, спасибо.
stagor Автор
А так да, забавно получилось. Матрешка.
Правда это еще что. Вон на митапе пару лет назад парень запускал OpenStack в Vagrant, и потом несколько виртуальных машин уже на самом OpenStack. Было забавно наблюдать.
onegreyonewhite
У нас облако на OpenStack, поэтому Vagrant и не используем, зато внутри крутятся gitlab-runner`ы и docker. Так что в принципе мы недалеко от «матрёшки» ушли. Но для локальной разработки используем только tox+virtalenv.
MMik
На рабочем компьютере менеджментом в виртуальных машинах вам разрешено запускать всё, что угодно, со свободным доступом к корпоративной сети?
stagor Автор
Получается, что да. Любые сторонние процессы могут быть запущены из директории
C:\Dev
с ограничениями.renskiy
когда начинал экспериментировать с Docker, тоже выбрал связку vagrant + docker inside. Вполне себе неплохая песочница для экспериментов. Правда тогда еще не было «нативной» реализации Docker под Windows/macOS. А ставить docker-machine самому было сложнее, чем воспользоваться vagrant.
renskiy
Более того, одно время у нас все проекты содержали в корне Vagrantfile в котором полностью описывалась инфраструктура для запуска проекта (включая БД, queue, nginx, uwsgi и пр.) — каждый проект в своей ВМ, каждый компонент в своём Docker контейнере внутри этой ВМ.
Такой способ позволял легко поднять любой проект на любом хосте, включая компы тестировщиков. А заодно, позволил нам набрать экспертизу использования Docker.
У нас есть даже история, когда мы ездили к нашему заказчику со своим Mac mini, чтобы развернуть у него тестовый стенд. В таком виде он проработал почти до окончания проекта.
stagor Автор
Отлично, значит я на правильном пути. Спасибо.