docker hub apache php
Docker-compose: идеальное рабочее окружение
Здрасте!
В последнее время все чаще задумываюсь об оптимальности рабочего процесса и хотелось бы поделиться своими изысканиями в данном вопросе.
В данном посте поговорим про docker-compose, который по моему мнению является панацеей в вопросе организации и оптимизации рабочего процесса разработчика.
Описывать все я буду почти на пальцах, поэтому если вы до этого ни разу не слышали про docker (что странно), ни разу с ним не работали и хотите в нем разобраться, то прошу под кат.
Предисловие
В статье я умышленно упрощаю некоторые моменты, не углубляюсь в детали и поверхностно касаюсь многих вопросов.
Делаю я это с полным понимаем своих действий, и считаю, что не нужно лазить под капот, если все работает.
Те, кто считают иначе — это ваше полное право, но только не нужно навязывать свою точку зрения.
Спасибо!
Docker
Технология, позволяющая легко (во всех смыслах) разворачивать необходимое рабочее окружение.
Подробнее можно узнать из ссылок в конце статьи, но лучше сейчас на это не переключаться, чтобы не забивать себе мозг.
Docker-compose
Пакетный менеджер (по аналогии с composer и npm, только у docker — контейнеры), позволяющий описывать необходимую структуру в одном файле (конфиге).
Подробнее также можно узнать из ссылок в конце статьи.
Docker-hub
Репозиторий контейнеров (по аналогии с packagist и npm).
Важное замечание: внимательно читайте описание к образу, 70-80% тупых вопросов там описано, не тратьте время на гугление.
Установка
Переписывать документацию docker я не стану, поэтому просто кину ссылки:
Установка обычного программного обеспечения (ПО), проблем возникнут не должно.
Если все же возникнут, то дальше можете не читать, вероятно вы случайно наткнулись на эту статью и разработку в целом.
Если вы устанавливали docker под Windows, то работать нужно через специальную консоль Docker Quickstart Terminal. После установки, на рабочем столе должен появиться соответствующий ярлык.
Структура проекта
Для начала определимся со структурой проектов:
CMD / Terminal
Для работы с docker и compose мы будем использовать всего несколько команд:
Описание прочих команд, можно найти на официальном сайте.
Перейдем непосредственно к делу.
apache
Начнем, пожалуй, с самого популярного сервера — Apache.
Создадим директорию проекта:
Конфиг будет выглядеть таким образом:
Что здесь происходит:
Создадим файл src/index.html в рабочей директории с содержимым:
Запускаем наш проект:
Переходим в браузер по адресу ПК и наблюдаем приветствие нашего сервера.
Чтобы уничтожить контейнеры нашего проекта, достаточно в консоле выполнить Ctrl+C.
Если докер работает через VirtualBox, то нужно заходить по IP виртуалки. При любом раскладе, если вы работаете через Docker Quickstart Terminal, то адрес выведется при запуске консоли.
Работа в фоновом режиме
Если вам необходимо запустить docker и далее работать в консоле, то можно запустить проект в фоном режиме:
После запуска, консоль будет доступна для работы.
Чтобы в данной ситуации уничтожить контейнер, необходимо его остановить и удалить, но для начала, нужно узнать его ID:
В моем случае получился такой вывод:
Теперь останавливаем и удаляем наш контейнер:
Либо можно поступить грубо и сразу удалить:
nginx
Конфиг nginx строиться по той же самой схеме, что и apache: образ, порты, рабочая директория. Выглядит файл таким образом:
Создаем файл src/index.html в рабочей директории с содержимым:
Заходим в браузер, и видим приветствие очередного сервера.
php + apache
Если говорить про связку PHP и Apache, то для нее уже есть готовый образ, поэтому про линковку контейнеров будем говорить далее. А сейчас просто конфиг:
Создаем файл src/index.php в рабочей директории с содержимым:
Проверяем его работу в браузере.
php + nginx
В данной связке php будет в формате fpm. Схематично это выглядит таким образом:
Соответственно нам нужно будет переписать конфиг сервера.
Для этого нужно будет слинковать помимо рабочей директории, еще и файл конфигурации сервера:
Если мы не укажем depends_on, то можем словить подобную ошибку:
Создаем файл /nginx/nginx.conf в директории нашего проекта. Сам конфиг выглядит таким образом:
После всех действий, директория нашего проекта выглядит таким образом:
Запускаем, проверяем, радуемся!
php + apache + nginx
Наверное, самая популярная связка для веб-проектов. Схематично это выглядит так:
Для того чтобы все настроить нам нужно будет также слинковать конфиг apache, и таким образом docker-compose будет выглядеть так:
Так как на просторах интернета я не нашел нормальный конфиг (оке, я просто не искал), а под рукой как раз docker, то решено было вытаскивать его из стандартного контейнера.
Уложилось все в 3 команды:
После выполнения данных команд, в текущей директории появится файл httpd.conf, который мы и будем использовать в качестве основы.
По сути, это простое копирование из запущенного контейнера.
Создаем файл /httpd/httpd.conf в рабочей директории, который после правок выглядит так:
Создаем файл /nginx/nginx.conf в рабочей директории со следующим содержимым:
В строке proxy_pass http://apache мы опять указываем не IP адрес, а название контейнера (вспоминаем про магию с hosts).
Для тестинга, нам нужно будет проверить, работает ли PHP и работает ли Apache.
Сформируем такую структуру проекта:
Содержимое .htaccess:
Содержимое index.php:
Содержимое index.html:
Если все настроено корректно, то картина должна быть следующей:
mariadb + phpmyadmin
Поговорим про базы данных.
Конфиг для подключения выглядит следующим образом:
Для mariadb и phpmyadmin мы указали директиву environment, которая содержит специфические для конкретного контейнера переменные (подробности можно посмотреть в репозиториях самих контейнеров).
В данном случае, это пароль для пользователя root.
Для phpmyadmin мы вручную указали директиву links:
Сделать это необходимо для того, чтобы phpmyadmin знал с какой базой соединятся.
Если бы контейнер mariadb назывался db, то указывать эту директорию было бы не нужно.
Для mariadb мы слинковали директорию с данными:
Сделано это для того, чтобы данные хранились в директории нашего проекта, а не внутри контейнера.
Если вы работаете не на linux машине, то у вас возникнут проблемы с размещением данных базы на локальной машине.
Эти непреодолимое обстоятельство, к сожалению, на данный момент не преодолено.
У кого есть решение просьба поделиться.
Однако по умолчанию (даже после уничтожения контейнера), данные базы сохраняются и вы можете пересоздавать контейнер сколько угодно раз — данные сохранятся в недрах локальной машины.
php + apache + nginx + mariadb + phpmyadmin
Ну, а теперь совмещаем наши конфиги, и получаем неплохое веб-окружение:
Для php мы добавили директиву build (подробнее), в которой указали директорию php, где хранится Dockerfile со следующим содержанием:
В данном файле мы обновляем репозитории и устанавливаем php модули (подробнее про docker-php-ext-install).
Также мы слинковали конфиг php, чтобы можно было его настроить нужным нам образом.
Содержимое php.ini можно взять, например, здесь.
Запускаем, проверяем, радуемся!
Если все сделано правильно, то index.php отработает без ошибок, а в директории project/mysql появятся служебные файлы базы.
Docker production
По данному вопросу к сожалению я ничего сказать не могу, зато может сказать официальная документация.
Если у вас есть опыт использования docker на боевых проектах, то просьба поделиться своим опытом в комментариях: стоит ли, какие трудности и подводные камни у вас возникли и др. полезную информацию для молодых и неопытных.
Заключение
Вот собственно и все, чем я хотел поделиться.
Как видите необязательно знать принцип работы docker, чтобы успешно с ним работать.
Да, конечно, для тонкой настройки или сложных задач, необходимо уже углубляться в дебри docker, но в средне-статистическом случае — это не нужно.
Если у вас есть что добавить, или вы заметили какой-то косяк, или вы с чем-то не согласны, то прошу в комментарии, обсудим 😉
Полезные ссылки (a.k.a список используемой литературы)
Если честно, я не понимаю откуда столько негатива.
Судя по комментариям, основные претензии к формулировкам и терминологии, и это с учетом того, что в предисловии я написал что умышленно упрощаю многие моменты.
Цель статьи — показать, как просто работать с docker-compose, как вместо того, чтобы разворачивать 100500 окружений и ПО для каждого своего проекта, можно использовать docker-compose и быть довольным.
Тут нет речи про prodUction (одного абзаца хватит), про deploy, про миграцию между dev и prod средой.
Нет, статья не об этом.
Большое спасибо krocos Caravus Vershnik Fesor за дельные комментарии.
Среда разработки PHP на базе Docker
Решение, которое позволит создать на локальном компьютере универсальную среду разработки на PHP за 30 — 40 минут.
Почему Docker?
Docker не является VM-системой, он не моделирует аппаратное обеспечение компьютера. Используя Docker вы получите минимальное потребление ресурсов. Docker-контейнеры взаимодействуют напрямую с ядром вашего компьютера (или ядром хоста), но при этом изолируют программу на уровне процесса.
Высокая скорость развертывания. Вы можете использовать готовые docker-образы, которые устанавливаются и запускаются за секунды.
Приложения, находящееся внутри docker-контейнеров, можно запустить на любом компьютере с установленным Docker, при этом окружение будет одинаковым.
Возможность простой сегрегации пользовательских данных и контейнеров-сервисов. Если вы сломаете или удалите docker-контейнер, то данные не потеряются, так как они не будут принадлежать контейнеру. Контейнер выполняет лишь функцию сервиса, и не хранит данные, которые нельзя потерять между запусками.
Вы можете очень быстро добавлять новые контейнеры, изменять их конфигурацию, запускать различные версии баз данных на одной машине.
Требования
Docker engine 19.x и выше.
Возможности и особенности среды разработки
Несколько версий PHP — 7.3 и 7.1 с набором наиболее востребованных расширений.
Возможность использовать для web-проектов разные версии PHP.
Готовый к работе монитор процессов Supervisor.
Предварительно сконфигурированный веб-сервер Nginx.
Базы данных: MySQL 5.7, MySQL 8, PostgreSQL (latest), MongoDB 4.2, Redis (latest).
Настройка основных параметров окружения через файл .env.
Возможность модификации сервисов через docker-compose.yml.
Последняя версия docker-compose.yml.
Все docker-контейнеры базируются на официальных образах.
Структурированный Dockerfile для создания образов PHP.
Каталоги большинства docker-контейнеров, в которых хранятся пользовательские данные и параметры конфигурации смонтированы на локальную машину.
В целом, среда разработки удовлетворяет требованию — при использовании Docker каждый контейнер должен содержать в себе только один сервис.
Репозиторий проекта
Структура проекта
Рассмотрим структуру проекта.
Примечание
.gitkeep — является заполнением каталога, это фиктивный файл, на который не следует обращать внимание.
.env-example
Пример файла с основными настройками среды разработки.
.gitignore
Каталоги и файлы, в которых хранятся пользовательские данные, код ваших проектов и ssh-ключи внесены в. gitignore.
Этот каталог предназначен для хранения ssh-ключей.
readme.md
docker-compose.yml
Документ в формате YML, в котором определены правила создания и запуска многоконтейнерных приложений Docker. В этом файле описана структура среды разработки и некоторые параметры необходимые для корректной работы web-приложений.
mongo
Каталог базы данных MongoDB.
mongo.conf — Файл конфигурации MongoDB. В этот файл можно добавлять параметры, которые при перезапуске MongoDB будут применены.
db — эта папка предназначена для хранения пользовательских данных MongoDB.
dump — каталог для хранения дампов.
mysql-5.7
Каталог базы данных MySQL 5.7.
config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 5.7 будут применены.
data — эта папка предназначена для хранения пользовательских данных MySQL 5.7.
dump — каталог для хранения дампов.
logs — каталог для хранения логов.
mysql-8
Каталог базы данных MySQL 8.
config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 8 будут применены.
data — эта папка предназначена для хранения пользовательских данных MySQL 8.
dump — каталог для хранения дампов.
logs — каталог для хранения логов.
nginx
Эта папка предназначена для хранения файлов конфигурации Nginx и логов.
default.conf — файл конфигурации, который будет применён ко всем виртуальным хостам.
vhost.conf — здесь хранятся настройки виртуальных хостов web-проектов.
Рассмотрим vhost.conf подробнее:
В файле конфигурации описаны настройки для двух web-проектов — project-1.localhost и project-2.localhost.
Здесь следует обратить внимание на то, как производится перенаправление запросов к нужному docker-контейнеру.
Например, для проекта project-1.localhost указано:
php-7.3 — название docker-контейнера, а 9000 — порт внутренней сети. Контейнеры между собой связаны через внутреннюю сеть, которая определена в файле docker-compose.yml.
php-ini
В этом каталоге находятся файлы конфигурации PHP.
Для каждой версии PHP — свой файл конфигурации.
php-workers
Место для хранения файлов конфигурации Supervisor.
Для каждой версии PHP — могут быть добавлены свои файлы с настройками.
php-workspace
Здесь хранится файл, в котором описаны действия, выполняемые при создании образов docker-контейнеров PHP.
Dockerfile — это текстовый документ, содержащий все команды, которые следует выполнить для сборки образов PHP.
postgres
Каталог для системы управления базами данных PostgreSQL.
data — эта папка предназначена для хранения пользовательских данных PostgreSQL.
dump — каталог для хранения дампов.
projects
Каталог предназначен для хранения web-проектов.
Вы можете создать в это каталоге папки, и поместить в них ваши web-проекты.
Содержимое каталога projects доступно из контейнеров php-7.1 и php-7.3.
Если зайти в контейнер php-7.1 или php-7.3, то в каталоге /var/www будут доступны проекты, которые расположены в projects на локальной машине.
redis
Каталог key-value хранилища Redis.
conf — папка для хранения специфических параметров конфигурации.
data — если настройки конфигурации предполагают сохранения данных на диске, то Redis будет использовать именно этот каталог.
Программы в docker-контейнерах PHP
Полный перечень приложений, которые установлены в контейнерах php-7.xможно посмотреть в php-workspace/Dockerfile.
Здесь перечислим лишь некоторые, наиболее важные:
Начало работы
1. Выполните клонирование данного репозитория в любое место на вашем компьютере.
Перейдите в директорию, в которую вы клонировали репозиторий. Все дальнейшие команды следует выполнять именно в этой директории.
2. Скопируйте файл .env-example в .env
Если это необходимо, то внесите изменения в файл .env. Измените настройки среды разработки в соответствии с вашими требованиями.
3. Выполните клонирование web-проектов в каталог projects.
Для примера, далее мы будем исходить из предположения, что у вас есть 2 проекта:
project-1.ru — будет работать на версии PHP 7.3, а project-2.ru — на PHP 7.1.
4. Отредактируйте настройки виртуальных хостов Nginx.
Файл конфигурации виртуальных хостов находится в каталоге ./nginx/conf.d/.
5. Настройте хосты (доменные имена) web-проектов на локальной машине.
Необходимо добавить названия хостов web-проектов в файл hosts на вашем компьютере.
В файле hosts следует описать связь доменных имён ваших web-проектов в среде разработки на локальном компьютере и IP docker-контейнера Nginx.
На Mac и Linux этот файл расположен в /etc/hosts. На Windows он находится в C:\Windows\System32\drivers\etc\hosts.
Строки, которые вы добавляете в этот файл, будут выглядеть так:
В данном случае, мы исходим из того, что Nginx, запущенный в docker-контейнере, доступен по адресу 127.0.0.1 и web-сервер слушает порт 80.
6. [опционально, если это необходимо] Настройте маршрутизацию внутри контейнеров web-проектов.
Web-проекты должны иметь возможность отправлять http-запросы друг другу и использовать для этого название хостов.
Из одного запущенного docker-контейнера php-7.1 web-приложение № X должно иметь возможность отправить запрос к другому web-приложению № Y, которое работает внутри docker-контейнера php-7.3. При этом адресом запроса может быть название хоста, которое указано в файле /etc/hosts локального компьютера.
Чтобы это стало возможным нужно внутри контейнеров так же внести соответствующие записи в файл /etc/hosts.
Самый простой способ решить данную задачу — добавить секцию extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.
IP_HOST_machine — IP адрес, по которому из docker-контейнера доступен ваш локальный компьютер.
Если вы разворачиваете среду разработки на Mac, то внутри docker-контейнера вам доступен хост docker.for.mac.localhost.
Узнать IP адрес вашего Mac можно при помощи команды, который нужно выполнить на локальной машине:
В результате вы получите, что-то подобное:
После того, как вам станет известен IP-адрес, укажите его в секции extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.
8. Настройте параметры соединения с системами хранения данных.
Хосты и порты сервисов
Для того, чтобы настроить соединения с базами данных из docker-контейнеров php-7.1 и php-7.3 следует использовать следующие названия хостов и порты:
Начало работы с Docker. Часть четвертая
С docker-compose.yml мы переносим все параметры, ранее записываемые в командной строке при запуске контейнера в конфигурационный YAML файл. Сделаем так, чтобы вместо перестроения образа при изменении файлов проекта, мы сможем изменять файлы на основной системе. А контейнер будет видеть эти изменения и сразу реагировать на них. Для этого примонтируем нашу рабочую директорию в контейнер.
Теперь выполним две команды:
Собираем проект заново, поскольку мы отредактировали файлы Dockerfile и docker-compose.yml :
И опять, по адресу http://localhost:8080 поднимется наш сервер. Но теперь мы можем редактировать файл index.php и сразу видеть изменения:
Docker-compose, так же как и Docker, предоставляет возможность для выполнения команд внутри контейнера:
Давайте остановим наши службы (точнее, нашу единственную службу), потом запустим их снова в режиме демона, а потом выполним команду внутри контейнера:
И опять остановим наши службы:
Две службы: Apache+PHP и MySQL
Давайте удалим все из директории www домашнего каталога и создадим более сложный проект. Он будет запускать две службы: Apache и MySQL. Структура каталогов будет такой:
Нам нужно выполнить шаги:
Скачиваем образы Apache и MySQL
Скачаем два образа
Создаем файлы конфигурации
Теперь возьмем из образа php:7.4-apache файл конфигурации Apache2 и файл конфигурации PHP (который работает как модуль Apache):
Из образа mysql:latest возьмем файл конфигурации MySQL /etc/mysql/mysql.cnf :
Создаем файлы Dockerfile
Создаем файлы логов Apache и MySQL
Создаем файлы логов Apache:
Создаем файлы логов MySQL:
Добавляем в файл конфигурации MySQL запись логов:
С файлом логов mysql.log надо быть осторожным — сервер MySQL будет записывать в него все запросы, так что размер этого файла будет расти очень быстро.
Создаем файл docker-compose.yml
Создаем образы и запускаем службы
При выполнении команды docker-compose up :
Открываем браузер и набираем в адресной строке http://localhost :
Логи Apache и MySQL
Мы смонтировали файлы логов внутрь контейнера и теперь можем их смотреть в основной системе:
Docker hub apache php
Docker, docker, docker. Было время, когда это слово звучало в каждой курилке разработчиков. Хайп вокруг докера уже подугас, однако он по-прежнему может быть полезен как для локальной среды, так и как production-ready решение. Но в посте речь пойдет именно о среде для локальной разработки.
Но для тех, кто не в курсе, на всякий случай:
Docker — программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы. Позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, который может быть перенесён на любую Linux-систему с поддержкой cgroups в ядре, а также предоставляет среду по управлению контейнерами. Изначально использовал возможности LXC, с 2015 года применял собственную библиотеку, абстрагирующую виртуализационные возможности ядра Linux — libcontainer. С появлением Open Container Initiative начался переход от монолитной к модульной архитектуре.
Что будет уметь наша сборка?
Простейшая среда разработки на php включает в себя следующие компоненты:
Также наша конфигурация будет поддерживать сколько угодно хостов nginx (см. проектов). Добавление новых компонентов в стек обычно не составляет труда, если это не заморская диковина конечно, но об этом позже.
Установка docker
Заострять внимание на процессе установки docker’а нет никакого смысла, на официальном сайте есть подробные мануалы по установке для всех популярных ОС:
Файловая структура
Переходим к организации папок и файлов нашей сборки. Создадим на диске какую-нибудь директорию, которая будет корневой для нашей сборки и в ней по порядку создаем следующие директории:
Собираем образ PHP
Стандартный официальный образ PHP не включает в себя никаких модулей, поэтому чтобы включить их нужно собрать свой образ на основе официального. Звучит немного страшновато, но на деле все просто. Создаем директорию для нашего образа images/php и в ней создаем файл Dockerfile следующего содержания:
Docker Compose
Конфигурация nginx для проектов
Run the magic!
В конце концов мы увидим заветные строчки:
Важно для windows и mac адрес 127.0.0.1 нужно заменить на адрес виртуальной машины, в которой запускается докер, потому что нативной поддержки пока нет или она очень унылая.
Итак, окрываем браузер и видим:


