Docker-compose настройка для сайта NGINX + MYSQL + PHP-FPM

Материал из Wiki МИАЦ ВО
Версия от 11:51, 29 февраля 2020; Misha (обсуждение | вклад) (Файловая структура)
Перейти к навигации Перейти к поиску

Основа статьи взята тут.
У нас есть сайт, который мы хотим быстро перенести на другой сервер. Для этого мы будем использовать docker + docker-compose

Что будет уметь наша сборка?

Простейшая среда разработки на php включает в себя следующие компоненты:

  1. Собственно сам PHP, последний стабильный релиз 7.4;
  2. Composer
  3. Mysql, последняя стабильная версия 8;
  4. Nginx

Также наша конфигурация будет поддерживать сколько угодно хостов nginx (см. проектов). Добавление новых компонентов в стек обычно не составляет труда, если это не заморская диковина конечно, но об этом позже.

Файловая структура

Переходим к организации папок и файлов нашей сборки. Создадим на диске какую-нибудь директорию, которая будет корневой для нашей сборки и в ней по порядку создаем следующие директории:

  1. www - в этой папке будут лежать файлы наших проектов, по директории на каждый проект;
  2. mysql и mysql-files - в этой папке будут храниться файлы наших баз данных;
  3. logs - здесь будет собриать логи из разных образов. В ней расположены 2 папки mysql и nginx;
  4. hosts - здесь будут храниться файлы конфигурации nginx для наших проектов;
  5. 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-сокета.