August 10, 2014

Локальный вебсервер без боли с Docker

Всем доброго времени суток!

Довольно давно я сюда уже не писал, но сегодня решил сделать исключение и написать пост с решением одной проблемы - лично мне уже давно лень тестировать различные CMS на PHP хотя бы потому что приходится делать однотипные действия - добавить хост в Apache, добавить пользователя и базу в MySQL. А потом еще не забыть все это удалить чтобы не замусоривалось.

Сразу оговорюсь что для локальной разработки я в основном использую Vagrant и Docker т.к. не хочу захламлять основную систему установленным LAMP-стеком. Обычно после пары тройки однотипных добавлений новых хостов получалось что виртуальные машины и контейнеры замусоривались никому не нужными БД и конфигами для сайтов которые уже неактуальны. Да и в hosts нет уже желания видеть бесчисленную череду всяких blog.dev,test.dev,site.dev и т.д.

Ну а сегодня я решил сказать «Хватит!».

Выбор решения

Реализовать решил все на Docker т.к. он обладает рядом неоспоримых плюсов:

  1. Это не виртуальная машина -> контейнер жрет меньше ресурсов и стартует мнгновенно
  2. Если не закоммитить изменения вручную то при остановке контейнера все ваши изменения в контейнере никуда не запишутся.

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

Статья рассчитана в основном на линуксоидов т.к. для той же Windows придется сперва поднять виртуальную машину с Linux и уже только на ней Docker. Думаю что в таком случае проще поставить какой-нибудь OpenServer и в ус не дуть :P Для Mac OS X кстати говоря вроде запилили нативный инсталлятор докера.

Тут должна была быть картинка по теме, но таковых нет. Поэтому чтобы хоть как то разбавить скучный текст держите сиськи xD

Ну да ладно, что-то я отвлекся.

Итак, вот краткий рецепт:

  1. Ставим Docker (желательно отсюда из раздела Installation т.к. в репах дистрибутивов обычно старые версии докера)
  2. Скачиваем образ моего контейнера с hub.docker.io: sudo docker pull rhamdeew/lamp
  3. Создаем директорию для проекта: mkdir ~/dockertest
  4. Запускаем контейнер: sudo docker run -v ~/dockertest/:/var/www/srv/ -p 80:80 -t -i rhamdeew/lamp /bin/bash
  5. В контейнере: cp -R /var/www/example /var/www/srv
  6. В контейнере: cd /var/www/srv
  7. В контейнере: ./start.sh
  8. В браузере открываем: http://localhost/1.php
  9. Видим вывод phpinfo =)

Теперь рассказываю что же мы такое сделали

Итак, первым делом мы стянули образ с преднастроенным контейнером, там уже установлены Apache2, PHP и MySQL, а в директории /var/www/example лежит шаблон для добавления проектов.

Далее мы стартуем контейнер.

Если внимательно посмотреть на аргументы запуска контейнера то можно увидеть что для контейнера мы прокинули нашу локальную директорию ~/dockertest в /var/www/srv у контейнера и также прокинули наружу 80 порт.

После старта контейнера (обычно это моментально!) мы получаем доступ к рутовой консоли внутри контейнера. Тут вспоминаем про то что я заботливо положил шаблон для нового проекта в /var/www/example и копируем его в /var/www/srv помня что на хостовой машине это папка ~/dockertest/. После мы переходим в /var/www/srv и запускаем скрипт start.sh.

Сам скрипт ничего магического не делает, просто стартует MySQL с Apache2 и подгружает базу данных из дампа лежащего в db/db.sql с реквизитами указанными в db/db.txt. Там же кстати лежит скрипт stop.sh который дампит базу обратно в db.sql (ведь в процессе работы мы могли что-то писать в базу). Его нужно запускать после того как вы поработали с контейнером и решили его остановить.

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

Реальный пример

Для примера покажу как теперь можно заценить новую версию Wordpress:

  1. Копируем наш шаблон проекта: cp -R ~/dockertest ~/wordpress
  2. Скачиваем архив с wordpress и распаковываем его в ~/wordpress/www
  3. Опционально правим ~/wordpress/db/db.txt где указываем желаемые реквизиты: название БД, имя пользователя и пароль
  4. Стартуем контейнер: sudo docker run -v ~/wordpress/:/var/www/srv/ -p 80:80 -t -i rhamdeew/lamp /bin/bash
  5. В контейнере: cd /var/www/srv/
  6. В контейнере: ./start.sh
  7. В браузере открывем http://localhost/ и приступаем к установке Wordpress, если в п.2 ничего не меняли то во время установки указываем в качестве реквизитов БД везде test

Различные улучшения и вариации

Конечно данное решение неидеальное и обладает некоторым количеством минусов. К примеру после долгой работы над сайтом можно случайно заглушить контейнер и потерять все изменения в БД. Тут в качестве решения можно выгружать БД например по крону. Думаю что можно скрипт stop.sh как то повесить на запуск при остановке контейнера, но пока до этого не дошел. Кстати start.sh также можно воткнуть куда-нибудь в init-скрипты. Можно пойти дальше и сделать 2-3 контейнера с разными версиями ПО, но схожими настройками - для масштабных тестов вообще ок. Тут еще должно быть 100500 примеров использования, но если вы вольетесь в данную тему то вероятно придумаете варианты и получше моих =)

UPD 2019: Сделал сборку с docker-compose поддерживающую кучу версий php и дополнительными утилитами - https://github.com/rhamdeew/docker-compose-php

Другие проекты:

telegram-catalog.top

rhamdeew © 2020