Установка LEMP с помощью Docker'а

Содержание
Не так давно из всех углов доносились крики о докоре шморек. А я тогда использовал на локалхосте Vagrant и не понимал нафига мне переходить на Docker. Если честно я до сих пор этого не понимаю, но очередной сбой в вагранте (я сам виноват, инфа 146%) сподвиг меня хоть чуть чуть разобраться с докером. Вообще, если быть честным это не первый мой опыт, у меня одно время локально крутился Ghost на нем, а дальше дело не пошло. Предлагаемое решение больше для локалхоста, но принципы понятны и его можно будет адаптировать для production-ready решение.
Что такое докер
Docker — программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы. Позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, который может быть перенесён на любую Linux-систему с поддержкой cgroups в ядре, а также предоставляет среду по управлению контейнерами. Изначально использовал возможности LXC, с 2015 года применял собственную библиотеку, абстрагирующую виртуализационные возможности ядра Linux — libcontainer. С появлением Open Container Initiative начался переход от монолитной к модульной архитектуре.
Углубляться в то, что же это зазверь и как он работает я не буду, это тема для отдельного разговора да и есть отличный хелп у них на сайте.
Что будет в сборке
Самая простая и примитивная среда разработки:
- PHP 8.3 + Composer
- MariaDB
- Nginx с мультихостами
- PhpMyAdmin
Сборка подходит для запуска Laravel, WordPress и Drupal.
Установка
На этом пункте я тоже заострять внимание не буду ибо все и так просто, но вот инструкции:
docker compose входит в состав Docker начиная с версии 20.10, отдельно устанавливать его не нужно.
Структура проекта
Создадим какую нибудь папку, где будет лежать наш проект. В ней нам нужно будет создать вот такие папки:
- www — в этой папке будут лежать файлы наших проектов, по директории на каждый проект
- mysql — в этой папке будут храниться файлы наших баз данных
- logs — здесь будет собираться логи из разных образов
- hosts — здесь будут храниться файлы конфигурации nginx для наших проектов
- images — папка с нашими образами
Еще не помешает создать папку с нашим дефолтным проектом для проверки нашей сборки. В папке www создадим папку с нашим проектом, например hello.test. В ней создадим файл index.php со следующим содержанием:
<?php phpinfo();
Так же давайте сразу создадим в папке с нашими образами папку php, а в ней файлы php.ini (можем в нем определять свои значения конфига) и Dockerfile (тут будут настройки нашего образа).
Для ленивых вот команда которая сделает все сама:
mkdir www www/hello.test mysql logs hosts images images/php && echo "<?php phpinfo();" > www/hello.test/index.php && touch images/php/php.ini && touch images/php/Dockerfile && touch docker-compose.yml
Собираем наш PHP образ
Официальный образ PHP не включает в себя никаких модулей, для того чтобы их включить, мы соберем собственный образ на основе официального. В файл images/php/Dockerfile пропишем следующее:
FROM php:8.3-fpm
RUN apt-get update && apt-get install -y \
curl \
wget \
git \
libcurl4-openssl-dev \
libexif-dev \
libfreetype6-dev \
libicu-dev \
libjpeg-dev \
libonig-dev \
libpng-dev \
libxml2-dev \
libzip-dev \
&& docker-php-ext-install -j$(nproc) \
bcmath \
curl \
exif \
fileinfo \
iconv \
intl \
mbstring \
mysqli \
opcache \
pdo_mysql \
xml \
zip \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
ADD php.ini /usr/local/etc/php/conf.d/40-custom.ini
WORKDIR /var/www
CMD ["php-fpm"]
Composer устанавливается через официальный образ — это надёжнее и быстрее чем скачивать инсталлятор через curl. В php.ini можно задать свои настройки, например лимиты загрузки файлов и параметры OPcache:
; Загрузка файлов
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
max_input_vars = 3000
; OPcache
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.revalidate_freq = 2
Docker Compose
Docker Compose упрощает жизнь если у вас больше одного контейнера. С помощью одного, а иногда нескольких файлов, мы описываем какие контейнеры запускать, их настройки и связи между контейнерами. В файл docker-compose.yml пропишем следующее:
services:
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./hosts:/etc/nginx/conf.d
- ./www:/var/www
- ./logs:/var/log/nginx
networks:
- app
depends_on:
- php
php:
build: ./images/php
volumes:
- ./www:/var/www
networks:
- app
depends_on:
- mysql
mysql:
image: mariadb:latest
ports:
- "3306:3306"
volumes:
- ./mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
networks:
- app
pma:
image: phpmyadmin:latest
restart: always
ports:
- "8183:80"
environment:
PMA_HOST: mysql
MYSQL_USERNAME: root
MYSQL_ROOT_PASSWORD: secret
networks:
- app
depends_on:
- mysql
networks:
app:
driver: bridge
Вместо устаревшего links теперь используются networks — контейнеры в одной сети видят друг друга по имени сервиса. depends_on задаёт порядок запуска.
Конфигурация nginx для проектов
Мы уже создали тестовый проект hello.test, создадим для него nginx конфиг. В папке hosts создадим файлик hello-test.conf:
server {
index index.php index.html;
server_name hello.test;
error_log /var/log/nginx/error.hello.log;
access_log /var/log/nginx/access.hello.log;
root /var/www/hello.test;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Конфиг nginx для докер контейнеров ничем не отличается от обычного конфига для сайта. Стоит лишь обратить внимание на директиву fastcgi_pass, где мы используем не путь к unix-сокету, а адрес php:9000. Здесь присутствует немного магии docker’а: php — это хост по которому доступен наш php контейнер внутри контейнера nginx, ну а 9000 — порт, по которому можно достучаться до fpm-сокета.
Блок location / с try_files нужен для корректной работы ЧПУ-ссылок в Laravel, WordPress и Drupal — без него красивые URL работать не будут.
Погнали!
Хост для доступа к MySQL — mysql. Не localhost, а именно mysql.
Минимальная конфигурация для нашей локальной разработки готова. Осталось только запустить ее и проверить, работает ли оно. Переходим в корень нашего проекта, где лежит файл docker-compose.yml. Выполняем команду docker compose up -d и ждем. Первый запуск он самый долгий, потому что докеру нужно скачать образы и собрать наш образ php.
В самом конце мы увидим заветные строки:
Container lemp4docker-mysql-1 Started
Container lemp4docker-php-1 Started
Container lemp4docker-nginx-1 Started
Container lemp4docker-pma-1 Started
Они сообщают нам, что все 4 контейнера поднялись и работают. Проверим все ли так. Открываем браузер и переходим по адресу http://hello.test:8080/ и нихрена не открывается. Все потому, что нам надо в файл hosts прописать следующую строку:
127.0.0.1 hello.test
Обновляем страницу и видим phpinfo — значит всё работает.
Для создания дополнительного хоста нам нужно в папке www создать папку проекта, а в папке hosts создать для него конфиг nginx и перезапустить контейнеры. Удачи!
Т.к. сейчас хром да и все остальные по умолчанию пытаются стучать в https рекомендую для локальной разработки создавать домены вида domain-name.test. Хром успокаивается и пускает вас поработать.
Github
Используемые образы
Хост для доступа к MySQL — mysql. Не localhost, а именно mysql.
Комментарии