Docker-compose настройка для сайта NGINX + MYSQL + PHP-FPM
Основа статьи взята тут.
У нас есть сайт, который мы хотим быстро перенести на другой сервер. Для этого мы будем использовать docker + docker-compose
Содержание
Что будет уметь наша сборка?
Простейшая среда разработки на php включает в себя следующие компоненты:
- Собственно сам PHP, последний стабильный релиз 7.4;
- Composer
- Mysql, последняя стабильная версия 8;
- Nginx
Также наша конфигурация будет поддерживать сколько угодно хостов nginx (см. проектов). Добавление новых компонентов в стек обычно не составляет труда, если это не заморская диковина конечно, но об этом позже.
Файловая структура
Переходим к организации папок и файлов нашей сборки. Создадим на диске какую-нибудь директорию, которая будет корневой для нашей сборки и в ней по порядку создаем следующие директории:
- www - в этой папке будут лежать файлы наших проектов, по директории на каждый проект;
- mysql и mysql-files - в этой папке будут храниться файлы наших баз данных;
- logs - здесь будет собриать логи из разных образов. В ней расположены 2 папки mysql и nginx;
- hosts - здесь будут храниться файлы конфигурации nginx для наших проектов;
- images - папка с нашими образами - компонентами нашей системы.
Еще не помешает создать дефолтный проект, чтобы проверить работоспособность нашей сборки когда все запустится. В директории www создадим директорию тестового проекта - hello.dev с одим единственным файлом index.php. Содердимое файла index.php классическое:
<?php phpinfo();
Также в корне будет лежать наш docker-compose.yml - сердце любой docker-конфигурации :)
Собираем образ PHP
Стандартный официальный образ PHP не включает в себя никаких модулей, поэтому чтобы включить их нужно собрать свой образ на основе официального. Звучит немного страшновато, но на деле все просто. Создаем директорию для нашего образа images/php и в ней создаем файл Dockerfile следующего содержания:
# Для начала указываем исходный образ, он будет использован как основа FROM php:7.4-fpm # Необязательная строка с указанием автора образа MAINTAINER PHPtoday.ru <info@phptoday.ru> # RUN выполняет идущую за ней команду в контексте нашего образа. # В данном случае мы установим некоторые зависимости и модули PHP. # Для установки модулей используем команду docker-php-ext-install. # На каждый RUN создается новый слой в образе, поэтому рекомендуется объединять команды. RUN apt-get update && apt-get install -y \ curl \ wget \ git \ libfreetype6-dev \ libjpeg62-turbo-dev \ libpng-dev \ libonig-dev \ libzip-dev \ libmcrypt-dev \ && pecl install mcrypt-1.0.3 \ && docker-php-ext-enable mcrypt \ && docker-php-ext-install -j$(nproc) iconv mbstring mysqli pdo_mysql zip \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j$(nproc) gd # Куда же без composer'а. RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Добавим свой php.ini, можем в нем определять свои значения конфига ADD php.ini /usr/local/etc/php/conf.d/40-custom.ini # Указываем рабочую директорию для PHP WORKDIR /var/www # Запускаем контейнер # Из документации: The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, # or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well. CMD ["php-fpm"]
Также в этой папке создадим пока пустой php.ini, чтобы не было ошибки при сборке образа. Можете добавить в него нужные вам настройки.
Вот мой файл php.ini
;было error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT ;было display_errors = of display_errors = on ;Разрешить сокращенные теги ;было short_open_tag = of short_open_tag = on ;было post_max_size = 8M post_max_size = 200M ;было upload_max_filesize = 2M upload_max_filesize = 200M ;Если не указать тайм зону, то будут сыпаться ошибки. ;было ;date.timezone = date.timezone = Europe/Moscow ;заремарить следующую строку, иначе письма будут терять поле FROM mail.add_x_header = of
Docker Compose
Docker compose сильно упрощает жизнь если у вас больше одного контейнера. С помощью одного (иногда нескольких) конфигурационных файлов формата yml вы описываете какие у вас будут запускаться контейнеры, их настройки, то как они будут между собой взаимодействовать и так далее. Начиная со второй версии docker compose поддерживает наследование и можно с его помощью описывать разные конфигурации для разных окружений. Мы сейчас не будем заострять на этом внимание, у нас одно окружение и один файл. Создадим в корне docker-compose.yml.
# Версия docker-compose version: '3' # Список наших сервисов (контейнеров) services: nginx: # используем последний стабильный образ nginx image: nginx:latest # маршрутизируем порты ports: - "80:80" - "443:443" # монтируем директории, слева директории на основной машине, справа - куда они монтируются в контейнере volumes: - ./hosts:/etc/nginx/conf.d - ./www:/var/www - ./logs/nginx:/var/log/nginx # nginx должен общаться с php контейнером links: - php php: # у нас свой образ для PHP, указываем путь к нему и говорим что его надо собрать build: ./images/php # этот образ будет общаться с mysql links: - mysql # монтируем директорию с проектами volumes: - ./www:/var/www mysql: image: mysql ports: - "3306:3306" volumes: - /etc/mysql/my.cnf:/etc/mysql/my.cnf - ./logs/mysql:/var/log/mysql - ./mysql:/var/lib/mysql - ./mysql-files:/var/lib/mysql-files - ./docker/data:/docker-entrypoint-initdb.d # задаем пароль для root пользователя # заливку дампа сайта и создание пользователя для доступа к базе снаружи будем делать позже environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: www_lpu_new
Конфигурация nginx для проектов
Раньше мы уже создали тестовый проект hello.dev, давайте добавим для него конфиг nginx. В папке hosts создадим файл с названием hello-dev.conf:
server { index index.php; server_name hello.dev; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/hello.dev; 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-сокета.