Раздел помощи SpaceWeb

Настройка Laravel, Nginx и MySQL с помощью Docker Compose

29 ноя, 2024

Настройка Laravel, Nginx и MySQL с помощью Docker Compose

Контейнеризация – это процесс изоляции приложений и их зависимостей в лёгкие, автономные и переносимые контейнеры. В отличие от виртуальных машин, в контейнеры не входит полноценная операционная система – лишь необходимые файлы и библиотеки. Благодаря этому они менее ресурсоемкие и быстрее запускаемые. Контейнеры идеально подходят для разработки, тестирования и развертывания приложений, поскольку позволяют избежать проблем совместимости и легко масштабировать систему.

Контейнеры также обеспечивают высокий уровень изоляции, позволяя запускать несколько экземпляров приложения или сервисов на одной машине, без риска взаимного влияния. На практике это означает, что разработчик может создать единую среду, в которой его приложение будет работать одинаково на всех этапах разработки и развертывания.

В этой статье мы изучим контейнеризацию, используя Linux, Nginx, MySQL и PHP. В качестве примера работы с зависимостями веб-приложений будем использовать Laravel.

Для этого потребуется: 

  • сервер с установленной ОС Ubuntu;
  • облачное решение (у нас – от Spaceweb) 
  • пользователь с привилегиями sudo. 
  • установленные Docker и Docker Compose.

Как установить Laravel

Laravel – это популярный фреймворк для разработки веб-приложений на PHP. Он предоставляет развитую архитектуру и множество встроенных функций, таких как маршрутизация, миграции баз данных, системы аутентификации и шаблоны, что упрощает создание сложных приложений. Laravel также имеет активное сообщество и обширную документацию, что делает его хорошим выбором для проектов любой сложности.

1. Чтобы начать работу с Laravel, сначала клонируйте его репозиторий из GitHub в домашнюю директорию, где будет размещен проект:

cd ~
git clone https://github.com/laravel/laravel.git

Это позволит получить актуальную версию фреймворка и быстро приступить к работе.

2. Далее, чтобы установить все зависимости проекта, воспользуйтесь Composer – менеджер зависимостей для PHP. 

Важно! Рекомендуется запускать Composer через Docker, а не устанавливать его глобально, так как это дает больше контроля над окружением и упрощает управление зависимостями. 

Для этого перейдём в каталог с проектом и выполним команду:

cd laravel
docker run -v $PWD:/app composer install

Эта команда создаст контейнер Composer, который привязывается к директории laravel. Все зависимости проекта сохранятся в каталоге vendor внутри этой директории, что позволит Laravel полноценно работать с нужными библиотеками и модулями. Такой подход изолирует зависимости и предотвращает конфликты версий, которые могут возникнуть при глобальной установке Composer.

3. После завершения установки необходимо изменить права доступа на каталог, чтобы дальнейшая работа не требовала привилегий суперпользователя:

sudo chown -R username:username ~/laravel

Теперь Laravel готов к работе, и можно переходить к настройке окружения. 

Инструмент Docker Compose: для чего он нужен

Docker Compose – это инструмент, который специально разработан для управления многоконтейнерными приложениями, где задействованы несколько сервисов. В то время как Docker управляет отдельными контейнерами, Docker Compose позволяет удобно описывать и запускать сложные приложения с множеством взаимосвязанных компонентов, таких как базы данных, веб-серверы и кеш.

Чтобы начать работу, создайте docker-compose.yml – централизованный файл конфигурации, – и определите в нем службы веб-сервера, базы данных и приложения:

nano ~/laravel/docker-compose.yml

Пример этого файла:

version: '3.8'
services:
  # PHP Service
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: php:8.1
    container_name: app
    restart: unless-stopped
    tty: true
    environment:
      SERVICE_NAME: app
      SERVICE_TAGS: dev
    working_dir: /var/www
    volumes: 
      - ./laravel/php/local.ini:/usr/local/etc/php/conf.d/local.ini
    networks:
      - app-network
  # Nginx Service
  webserver:
    image: nginx:alpine
    container_name: webserver
    restart: unless-stopped
    tty: true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /home/username/laravel:/var/www
      - ./nginx/conf.d:/etc/nginx/conf.d
    networks:
      - app-network
  # MySQL Service
  db:
    image: mysql:5.7.22
    volumes:
      - ./mysql:/var/lib/mysql
    container_name: db
    restart: unless-stopped
    tty: true
    ports:
      - "3306:3306"
    environment:
      SERVICE_TAGS: dev
      SERVICE_NAME: mysql
      MYSQL_ROOT_PASSWORD: p@$$w0rd
    networks:
      - app-network
# Docker Networks
networks:
  app-network:
    driver: bridge

Где: 

  • app – служба, которая содержит приложение Laravel. Этот контейнер будет отвечать за выполнение PHP-кода и запуск команд Laravel.
  • webserver – Служба Nginx, которая прослушивает HTTP и HTTPS (порты 80 и 443), выполняя роль веб-сервера. Контейнер использует образ nginx:alpine, и монтируются конфигурации из каталога nginx.
  • db – контейнер MySQL, который предоставляет базу данных для приложения. В файле задается пароль и имя БД через переменные среды и указывается каталог для хранения данных. Порт 3306 выставляется для взаимодействия с базой данных через локальный компьютер.

Docker Compose также автоматически создает сеть для общения между контейнерами, что позволяет им «видеть» друг друга и безопасно взаимодействовать. В нашем случае сеть app-network объединяет все контейнеры, и служба app может взаимодействовать с webserver и db напрямую по их именам. Подключение контейнеров к отдельной сети изолирует их от других приложений, повышая безопасность.

Также стоит отметить, что, если не указать параметр container_name, Docker присвоит контейнерам случайные имена, что затруднит управление ими. Поэтому необходимо задать конкретные имена для каждого контейнера. 

Важно! Подключение всех служб к единой сети app-network позволяет Laravel обращаться к MySQL по имени db, а Nginx – к PHP по имени app. Это значительно упрощает конфигурацию и позволяет организовать надёжное взаимодействие между контейнерами.

Создание Dockerfile

Dockerfile – это специальный файл, который описывает, как собрать образ для запуска контейнера. В Dockerfile прописываются все шаги, необходимые для создания окружения, а Docker последовательно выполняет эти инструкции сверху вниз. 

Этот файл позволяет настраивать рабочую среду приложения, включая установку зависимостей, создание необходимых каталогов и файлов, а также настройку пользователя.

Расположим Dockerfile в корне нашего Laravel-проекта:

nano ~/laravel/Dockerfile

Пример Dockerfile для Laravel

# Базовый образ PHP с поддержкой FPM
FROM php:8.1-fpm
# Устанавливаем рабочую директорию
WORKDIR /var/www
# Копируем файлы composer для установки зависимостей
COPY composer.lock composer.json /var/www/
# Устанавливаем необходимые пакеты для работы Laravel
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    libpq-dev \
    libonig-dev \
    libzip-dev && \
    docker-php-ext-configure gd --with-freetype --with-jpeg && \
    docker-php-ext-install pdo_mysql mbstring zip exif pcntl gd && \
    apt-get clean && rm -rf /var/lib/apt/lists/*
# Устанавливаем Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Создаем пользователя и группу для работы с приложением
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Копируем файлы проекта в рабочую директорию
COPY . /var/www
COPY --chown=www:www . /var/www
# Меняем пользователя на www
USER www
# Открываем порт для php-fpm
EXPOSE 9000
# Запускаем php-fpm сервер
CMD ["php-fpm"]

Основные шаги в Dockerfile:

  1. В первой строке задаем образ php:8.1-fpm, который содержит PHP с поддержкой FastCGI Process Manager. Это оптимальный выбор для работы с Laravel.
  2. Устанавливаем /var/www как рабочую директорию для проекта с помощью команды WORKDIR. Все дальнейшие команды и файлы будут относиться к этому каталогу.
  3. С помощью RUN добавляем необходимые пакеты для работы Laravel, включая pdo_mysql, mbstring, zip и gd. Эти пакеты обеспечивают поддержку для взаимодействия с базами данных, работы с мультиязычными текстами и обработки изображений.
  4. Используем RUN для загрузки и установки Composer – менеджера зависимостей для PHP, который необходим для установки библиотек Laravel.
  5. Добавляем пользователя и группу www с UID и GID 1000, чтобы контейнер не запускался с правами суперпользователя. Это повышает безопасность, поскольку предотвращает выполнение кода от имени root.
  6. Директивой COPY переносим все файлы Laravel в /var/www. Аргумент --chown=www:www устанавливает права на файлы для пользователя www.
  7. Открываем порт 9000 для php-fpm и задаём команду CMD ["php-fpm"], чтобы контейнер запускал сервер php-fpm при старте.

Этот Dockerfile позволяет создать стандартное окружение для Laravel, а также настроить его так, чтобы приложение могло безопасно работать в контейнере. Созданный образ включает все необходимые компоненты и зависимости, готовые к запуску приложения.


Как настроить службы

Для корректной работы веб-приложения на Laravel с использованием Docker Compose важно настроить службы PHP, Nginx и MySQL. Эти настройки позволят контейнерам взаимодействовать друг с другом и обеспечат управление параметрами каждого сервиса. 

Ниже рассмотрим, как переопределить базовые настройки для каждой из этих служб.

MySQL

MySQL требуется для хранения данных, и ее конфигурацию можно дополнительно настроить в отдельном файле. 

Создайте каталог и файл конфигурации MySQL:

mkdir ~/laravel/mysql
nano ~/laravel/mysql/my.cnf

Добавьте следующие параметры в my.cnf для логирования запросов:

[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.log
max_connections = 200
sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"

Здесь:

  • general_log включает ведение журнала запросов, что помогает в отладке.
  • general_log_file указывает файл, в который будут записываться запросы.
  • max_connections задает максимальное количество подключений к базе данных.
  • sql_mode устанавливает режимы SQL, включая STRICT_TRANS_TABLES для предотвращения вставки некорректных данных.

Nginx

Nginx будет выполнять роль прокси-сервера, перенаправляя все входящие запросы на сервер PHP-FPM. Для этого нужно создать конфигурацию Nginx в файле app.conf, который монтируем в контейнере.

Создайте необходимые каталоги и файл конфигурации Nginx:

mkdir -p ~/laravel/nginx/conf.d
nano ~/laravel/nginx/conf.d/app.conf

Вставьте следующую конфигурацию в app.conf:

server {
    listen 80;
    server_name localhost;
    root /var/www/public;
    
    index index.php index.html;
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

Где:

  • listen указывает порт для прослушивания (80, стандартный HTTP-порт).
  • root задает корневую директорию для веб-приложения.
  • index указывает индексные файлы, которые Nginx будет использовать.
  • error_log и access_log задают файлы для записи ошибок и запросов.
  • location / перенаправляет все запросы на index.php, что позволяет Laravel обрабатывать маршрутизацию.
  • location ~ .php$ конфигурирует параметры для выполнения PHP-файлов, передавая запросы на php-fpm, работающий на порту 9000.

PHP

Чтобы PHP корректно обрабатывал запросы, поступающие через Nginx, создадим файл local.ini, который позволяет управлять параметрами конфигурации PHP. Его мы укажем в docker-compose.yml по пути /usr/local/etc/php/conf.d/local.ini. Если файл не создать, контейнер будет использовать стандартный php.ini.

Создайте каталог и файл для конфигурации PHP:

mkdir ~/laravel/php 
nano ~/laravel/php/local.ini

Добавьте в local.ini следующие настройки для подробного отображения ошибок:

error_reporting = E_ALL
display_errors = On
memory_limit = 256M

Эти директивы активируют вывод всех ошибок (error_reporting = E_ALL), показывают их в браузере (display_errors = On) и задают ограничение на потребление памяти в 256 МБ. Файл можно изменить в будущем, например, добавив нужные параметры конфигурации для специфических задач.

Как запустить контейнер

После настройки конфигураций для основных служб можно переходить к запуску контейнеров. Однако прежде чем это сделать, зададим необходимые параметры для приложения Laravel в файле .env. 

Для начала скопируйте .env.example и создайте на его основе новый .env файл:

cd ~/laravel
cp .env.example .env
nano .env

Теперь в файле .env задайте настройки подключения к базе данных и URL вашего приложения:

APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel_user
DB_PASSWORD=secure_password

Здесь:

  • APP_URL – URL вашего приложения (укажите http://localhost, если тестируете локально).
  • DB_CONNECTION – тип подключения. Укажите mysql.
  • DB_HOST – имя хоста базы данных, в Docker оно совпадает с названием сервиса, заданным в docker-compose.yml, например, db.
  • DB_PORT – порт для подключения к базе данных (обычно 3306 для MySQL).
  • DB_DATABASE, DB_USERNAME, DB_PASSWORD – имя базы данных, пользователя и пароль, которые вы указали в docker-compose.yml.

Теперь, когда все параметры заданы, запустите Docker Compose для создания и запуска контейнеров:

docker-compose up -d

При первом запуске Docker загрузит необходимые образы из Docker Hub. Это может занять некоторое время. После загрузки и сохранения образов на локальной машине Docker Compose автоматически создаст контейнеры и запустит все службы в фоновом режиме благодаря флагу -d.

Чтобы проверить, что все контейнеры успешно запущены, выполните команду:

docker ps

Эта команда отобразит список работающих контейнеров с уникальными идентификаторами, именами, образами и текущим статусом. Если все службы работают корректно, вы увидите запущенные контейнеры для приложения Laravel, веб-сервера Nginx и базы данных MySQL.

Теперь ваше приложение Laravel готово к использованию в контейнерах.

Как сгенерировать ключ APP_KEY (ключ приложения Laravel)

Чтобы обеспечить безопасность Laravel-приложения, необходимо сгенерировать уникальный ключ приложения, который хранится в переменной APP_KEY в файле .env. Он используется для шифрования данных и должен быть задан при первой настройке.

Чтобы выполнить команду генерации ключа внутри контейнера с приложением Laravel, пропишите команду:

docker-compose exec app php artisan key:generate

Она сгенерирует и автоматически добавит ключ APP_KEY в файл .env. После этого ключ будет готов к использованию для шифрования данных в приложении.

Чтобы повысить производительность, также закешируем конфигурацию приложения. Кеширование помогает быстрее загружать параметры при каждом запросе:

docker-compose exec app php artisan config:cache

Команда создаст файл кеша конфигурации в /var/www/bootstrap/cache/config.php, что ускорит загрузку приложения.

Вы можете открыть браузер и ввести IP-адрес сервера или localhost (в зависимости от настроек). Если увидите стартовую страницу Laravel, то это будет означать, что настройка прошла успешно.

Вывод

Настройка Laravel, Nginx и MySQL с помощью Docker Compose позволяет создать удобную и изолированную среду для разработки, которая легко масштабируется и переносится на разные машины. Мы рассмотрели, как создать Dockerfile для Laravel, настроить конфигурации PHP, Nginx и MySQL, а также запустить контейнеры через Docker Compose. Такой подход позволяет упростить управление зависимостями, изолировать сервисы и ускорить процесс разработки.

Теперь у вас есть гибкое окружение, которое можно легко модифицировать и масштабировать в зависимости от потребностей вашего проекта. В будущем это позволит быстрее развертывать Laravel-приложения и обеспечит стабильную работу всех служб.