Всю свою текущую разработку я веду, используя docker контейнеры, и если под Linux такой подход не вызывает никаких проблем, то под OS X некоторые моменты могут отнять невероятное количество сил и времени.
Об одном из таких моментов я и хочу рассказать.
В моем случае разработка с иcпользованием docker выглядит так: на контейнере поднят весь необходимый мне софт. Папки с рабочим проектом смаплены с хост системы в контейнер. В контейнере для автобилда настроен либо grunt с grunt-contrib-watch, либо watchify, либо порой просто висит скриптик, использующий inotify-tools.
В случае веб-разработки цикл простой: я правлю на маке файлы проекта, watch утилитки стартуют билд, livereload обновляет web страничку. Но при таком подходе сразу возникает проблема — файловая система vboxsf входящая в Virtualbox Guest Additions невероятно медленная, отсюда:
Это — неприемлемо.
Быстрое гугление показало, что nfs работает в разы быстрее, чем vboxfs. Настроить nfs сервер под OSX быстро и легко.
Дальше надо передать в docker ip адрес OSX хоста, чтобы можно было подцепить файловую систему:
В контейнере надо накатить nfs клиента и замаунтить нужные папки:
И действительно, две проблемы уходят:
Но появляется новая проблема — inotify события файловой системы nfs, на которых сидят все watch утилитки, проходят, но с задержками по 10-20 секунд.
Это — неприемлемо.
Поэтому было принято решение начать ловить inotify события на host машине и передавать информацию в docker контейнер.
Для решения проблемы я использовал следующие утилитки:
Сторона докера
Вешаем http веб сервер на 3080 порт:
Это самый настоящий веб сервер на bash висящий на 3080 порту, на каждый запрос он выполняет команду date и touch файла watchhelper.tmp, который надо положить вне исходников вашего проекта, который надо добавить в watch. Ниже я поясню, почему вне исходников проекта.
Проверить, что работает, можно так:
И, ура — в браузере видим время, а в контейнере — мгновенное срабатывание watch утилиток.
Сторона OSX
Устанавливаем fswatch:
Запускаем:
Теперь при изменении любого файла в папке /Users/user/my_web_project/src будет вызван поднятый в контейнере веб сервер, который «потрогает» файл, что в свою очередь вызовет билд.
Файл watchhelper.tmp надо расположить вне исходников проекта по причине, что nfs все-таки пропускает inotify события и лежащий в исходниках файл вызовет вечный цикл curl touch touch событий.
Различные вопросы настройки докер контейнеров под макось я нерегулярно добавляю в проект на гитхабе istarkov/docker.
Если тема вызовет отклик — напишу еще несколько заслуживающих внимания вещей при использовании docker контейнеров при разработке на OS X.
PS:
Мне сообщили о небольшой проблеме с этим подходом.
Если редактор sublime text 3 и длина файла после внесения изменений осталась прежней, то изменения не попадают в nfs клиента, т.е. в docker.
Вылечить можно так — в настройках sublime, в файле Preferences.sublime-settings сменить крыжик {«atomic_save»: true} на {«atomic_save»: false} и все будет работать как надо.
PPS:
В комментариях descentspb дал более простое решение этой проблемы, рекомендую использовать его подход.
Об одном из таких моментов я и хочу рассказать.
В моем случае разработка с иcпользованием docker выглядит так: на контейнере поднят весь необходимый мне софт. Папки с рабочим проектом смаплены с хост системы в контейнер. В контейнере для автобилда настроен либо grunt с grunt-contrib-watch, либо watchify, либо порой просто висит скриптик, использующий inotify-tools.
В случае веб-разработки цикл простой: я правлю на маке файлы проекта, watch утилитки стартуют билд, livereload обновляет web страничку. Но при таком подходе сразу возникает проблема — файловая система vboxsf входящая в Virtualbox Guest Additions невероятно медленная, отсюда:
- watch утилитки начинают грузить систему процентов на 200;
- даже небольшая сборка — например простая конкатенация файлов начинает занимать десятки секунд.
Это — неприемлемо.
Быстрое гугление показало, что nfs работает в разы быстрее, чем vboxfs. Настроить nfs сервер под OSX быстро и легко.
#включить nfs сервер
sudo nfsd enable
#отредактировать файл с папками для шаринга
sudo vi /etc/exports
# добавить папки которые надо сделать доступными например /Users/user/my_web_project -mapall=ice
#проверить что нет ошибок
sudo nfsd checkexports
#проверить что папки подцпились
showmount -e
Дальше надо передать в docker ip адрес OSX хоста, чтобы можно было подцепить файловую систему:
#получить ip хоста висящего на интерфейсе virtual box
HOST_IP=`ifconfig vboxnet0 | tail -1 | awk '{print $2}'`
#передать в контейнер
docker run --name smap -p 3080:3080 -e HOST_IP="$HOST_IP" -d -t sentimeta/node_scikit_image
В контейнере надо накатить nfs клиента и замаунтить нужные папки:
#накатить клиента
sudo apt-get update
sudo apt-get install nfs-common
#замаунтить nfs osx папку
sudo mount -o nolock "$HOST_IP":/Users/user/my_web_project ~/my_web_project
И действительно, две проблемы уходят:
- загрузка процессора около ноля;
- билд теперь идет очень быстро.
Но появляется новая проблема — inotify события файловой системы nfs, на которых сидят все watch утилитки, проходят, но с задержками по 10-20 секунд.
Это — неприемлемо.
Поэтому было принято решение начать ловить inotify события на host машине и передавать информацию в docker контейнер.
Для решения проблемы я использовал следующие утилитки:
Сторона докера
Вешаем http веб сервер на 3080 порт:
watch -n0 'printf "HTTP/1.1 200 OK\n\n$(date && touch /home/user/my_web_project/watchhelper.tmp)\n" | nc -l -p 3080 >/dev/null && date'
Это самый настоящий веб сервер на bash висящий на 3080 порту, на каждый запрос он выполняет команду date и touch файла watchhelper.tmp, который надо положить вне исходников вашего проекта, который надо добавить в watch. Ниже я поясню, почему вне исходников проекта.
- touch команда «трогая» файл вызывает inotify событие приводяещее к сборке;
- date команда удобна для тестирования, ее вывод и есть ответ этого сервера.
Проверить, что работает, можно так:
- На OSX получаем адрес boot2docker виртуальной машины:
boot2docker ip 2>&1 | sed -n 2,2p | awk -F' ' '{print $9}'
И, ура — в браузере видим время, а в контейнере — мгновенное срабатывание watch утилиток.
Сторона OSX
Устанавливаем fswatch:
brew install fswatch
Запускаем:
fswatch-run /Users/user/my_web_project/src "curl http://`boot2docker ip 2>&1 | sed -n 2,2p | awk -F' ' '{print $9}'`:3080"
Теперь при изменении любого файла в папке /Users/user/my_web_project/src будет вызван поднятый в контейнере веб сервер, который «потрогает» файл, что в свою очередь вызовет билд.
Файл watchhelper.tmp надо расположить вне исходников проекта по причине, что nfs все-таки пропускает inotify события и лежащий в исходниках файл вызовет вечный цикл curl touch touch событий.
Различные вопросы настройки докер контейнеров под макось я нерегулярно добавляю в проект на гитхабе istarkov/docker.
Если тема вызовет отклик — напишу еще несколько заслуживающих внимания вещей при использовании docker контейнеров при разработке на OS X.
PS:
Мне сообщили о небольшой проблеме с этим подходом.
Если редактор sublime text 3 и длина файла после внесения изменений осталась прежней, то изменения не попадают в nfs клиента, т.е. в docker.
Вылечить можно так — в настройках sublime, в файле Preferences.sublime-settings сменить крыжик {«atomic_save»: true} на {«atomic_save»: false} и все будет работать как надо.
PPS:
В комментариях descentspb дал более простое решение этой проблемы, рекомендую использовать его подход.