Назад в блог

Развертывание Laravel, Nginx и MySQL с помощью Docker Compose

Развертывание Laravel, Nginx и MySQL с помощью Docker Compose

Введение

Непрерывная интеграция (CI) и непрерывное развертывание (CD) — одни из самых актуальных тем в современной разработке программного обеспечения. Чтобы реализовать CI/CD аспект архитектуры программного обеспечения, разработчики используют контейнеры. Контейнеры представляют собой легковесные, виртуализированные, переносимые, программно-определяемые среды. В контейнерах программное обеспечение может работать изолированно от другого ПО, запущенного на физическом хосте. В этом руководстве основное внимание уделяется использованию контейнерной платформы Docker для развертывания и запуска веб-приложений. Docker помогает упростить процесс настройки стека веб-сервера. В этом руководстве мы будем использовать стек LEMP для обслуживания приложения Laravel .

Стек LEMP объединяет Linux в качестве операционной системы, Nginx в качестве веб-сервера, MySQL в качестве базы данных и PHP в качестве языка для написания скриптов и динамической обработки. Вы можете воспользоваться нашим руководством по установке и настройке стека LEMP в Ubuntu. Laravel — один из лучших PHP-фреймворков для разработки веб-приложений.

Docker предоставляет инструмент под названием Docker Compose для определения процесса настройки контейнера Docker. Docker Compose позволяет разработчикам описывать инфраструктуру своего приложения, службы, тома, сети и любые зависимости в одном файле, называемом файлом docker-compose. Он может управлять несколькими контейнерами Docker с помощью своих команд, таких как docker container create, docker container run и т. д.

В этом руководстве вы узнаете, как развернуть веб-приложение Laravel с Nginx и MySQL внутри контейнера Docker. Конфигурации для всего стека будут определены внутри файла docker-compose, а также другие конфигурационные файлы для PHP, MySQL и Nginx. Давайте начнем!

Прежде всего

Шаг 1. Загрузка Laravel и установка зависимостей

Первый шаг — получить код Laravel из репозитория. В реальных сценариях ваш код Laravel может находиться в каком-либо репозитории, например на GitHub, Bitbucket, GitLab и т. д. Однако в рамках этого руководства мы будем клонировать последнюю версию из официального репозитория Laravel на GitHub. Репозиторий поставляется с файлом composer — менеджером зависимостей уровня приложения для PHP. Поскольку мы хотим, чтобы все работало внутри контейнера Docker, мы установим зависимости с помощью Docker-образа composer . Это также поможет нам избежать необходимости устанавливать composer глобально на самом хосте. Теперь запустите терминал.

Перейдите в свой домашний каталог:

Введите следующую команду, чтобы клонировать репозиторий в каталог с именем laravel-web. Вы можете назвать его как угодно. На момент написания этого руководства при выполнении этой команды загружается Laravel версии 8. Когда вы запустите команду, вы, вероятно, получите более новую версию:

Затем перейдите в каталог, в который вы только что клонировали репозиторий:

Введите следующую команду, чтобы смонтировать каталоги, необходимые вашему приложению Laravel, используя образ composer:

Флаги -v и –rm в команде docker run создают временный контейнер, который монтируется к текущему каталогу перед удалением. Команда копирует содержимое ~/laravel-web в контейнер и гарантирует, что папка vendor, созданная composer, будет скопирована обратно в текущий каталог.

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

Код вашего приложения теперь на месте. Владельцем директории является пользователь без прав root, поэтому вы можете перейти к определению служб приложения в файле docker-compose.

Шаг 2: Создание файла Docker Compose

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

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

Файлы Docker Compose представляют собой YAML файлы, сохраненные с расширением .yml. Обратите внимание, что для корректного файла Docker Compose необходимы правильные отступы. Введите следующую команду, чтобы создать и открыть файл в nano для редактирования:

Далее вы определите три службы в этом файле: app, webserver и db. Раздел db определяет учетные данные базы данных для вашего приложения, поэтому обязательно выберите надежный mysql_root_password и замените его в этом разделе. Скопируйте и вставьте следующий код:

Ниже приведены пояснения к определениям служб из приведенного выше кода:

  • app: определяет приложение Laravel и запускает кастомный Docker-образ cloudsigma.com/php, который мы определим в Шаге 4. Он также устанавливает working_dir в контейнере на /var/www/html.
  • webserver: он загружает образ nginx:alpine из Docker и открывает порты 80 и 443.
  • db: он загружает образ mysql:5.7.32 из Docker и определяет несколько переменных окружения. К ним относится база данных с именем laravel_web для приложения и root-пароль для базы данных. Вы можете переименовать базу данных по своему усмотрению. Не забудьте заменить свойство MYSQL_ROOT_PASSWORD надежным паролем. Эта служба также сопоставляет порт 3306 на хосте с портом 3306 в контейнере.

Свойство container_name в каждой службе определяет имя контейнера, соответствующего этой службе. Если вы не определите это свойство, Docker выберет случайное имя для каждого контейнера.

Свойство networks определяет мостовую сеть под названием app-network, которая облегчает взаимодействие между контейнерами. Мостовая сеть управляется программным мостом, который разрешает связь только между контейнерами на одном и том же сетевом мосту. Программный контроллер моста устанавливает драйверы, которые предотвращают прямое взаимодействие контейнеров в разных мостовых сетях друг с другом. Это обеспечивает высокий уровень безопасности, так как напрямую могут общаться только связанные службы. Вы можете определить несколько служб и сетей, подключающихся к связанным функциям.

Шаг 3: Как обеспечить постоянное хранение данных

Ваше веб-приложение будет обрабатывать и предоставлять данные вашим пользователям. На этом шаге мы расскажем вам, как определить тома (volumes) и привязки каталогов (bind mounts) в определениях служб для сохранения данных приложения. Docker предлагает такие невероятные возможности, как привязки каталогов и тома для постоянного хранения данных и сохранения конфигурационных файлов приложения. Мы будем использовать их при настройке нашего приложения Laravel с помощью Docker.

Тома предпочтительнее по разным причинам, включая возможность создания резервных копий и сохранение данных после окончания жизненного цикла контейнера. Привязки каталогов (Bind Mounts) обычно ссылаются на реальный каталог на хост-машине. Когда вы создаете том, внутри каталога хранения Docker создается новый каталог, которым управляет Docker. Когда вы создаете привязку каталога, файл или каталог на хост-машине монтируется в контейнер (по его абсолютному пути). Это крайне важно для нашего веб-приложения, так как при внесении изменений в код на хост-машине они сразу же станут доступны в контейнере.

Будьте осторожны при использовании привязок каталогов. Процессы, запущенные внутри контейнера Docker, могут вносить изменения в файловую систему хоста и влиять на процессы, не связанные с Docker, запущенные на хост-системе. Хотя монтирование в Docker — это мощная функция, помните об этих последствиях для безопасности.

С учетом сказанного, давайте посмотрим, как мы можем использовать эти две функции в нашей конфигурации. Сначала мы определим том для постоянного хранения базы данных MySQL. В созданном нами файле Docker Compose в службе db добавьте свойство volumes, как выделено ниже:

Как определено, том dbdata будет сохранять содержимое /var/lib/mysql. Это облегчает резервное копирование и позволяет перезапускать службу без потери данных. Далее вам следует добавить определение volumes в конец файла Docker Compose, чтобы сделать его доступным для всех служб. Введите следующий фрагмент кода в самый низ файла:

Для подключения к базе данных MySQL необходимо предоставить учетные данные. Для этого определите привязку каталога, добавив следующий выделенный фрагмент кода в службу db под свойством volumes:

Код привязывает ~/laravel-web/mysql/my.cnf к /etc/mysql/my.cnf в контейнере. Привязанный файл — это конфигурационный файл MySQL, который мы создадим на Шаге 7.

Контейнеру необходимо использовать сервер Nginx для обслуживания кода вашего приложения. Поэтому для этой цели мы определим две привязки каталогов (одну для конфигурационного файла Nginx и одну для кода приложения) в службе webserver. Добавьте следующий фрагмент кода для определения volumes в службу webserver:

Эта строка – ./:/var/www/html связывает код приложения в директории ~/laravel-web с директорией /var/www/html внутри контейнера. Для второго монтирования привязки (bind mount) файл конфигурации Nginx будет создан в ~/laravel-web/nginx/conf.d/. Он будет смонтирован в /etc/nginx/conf.d/ внутри контейнера. Таким образом, вы сможете обновлять конфигурационный файл на хост-машине по мере необходимости. Мы создадим конфигурационный файл Nginx в Шаге 6.

Чтобы изменения в коде автоматически отражались в контейнере, мы монтируем код приложения в контейнер с помощью bind mount. Это ускоряет процесс развертывания. Таким образом, добавьте следующий выделенный фрагмент кода в службу app:

Вторая строка привязывает конфигурационный файл php, который мы создадим в Шаге 5 внутри файла ~/laravel-web/php/laravel.ini, к /usr/local/etc/php/conf.d/laravel.ini внутри контейнера.

Теперь ваш полный файл Docker Compose должен выглядеть следующим образом:

Если все выглядит правильно, нажмите Ctrl + O, чтобы сохранить файл. Затем нажмите Ctrl + X, чтобы выйти из редактора. На данном этапе вы сможете собрать собственный Docker-образ для вашего приложения с помощью файла Docker Compose.

Шаг 4. Создание Dockerfile

Dockerfile содержит инструкции, которые Docker может использовать для сборки пользовательских Docker-образов. Он также может устанавливать необходимое программное обеспечение и настраивать параметры для вашего приложения. Они определяют среду внутри контейнера, в которой будет размещен код вашего приложения. Вы можете отправить созданные вами образы в docker hub для совместного использования или разместить их в других приватных реестрах.

Мы создадим Dockerfile, который будет содержать инструкции для сборки образа приложения Laravel. Используйте nano для создания Dockerfile в каталоге ~/laravel-web:

В открывшемся редакторе добавьте следующий код:

Сначала Dockerfile создает образ на основе php:7.4-fpm Docker-образа. Это образ на базе Debian с установленной реализацией PHP FastCGI (PHP-FPM). Для правильной работы Laravel требуются другие расширения php, такие как mcrypt, pdo_mysql, mbstring и imagick, которые устанавливает скрипт. Затем он устанавливает composer — менеджер пакетов php. Контейнер будет использовать его для установки php-зависимостей Laravel.

Вы можете использовать директиву RUN для определения таких команд, как установка, обновление и настройка параметров внутри контейнера. Она также назначает права пользователей. Директива WORKDIR указывает рабочую директорию, в данном случае /var/www/html. Скрипт выполняет команду CHOWN для назначения прав на директорию /var/www/html пользователю www-data.

Перед окончательной сборкой образа необходимо открыть порт, чтобы разрешить доступ к приложению, работающему внутри контейнера. Команда EXPOSE открывает порт 9000 для сервера php-fpm. Последней выполняемой командой является директива CMD. Она запускает php-fpm для старта сервера.

Теперь вы можете нажать Ctrl + O, чтобы сохранить файл. Затем нажмите Ctrl + X, чтобы выйти из редактора.

Шаг 5: Настройка PHP

На этом шаге мы настроим службу php для обработки входящих запросов от Nginx. Вы создадите файл laravel.ini внутри каталога php. Этот файл будет содержать конфигурации PHP. Это тот самый файл, который вы примонтировали (bind-mount) к /usr/local/etc/php/conf.d/laravel.ini в контейнере на Шаге 3. Конфигурации в этом файле переопределяют стандартный файл php.ini, который обычно считывается PHP при запуске. Введите следующую команду, чтобы создать каталог php:

Создайте и откройте файл laravel.ini внутри каталога php, введя следующую команду:

По умолчанию в файле php.ini лимит на загрузку файлов установлен в 2M. В качестве примера мы покажем вам, как скорректировать и настроить конфигурацию php, изменив значение разрешенного лимита загрузки, на случай, если вы захотите загружать файлы большего размера. Введите следующие строки кода внутрь файла:

Это устанавливает лимит загрузки, и вы сможете загружать файлы общим размером не более 80 МБ. Вы можете добавить другие конфигурации php внутрь файла laravel.ini, чтобы переопределить стандартные настройки php. Теперь сохраните и закройте файл.

Шаг 6. Настройка Nginx

На этом шаге мы настроим Nginx для использования службы php, которую мы определили ранее. Она будет использовать PHP-FPM в качестве сервера FastCGI для обслуживания динамического контента. Сервер FastCGI — это программное обеспечение, которое позволяет интерактивным программам взаимодействовать с веб-сервером.

Как мы определили в файле docker-compose на Шаге 3, мы создадим конфигурационный файл Nginx app.conf внутри каталога ~/laravel-web/nginx/conf.d/. Сначала введите следующую команду для создания каталога:

Затем создайте и откройте файл app.conf с помощью nano, введя следующую команду:

Добавьте следующий код конфигурации Nginx в файл:

Nginx считывает конфигурационные файлы, называемые серверными блоками (server blocks), чтобы знать, какой каталог должен обслуживаться для посетителя сайта на основе URL-адреса. Чтобы узнать больше, прочитайте о настройке серверных блоков в нашем руководстве по установке Nginx в Ubuntu 18.04. Определенные директивы служат следующим целям:

  • listen – определяет порт, на котором сервер будет ожидать входящие запросы, обычно это порт 80.
  • error_log & access_log – определяет файлы для записи логов приложения.
  • root – определяет путь к корневому веб-каталогу (webroot), который будет обслуживать любые запросы к серверу из интернета.

В блоке location для php директива fastcgi_pass указывает, что служба app ожидает подключения на TCP-сокете через порт 9000 (который был определен в Dockerfile). Это указывает серверу PHP-FPM ожидать подключения по сети, а не через Unix-сокет. Хотя Unix-сокет может иметь небольшое преимущество в скорости по сравнению с TCP-сокетом, у него отсутствует сетевой протокол, что позволяет обойти сетевой стек.

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

Теперь вы можете нажать Ctrl + O, чтобы сохранить файл, а затем Ctrl + X, чтобы выйти из редактора. Изменения, внесенные в каталог nginx/conf.d/, автоматически отразятся в контейнере веб-сервера благодаря монтированию привязки (bind mount), которое вы добавили в файл Docker Compose в Шаг 3.

Шаг 7: Настройка MySQL

После того как мы настроили Nginx для работы с PHP, мы можем настроить MySQL для хранения и предоставления динамических данных для PHP. Мы уже настроили файл Docker Compose для установки необходимых расширений для взаимодействия PHP и MySQL. Мы создадим конфигурационный файл MySQL my.cnf внутри папки mysql, который будет примонтирован к /etc/mysql/my.cnf, как мы определили в разделе службы db в Docker Compose в Шаг 3.

Настройки конфигурации MySQL и изменения в файл my.cnf можно вносить в любое время. Они должны немедленно отразиться внутри контейнера. Сначала создайте каталог, введя следующую команду:

Затем создайте и откройте nano, введя следующую команду:

Введите следующий фрагмент кода, чтобы включить журнал запросов и указать расположение файла журнала запросов:

Определив свойство general_log как 1, вы разрешаете общие журналы. Свойство general_log_file указывает расположение файла журналов. Нажмите Ctrl + O, чтобы сохранить файл, затем нажмите Ctrl + X, чтобы выйти из редактора.

Шаг 8: Настройка переменных окружения Laravel

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

После копирования откройте файл с помощью nano для редактирования:

Вот скриншот того, как может выглядеть файл:

screenshot of what the file

В файле следующим шагом является изменение переменных в блоке DB_CONNECTION в соответствии с ранее выполненными настройками. Обновите их следующим образом:

  • DB_HOST — это db контейнер базы данных.
  • DB_DATABASE — это laravel_web.
  • DB_USERNAME — это имя пользователя для базы данных. Выберите любое имя на свой вкус, но в рамках этого руководства давайте остановимся на laraveldocker.
  • DB_PASSWORD — это надежный пароль, который ваш пользователь выше будет использовать для входа в базу данных, поэтому выберите надежный пароль. В Шаге 10, мы создадим этого пользователя с паролем, который вы выберете здесь.

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

DB_CONNECTION

Сохраните и закройте файл.

Шаг 9: Запуск контейнеров Docker

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

При первом запуске команды docker-compose up загружаются все необходимые образы Docker. Если вы настраиваете инфраструктуру на своем локальном компьютере, это может занять некоторое время. После загрузки образов Compose создает контейнеры. Флаг -d указывает Docker запускать контейнеры в фоновом режиме. Если процесс завершится успешно, вы должны увидеть в своем терминале что-то подобное:

terminal

Введите следующую команду в терминале, чтобы вывести список всех запущенных контейнеров:

Должно отобразиться что-то похожее на скриншот ниже с подробной информацией о контейнерах app, webserver и db:

screenshot details

  • CONTAINER ID — уникальный идентификатор для каждого контейнера.
  • NAMES — имя службы, связанное с каждым контейнером, как определено в файле Docker Compose. (Вы можете использовать либо ID, либо имя контейнера для доступа к нему).
  • IMAGE — имя образа для каждого контейнера.
  • STATUS — отображает информацию о состоянии контейнера (он может быть остановлен, запущен или перезапускается).
  • PORTS — показывает порты, которые открывает контейнер.

Docker Compose предоставляет команду exec, которую можно использовать для запуска команд терминала или доступа к командной строке внутри контейнера. Сначала мы хотим запустить несколько команд внутри контейнера app, в котором запущено приложение Laravel.

Docker предоставляет команду для доступа к командной строке контейнера. Ее синтаксис следующий: docker-compose exec container_name bash. Чтобы получить доступ к командной строке контейнера app, введите следующую команду:

Оказавшись в командной строке контейнера, вы можете запустить некоторые команды настройки Laravel Artisan. Введите следующую команду, чтобы сгенерировать ключ laravel и сохранить его в файл .env:

После установки ключа окружения вы можете запустить следующую команду для кэширования настроек конфигурации:

Конфигурации сохраняются в файле /var/www/html/bootstrap/cache/config.php внутри контейнера. Вы можете нажать Ctrl + D, чтобы выйти из терминала контейнера.

Чтобы подтвердить, что приложение Laravel развернуто и работает, перейдите по публичному IP-адресу вашего сервера в браузере (http://your_server_public_ip). Вы должны увидеть приветственную страницу новой установки Laravel:

laravel screenshot

Шаг 10: Настройка пользователя MySQL

На этом шаге мы создадим пользователя базы данных для базы данных MySQL laravel_web, которую мы указали в файле docker-compose. Когда вы запустили команду сборки контейнера на Шаге 9, MySQL был установлен, но создал только учетную запись администратора root по умолчанию, которая имеет неограниченные привилегии в базе данных. Чтобы избежать использования пользователя root, мы создадим специального пользователя laraveldocker для использования в приложении. Это пользователь, которого вы указали в переменных окружения на Шаге 8. Получите доступ к командной строке внутри терминала, введя следующую команду:

Оказавшись внутри контейнера, войдите в MySQL, введя следующую команду:

В запросе пароля введите пароль, который вы установили для службы db в файле docker-compose на Шаге 2.

После входа в консоль MySQL проверьте, видите ли вы базу данных, указанную в файле docker-compose, введя следующую команду SQL:

Вы должны увидеть базу данных laravel_web или любое другое имя, которое вы указали для своей конфигурации:

Laravel

Далее мы создаем пользователя и пароль для базы данных laravel_web. Это должны быть те же данные, которые вы указали в файле .env на Шаге 8. Введите следующую команду, чтобы создать пользователя и пароль, а также предоставить этому пользователю все привилегии:

Чтобы изменения вступили в силу немедленно, введите следующую команду для сброса привилегий:

На этом настройка пользователя MySQL завершена. Выйдите из командной строки MySQL, введя exit и нажав Enter. Наконец, выйдите из контейнера db, нажав Ctrl + D.

Шаг 11: Тестирование взаимодействия между кодом приложения Laravel и базой данных MySQL

До этого момента все работало отлично. Однако мы хотим убедиться, что код Laravel в контейнере app может взаимодействовать с базой данных MySQL в контейнере db. Сначала войдите в терминал контейнера app, выполнив следующую команду:

Далее необходимо запустить команду миграции Laravel, которая создает таблицы:

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

migration process

Далее мы проверим, можем ли мы получить доступ к базе данных из Laravel. Laravel поставляется с Tinker по умолчанию, что позволяет вам взаимодействовать со всем приложением из командной строки, включая доступ к базе данных, запуск задач, eloquent ORM, и многое другое. Мы можем использовать Tinker для просмотра данных в таблице миграций. Введите следующую команду для доступа к Tinker:

Находясь в командной строке Tinker, вы можете вывести список таблиц, созданных командой migrate, введя следующее:

На скриншоте ниже показан вывод — таблицы, которые в данный момент находятся в базе данных laravel_web:

laravel_web database

Вы можете извлечь данные из таблицы, указав ее имя. Например, вы можете получить данные из таблицы migrations, введя следующую команду:

Команда выводит следующее:

comman output

Судя по выводу выше, ваше приложение Laravel правильно настроено и может взаимодействовать с базой данных. Вы можете поэкспериментировать с другими командами, такими как создание моделей, запуск задач и т. д. Вы можете выйти из командной строки Tinker, нажав Ctrl + D.

Заключение

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

Если вы хотите поближе познакомиться с контейнерами, ознакомьтесь с нашим руководством, в котором показано, как очистить ресурсы Docker — образы, контейнеры и тома и нашим подробным обзором инструмента Kubernetes.

Вы также можете посетить наш блог, чтобы узнать больше о Docker, непрерывной интеграции и непрерывном развертывании.

Приятной работы!

author

Pranay Kapgate

Автор · CloudSigma

Preslav Dobrev — креативный дизайнер в CloudSigma, сосредоточенный на формировании последовательного корпоративного образа с помощью традиционных и инновационных маркетинговых каналов. Он умело сочетает художественное видение со стратегическим маркетингом, создавая убедительные истории бренда.

Комментарии

Комментариев пока нет. Будьте первым.