Установка LEMP с помощью Docker'а — Пермяк на Неве
На главную

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

Установка 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 и перезапустить контейнеры. Удачи!

Info

Т.к. сейчас хром да и все остальные по умолчанию пытаются стучать в https рекомендую для локальной разработки создавать домены вида domain-name.test. Хром успокаивается и пускает вас поработать.

Github

Используемые образы

Внимание

Хост для доступа к MySQL — mysql. Не localhost, а именно mysql.

Комментарии