Come work in Estonia – the most advanced digital society. Many Ukrainians already know that Estonia is affordable – become one of them and check out the jobs available!

Виртуализация процесса разработки, часть 2: Docker и Vagrant

В предыдущей статье я уже рассказал, как мы в Preply.com используем Docker для развертывания локальной среды разработки, поднимая каждый необходимый сервис в отдельном контейнере.

В данной статье я опишу как правильно настраивать и поднимать Vagrant — виртуальную машину в которой можно установить Docker. Ранее мы использовали Vagrant только для того, чтобы иметь возможность запускать Docker на любой платформе, однако теперь — когда почти под каждую платформу существует Docker Toolbox, Vagrant потерял свою актуальность. В любом случае, первая часть статьи — инструкция по тому как правильно работать с Vagrant.

Во второй части статьи я вернусь к Docker и опишу процесс поднятия локальной базы данных в контейнере с использованием Docker Volumes.

Vagrant

Единственная причина, по которой мы пользуемся Vagrant — ради возможности создавать изолированную среду разработки, основанную на виртуальной машине со всеми необходимыми сервисами, которая должна будет воспроизвести реальную рабочую среду. Другими словами, лишь для того чтобы иметь возможность запустить Docker.

Эта среда может быть легко\просто и быстро установлена на любой машине ваших сотрудников. Для этого вам необходимо будет всего лишь установить Vagrant и VirtualBox (или другое похожее ПО) на локальную машину.

Чтобы запустить виртуальную машину, нам нужно создать файл под названием Vagrantfile в корневом каталоге нашего проекта.

Вот хороший пример файла Vagrantfile:

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

Vagrant.configure(2) do |config|

  config.vm.box = "ubuntu/trusty64"
  config.vm.network :forwarded_port, guest: 80, host: 8000
  config.vm.synced_folder ".", "/project"

  # We are going to give VM 1/4 system memory & access to all cpu cores on the host
  config.vm.provider "virtualbox" do |vb|
    host = RbConfig::CONFIG['host_os']
    if host =~ /darwin/
      cpus = `sysctl -n hw.ncpu`.to_i
      mem = `sysctl -n hw.memsize`.to_i / 1024 / 1024 / 4
    elsif host =~ /linux/
      cpus = `nproc`.to_i
      mem = `grep 'MemTotal' /proc/meminfo | sed -e 's/MemTotal://' -e 's/ kB//'`.to_i / 1024 / 4
    else
      cpus = 2
      mem = 1024
    end
    vb.customize ["modifyvm", :id, "--memory", mem]
    vb.customize ["modifyvm", :id, "--cpus", cpus]
  end

  config.vm.provision "shell", inline: <<-SHELL
    # Install docker and docker compose
    sudo -i
    echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
    curl -sSL https://get.docker.com/ | sh
    usermod -aG docker vagrant
    curl -L https://github.com/docker/compose/releases/download/1.5.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    chmod +x /usr/local/bin/docker-compose
  SHELL
end

Мы будем использовать этот файл для запуска нашей виртуальной машины, набирая на клавиатуре следующую команду:
vagrant up --provision

Если вы увидите предупреждение о новой версии вашего первоначального бокса, просто делайте так:
vagrant box update

Давайте рассмотрим детальней, что он делает:
— Он извлечет образ ubuntu/trusty64 операционной системы из хранилища vagrant;
— Он направит 80-й порт изнутри на 8000-й снаружи;
— Он закрепит ваш текущий каталог к каталогу ’/project’ внутри машины;
— Он даст 1/4 системной памяти & доступ ко всем ядрам центрального процессор из виртуальной машины;
— Он установит Docker и Docker-Compose внутри виртуальной машины.

Вот и все. Теперь вам нужно всего лишь зайти внутрь данной Виртуальной Машины путем набора на клавиатуре:
vagrant ssh

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

docker --version
docker-compose --version

Если нет — попробуйте установить вручную: Docker и Docker-Compose.

Давайте посмотрим наш каталог проекта внутри Виртуальной Машины и установим переменную среду RUN_ENV to DEV:

cd /project
export RUN_ENV=DEV

Теперь вы можете сделать локальное повторное развертывание элементарно (как было описано в предыдущей статье):
sh redeploy.sh

Итак, теперь можно пользоваться вашим локальным сервером по ссылке 127.0.0.1:8000.

Вы можете применить три разных команды для завершения работы с вашей Виртуальной Машиной:

vagrant suspend     # - to freeze your VM with saved RAM
vagrant halt        # - to stop your VM but save all files
vagrant destroy     # - to fully delete your virtual machine!

Создание локальной базы данных в контейнере

По умолчанию мы основываемся на том, что вы используете Docker 1.9 и Docker-Compose 1.5.1 или более поздними версиями.

Была большая путаница с томами\разделами в Docker до версий 1.9. Но теперь Docker внедрил Volume как отдельную сущность на ряду с контейнерами и образами! Теперь вы можете создать раздел (volume) отдельно от контейнеров и образов. К разделам можно достучаться в любое время из любого количества смонтированных контейнеров. И не нужно беспокоиться о сохранности данных даже в случае удаления контейнера.

Это очень просто. Чтобы посмотреть список всех ваших локальных разделов, сделайте следующее:
docker volume ls

Чтобы проверить раздел:
docker volume inspect <volume_name>

Создать новый раздел:
docker volume create --name=<volume_name>

А чтобы удалить раздел сделайте так:
docker volume rm <volume_name>

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

Создание локальной базы данных

Мы запустим контейнер Docker с PostgreSQL и закрепим его к уже созданному Docker Volume. Давайте создадим локальный раздел для нашей базы данных:
docker volume create --name=local_postgres

Мы будем использовать временный файл docker-compose.database.yml file:

  postgres:
      image: postgres:9.1
      container_name: some-postgres
      volumes:
        - local_postgres:/var/lib/postgresql/data
      ports:
        - "5432:5432"
      environment:
        POSTGRES_PASSWORD: "$POSTGRES_PASSWORD"
        POSTGRES_USER: "$POSTGRES_USER"

И запустим контейнер с PostgreSQL:
docker-compose -f docker-compose.database.yml up -d

Теперь у вас есть пустая база данных, работающая в контейнере и доступная на localhost:5432 (или другом хосте, если вы запускаете Docker на Mac).

Вы можете подключиться к этому контейнеру:
docker exec -it some-postgres /bin/bash

Переключите на нужного пользователя:
su postgres

Запустите PSQL:
psql

И, например, создайте новую базу данных:
CREATE DATABASE test;

Выйти из PSQL:
\q

Вы легко можете удалить этот контейнер следующим образом:

docker-compose -f docker-compose.database.yml stop
docker-compose -f docker-compose.database.yml rm -f

Все созданные данные будут сохранены в раздел local_postgres.

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

Сохранение базы в файл

Скажем, вы хотите сохранить данные из вашей локальной базы данных. Вам необходимо запустить простой контейнер с базой и смонтировать ваш локальный каталог с каким-то каталогом в контейнере. Затем вы заходите в контейнер и сохраняете данные как файл в этот вмонтированный каталог.

Давайте сделаем это:

postgres:
  image: postgres:9.1
  container_name: some-postgres
  volumes:
    - local_postgres:/var/lib/postgresql/data
    - .:/data
  ports:
    - "5432:5432"
  environment:
    POSTGRES_PASSWORD: "$POSTGRES_PASSWORD"
    POSTGRES_USER: "$POSTGRES_USER"

В этом примере мы монтируем наш текущий каталог с каталогом /data внутри контейнера. Зайдите внутрь:

docker exec -it some-postgres /bin/bash
su postgres

И выполним дамп:

pg_dump --host 'localhost' -U postgres test -f /data/test.out

Эта команда сохранит тестовую базу данных в файл test.out в вашем текущем каталоге. Теперь вы можете удалить этот контейнер.

Загрузка данных из файла

Воспользуйтесь той же техникой монтирования каталогов для загрузки данных из файла. Чтобы загрузить данные, если вы уже в контейнере postgres и /data/test.out смонтированы, примените команду:
psql --host 'localhost' --username postgres test < /data/test.out

Не забудьте перед этим создать базу данных test.


P.S. Пожалуйста, не стесняйтесь делиться своим опытом по организации процесса разработки в вашей команде и удачными методиками работы с Docker и Vagrant. Пишите в комментариях к статье или же на почту или в фейсбук. Спасибо!

57 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

я верно понимаю бутерброт такой:
vargant -> docker -> [image -> app]
[] - контейнер
тоесть в каждом контейнере есть своя image (например ubuntu) и каждая image жрет ОЗУ?

Кстати, можно такой вопрос от полного профана в доккерах. Можно-ли в доккере развернуть среду разработки. Будет ли это удобнее, чем иметь несколько виртуалок? Можно-ли сделать доккер, и при запуске задавать набор параметров для преднастроики среды?

Мне удобнее виртуалка + автоматическое развертывание среды.

В виртуалке? Но в них-то все просто. Сделал 10 виртуалок под 10 вариантов настроек и работай в них.
Мне интересно было с доккерами? Облегчают ли они сей процесс. То бишь одна базовая виртуалка, они ее поднимают в 10 разных вариантах с недублированием всего?

Краткий ответ на Ваш вопрос.

1. Эти 10 виртуалок будут занимать меньше места. Недублирование всего достигается за счет Union File System en.wikipedia.org/wiki/UnionFS
2. Меньше ресурсов будут потреблять. Нет хипервизора.
3. Стартуют быстрее. Как раз потому что не надо дублировать все. Запуск среды это добавление read-write слоя. снова UFS из первого пункта

docs.docker.com/...ine/understanding-docker
И вот
docs.docker.com/...iver/imagesandcontainers

Облегчают ли они сей процесс?

Если вы настроили процесс с помощью того же вагранта и у вас нет приреканий, например на скорость сборки или потребляемые ресурсы, то Вам не стоит что-то менять.

В первую очередь разные версии компиляторов, разные версии библиотек и разные переменные среды. Т.е. по сути система всё таже, но быстро перключаться между этими вариантами.
В случае виртуалки всё быстро и удобно, но в каждой виртуалке 95% всего одинаково и дублируется. И запуск в параллель нескольких виртуалок жрет память, пропорционально их количеству.

Да, Docker может быть Вам полезным. Эти проблемы он и решает.

О, спасибо, буду изучать и пробовать.

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

Можно все что можно в линукс. Докер это набор скриптов поверх cgroups, chroot, aufs, и еще парочки технологий. Это не виртуальная машина, это всего лишь изоляция процессов, со своими плюсами и минусами. Как и в любые другие процессы, перед запуском вы можете передать переменные окружения, смонтировать папки, пробросить порты. Все процессы работают на том же ядре что и хост система, это накладывает определенные ограничения на то что можно запустить внутри контейнера. Из плюсов конечно минимальный оверхед по производительности, общая файловая система и тд. К минусом так же можно отнести низкую безопасность, так как в том же cgroups постоянно латают дырки, когда процессы могут получить доступ к памяти и прочим ресурсам за пределами контейнера. Так что докер это: быстро, не безопасно, иногда удобно, иногда не удобно (потому что это неполноценная контейнеризация ос как например lxc/lxd и тем более не полная виртуализация как xen/kvm).

А есть ли какой ГУЙ для чайников к нему, чтобы можно было юзать, не влазя в его глубины?
Ну типа того, что в VirtualBox.
типа создать контейнер, тут пропиши то-то тут то-то там с примером и хелпом.

Хм, хороших не знаю. В реальности проще всего освоить cli. Так как ui не сможет покрыть все возможные варианты использования. И в итоге не позволит реализовать то что хочется.

В VB типичные вещи в gui внесены. А не типичные — cli. Так что для простого пользования gui хватает, для чего не общеупотребимого есть cli.

Ты у меня спрашивает то, что я спросил час назад? Я не знаю, может и он, а может и нет.
Нахрена мне было бы спрашивать, если бы и так знал. Чтобы почесать ЧСВ? Тут и без этого срачей хватает, где идиотов толпами и над ними стебаться веселее.

я знак вопроса поставил, потому что я слышал о такой утилите, но ниразу ее не использовал и не уверен в ее адекватности

соответственно могу подсказать, но рекомендовать ее не буду

Также вот интересный патерн. Смысл в том что данные можно хранить как контейнер, это избавляет от зависимости, которую вы создаете ссылаясь на папку в хосте
docs.docker.com/...c12a239db6771d5b9954eba86

Ще момент, як базовий образ краще використовувати baseimage-docker. Проблеми які він вирішує — phusion.github.io/baseimage-docker

FYI:
Згідно наведених інструкцій:

> docker exec -it some-postgres /bin/bash
root@63b095084532:/# su postgres
$ pg_dump --host 'localhost' -U postgres test -f /data/test.out
pg_dump: [archiver] could not open output file "/data/test.out": Permission denied

Проте працює без su postgres:

> docker exec -it some-postgres /bin/bash
root@63b095084532:/# pg_dump --host 'localhost' -U postgres test -f /data/test.out
root@63b095084532:/# exit

Версії ПЗ:

> docker --version 
Docker version 1.9.1, build a34a1d5
> docker-compose --version
docker-compose version 1.5.2, build 7240ff3
# psql --version
psql (PostgreSQL) 9.5.0

І дякую за статтю! Давно чекав чогось подібного на цьому ресурсі :-)

Другими словами, лишь для того чтобы иметь возможность запустить Docker.
докер чудово можна запустити без оверхеда ресурсів на вагрант. Одна з самих крутих фіч докера якраз і в цьому, не обовязково тягнути цілу віртуалку з драйверами на електрочайник і зі всім оверхедом.
Да і сам варгант в скорому часі може стати депрікейтед, хашікорп просуває наступника — Otto .
Але в любому випадку ++ за старання, новачкам саме то

Ну в этом случае здесь Vagrant используется автором с целью развернуть сетап на винде, без курения манов и танцев с бубнами. Вполне неплохой вариант (на самом деле очень хороший, если нужно быстро разворачивать унифицированный девелоперский энв в одну команду).
У докера сейчас есть инсталлятор для винды в «пару кликов» — но все равно поднимается виртуалка где демон докера будет запущен.

Ну и еще к слову, Vagrant можно же использовать и без виртуалбокса, просто для конфигурации/сетапа докер контейнера. Зачем его оверхедом называть =)

Потому, что у докера и так есть все для:

просто для конфигурации/сетапа докер контейнера.

Возможно Вы подскажете более конкретно инструменты/best practice?
имхо, dockerfile и слои недостаточно для определения «есть все»
ну и +/- удобный DSL для всяких пробросов портов, настройки общих директорий, etc... автоматический запуск шефа/ансибла/паппета на развернутом контейнере для «доведения» до рабочего вида — весьма удобные/необходимые опции.

+/- удобный
или же приславутое
есть все
? Причем тут докер и пуппеты и иже с ними ? Смешались в кучу кони, люди ))

wat? :)
чого вам нехватає в докері щоб його в вагранті ранити? в чому проблема?
і да, що за ізврат з папетом в докері? або прекращайте з цими речовинами або діліться ;)

Я підозрюю, що в цьому контексті паппет(chef,ansible) використовується для розгортання рішення десь в хмарці, як альтернатива шелл скріптам.

Можна звісно анзібл і в контейнер втулити, але думаю, що він буде важити значно більше.

зависит от задачи, допустим если мне нужно предоставлять изолированный/унифицированный дев енв для пользователей linux/win/mac, то достаточно удобно просто иметь один набор скриптов сетапа(chef/puppet/shell) и запускать их на одном из базовых образов(виртуалбокс(win/mac), докер(linux)). ну а как обвязку для этого всего Вагрант.

т.е: Vagrantfile, который в зависимости от энва где запущен разворачивает либо Виртуалбокс, либо Докер (со всеми необходимыми шареными папками/портами), потом внутри виртуалки просто запускает пачку скриптов конфигурации.

итого плюсы для ОПСа — этот кусок инфраструктуры красиво лежит в системе контроля версий, обновляется только один набор скриптов конфигурации + Vagrantfile

Плюсы для Девелопера — сетап дев-енва сводится к выкачиванию вагрант-файла и запуска `vagrant up`. Справится даже trainee.

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

про депрекейтед вагрант — вы не правильно поняли цели отто
а про «докер без вагранта» ...
на маке, например, докер только под виртуалкой запускается
как пример
мне проще запустит паралелс, а в ней крутить докер (ибо паралеллс быстрей и удобней)
а параллелсовой машинкой мне проще управлять вагрантом
можно конечно управлять докером — вагрантом, но я не уверен что докер может юзать параллель вместо тупого виртуалбокс
можно докером управлять и напрямую
можно и без докера обойтись, поставить фрибсд перекомпилить мир и юзать джайлы ... тот же докер — тока все руцями

Цікаво- наскільки «продуктивне» виходить розгортання якогось реального рішення з докер контейнера, який запущений у вагранті, який виконується з VirtualBox. Воно реально пробує працювати ?

Бо Вагрант сам по собі не є швидким. Логічніше виглядало би встановити докер локально, без вагранта.

Единственная причина, по которой мы пользуемся Vagrant — ради возможности создавать изолированную среду разработки, основанную на виртуальной машине со всеми необходимыми сервисами, которая должна будет воспроизвести реальную рабочую среду. Другими словами, лишь для того чтобы иметь возможность запустить Docke

На MacBook Pro 2.2GHz Intel Core i7, 16GB — все літає(правда жре заряд батареї).
У нас в команді всі так і юзають докер без Вагранта крім мене, але мені вагрант подобається як рішення на рівні якого я ізолюю середовище розробки на особистому ноуті і на якому налаштоване ізольоване середовище деплоймента.

Мажор чо, макбук всі діла, зробіть цей солюшн віндоводам, і з варіантом коли вінда шарить файли вагранту (що як правило не дуже швидко) і ще в середині вагранта тоже синхронізування файлів. Є всі шанси що буде страшно тупити.

Тут є вже перші спроби реалізувати NFS github.com/winnfsd/vagrant-winnfsd

А SMB так само тупить як синхронізація VBox по-замовчуванню ?

в свій час пробував різні велосипеди тіпа «nfs+vagrant+windows», правда до терпимої швидкодії так і не вийшло, в підсумку фронти пересіли на лінукса ;)

если вы сидите под линуксом, то для разработки всеравно нужна изоляция в виртуалку
ибо сидите вы обязательно на крайней бубунте, а на сервере наверняка стоит дебиан (или в худшем случае, лтс-ная бубунта)
осюда несовместимости и версий софта и окружения итп итд итчк

чому це лтс-на убунта — гірший випадок?

ну, юзать лтс убунту — хуже чем юзать дебиан ...
лучше юзать дебиан на сервере
вы с этим хотите поспорить?

спорить незачем и без толку — это холиварная тема
в контексте веб-разработки
у меня вообще CentOS почти всюду по серверам. Ubuntu только на ноуте и рабочем ПК. веду разработку в докере тоже на образах Ubuntu/Debian (в зависимоти от нужной версии php) и потом все отлично разворачивается на CentOS-6.7/CentOS-7. никаких проблем не возникалос аналогично с проектами node.js. если у Вас другая специфика и у Вас проблемы с Ubuntu или другими дистрибутивами, то, возможно, вы просто не научились их готовить
оговорюсь: возможно, у меня не было таких задач, которых я не приготовил на разных ветках RHEL-Debian, но в конечном итоге все упирается в софт, который будет использоваться разрабатываемым продуктом

юзать лтс убунту — хуже чем юзать дебиан ...
это ж чем же? я не сторонник убунты на сервере, но аргументируейте свое мнение

не используйте виндов для разработки для линукс
или выстрелите себе в ногу наконец

А для разработки для Джавы можно? Спасибо.

в шабат — низя
а так, только не жирную

Вагрант это какбы обертка вокруг Виртуал Бокса (или чего другого если хочется). Так что если тормозит, то не он а виртуальная машина. Без которой докер на мако/вындовзе не запустить. По ходу сильно вроде не тормозит, но нужно ещё параметрами повозится если что требовательное. Как VM так и контейнеров при запуске.

Корректное замечание, неправильно выразился.

Сильно тормозят шаред-фолдеры, а виртуалка имеет очень маленький оверхед.

Шаред фолдеры это фича виртуал бокса, нет?

Все верно, но с samba/nfs дела не намного лучше.

При чем тут самба если мы про торможение Вагранта говорили?

А причем тут vagrant к торможению? vagrant это ruby cкрипт ))

Если речь идет о дев окружении, то чаще всего причина тормозов в том, что для того что бы зашарить папку с исходниками внутрь машины, нужны дикие костыли, типа sharedfolder или samba/nfs. От чего потом внутри все тормозит. Не цпу/озу же тормозит :D. А тупит io. Может конечно диск притормаживать, но это только если вы забыли включить кеширование в память. Если вам шарить ничего не надо, то включайте кеширование диска, и на глаз вы разнице в производительности не заметите, а в некоторых случая vm еще и быстрее хоста будет.

Ну так может если некромантить, то все-таки почитаем что? Цитирую себя:

Вагрант это какбы обертка вокруг Виртуал Бокса (или чего другого если хочется). Так что если тормозит, то не он а виртуальная машина
. Теперь перечитай свой ответ и подумай к чему он.

К чему тогда вопрос про самбу, если еще в самом начале я сказал про тормоза шаредфолдеров?

Дякую, хороша витримка інформації.

UP. Але в тому ж AWS EB — Docker версії 1.7.1. Тому описані зручності з налаштуванням docker volume тільки для локального розгортання.

Станом на вчора Docker 1.9 на AWS вже є доступним в окремих регіонах

ECS now supports Docker 1.9, deployment options, CloudWatch metrics, Singapore and Frankfurt regions.

Не знаю, може ще не все оновили. Але в мене в Frankfurt для single Docker тільки версії 1.7 та 1.6, а для multidocker — 1.7, без можливості вибрати .

+ ви завжди можете взяти ami з CoreOS і отримати потрібну вам версію докера незалежно від підтримки (ІМХО)

Я хочу розгортати з EB, тобто конфігурити останній, а не саму внутрішню інфраструктуру ECS.

так в EB можно указать свой образ. Просто берете последнюю версию ami linux, ставите нужную версию докера, пакуете в ami и полученный айди прописываете в конфигурацию EB. Можно автоматизировать создание образа с помощью packer.
Когда EB подхватывает ваш образ, он сам ставит нужную ему версию nginx и собственно EB тулкит.

Подписаться на комментарии