Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.
Кратко о задаче
Laravel — бесплатный фреймворк с открытым исходным кодом. Его используют для создания архитектурно сложных веб-приложений. Загрузим в домашнюю директорию из GitHub актуальную версию:
cd ~
git clone https://github.com/laravel/laravel.gitСмонтируем образ composer в каталог проекта Laravel, поскольку крайне не рекомендуется устанавливать Composer глобально и запускать из-под суперпользователя:
cd laravel
docker run -v $PWD:/app composer installЭтой командой мы создаём виртуальный контейнер, который будет привязан к текущему каталогу; всё, что находится внутри каталога laravel, скопировано в контейнер. Каталог vendor, который создал менеджер зависимостей Composer в рамках команды install, также скопирован в текущий каталог, то есть в laravel.
Затем изменим права на каталог так, чтобы к нему был доступ у обычного пользователя, поскольку нам понадобится запускать процессы в контейнере без root-привилегий.
sudo chown -R username:username ~/laravelТеперь можно приступать к работе со службами с помощью Docker Compose.
Для решения задач, связанных с развёртыванием проектов, которые используют несколько сервисов, разработан инструмент Docker Compose. Если Docker применяется для управления отдельными контейнерами, то Docker Compose позволяет работать с приложениями со сложной архитектурой и множеством зависимостей.
Для настройки приложения Laravel создадим файл docker-compose.yml и определим необходимые службы — веб-сервер и базу данных.
nano ~/laravel/docker-compose.yml
version: '3'
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, который мы определим в дальнейшем. Также определяет рабочую директорию —
/var/www. - webserver. Содержит образ nginx:alpine и определяет порты 80 (http) и 443 (https) для работы веб-сервера.
- db. Указываем образ mysql из Docker Hub. Кроме этого определяем переменные среды — базу данных
laravel, пароль (в нашем случае —p@$w0rd) и порт.
Если Docker Hub недоступен, можно использовать наш бесплатный прокси, который возобновляет этот доступ.
Обратите внимание, что если вы не укажете имя контейнера container_name, Docker сделает это за вас. При этом он присвоит контейнерам имя исторической личности и случайного слова — это значительно усложнит администрирование вашего приложения.
Для того чтобы организовать взаимодействие между контейнерами, подключим службы к соединительной сети app-network. Так приложения из разных сетей не смогут взаимодействовать друг с другом — это значительно повысит безопасность проекта.
Далее приступим к настройке основных служб.
С помощью специального файла Dockerfile можно указать, как собирать образы, на основе которых создаётся контейнер. Этот файл содержит инструкции и аргументы, которые при работе с Docker обрабатываются сверху вниз.
Наш Dockerfile расположим в корне проекта:
nano ~/laravel/DockerfileВ первой строке мы указываем, что нужно создать образ PHP-FPM версии 8.1. Кроме того, установим нужные для работы приложения Laravel пакеты: pdo_mysql , mbstring , imagick __ и composer.
В качестве аргументов директивы RUN укажем команды для установки и обновления зависимостей. А также создадим пользователя и группу www __ для работы с приложением Laravel. Так мы снизим риски при запуске контейнера Docker, поскольку иначе они бы запускались с правами суперпользователя.
С помощью Workdir укажем рабочий каталог /var/www и зададим необходимые права для нового пользователя www, воспользовавшись командой COPY. Директивой EXPOSE откроем 9000 порт для сервера php-fpm.
После создания контейнера нужно запустить php-fpm сервер, для этого используем команду CMD.
Чаще всего для веб-приложений достаточно основных файлов конфигурации служб. В рамках нашего примера мы всё же переопределим базовые настройки для демонстрации возможностей контейнеризации.
После того, как мы определили конфигурацию контейнера, нужно настроить PHP для обработки входящих запросов NGINX. Для начала нужно создать файл local.ini, путь к нему мы указывали в файле docker-compose.yml — /usr/local/etc/php/conf.d/local.ini. Если мы не создадим этот файл, контейнер будет использовать стандартный файл конфигурации PHP: php.ini.
В директории приложения laravel создаём каталог php и файл local.ini в нём:
mkdir ~/laravel/php
nano ~/laravel/php/local.iniВ этот файл вставим директиву для отображения всех ошибок:
Затем файл можно сохранить и закрыть. Когда мы приступим к активной работе над приложением, сможем добавить любые параметры конфигурации для переопределения стандартных.
В нашем примере мы используем NGINX в качестве прокси-сервера. Это значит, что все входящие запросы будут асинхронно передаваться на бэкенд (в нашем случае — PHP-FPM).
По аналогии с настройкой PHP мы также создадим в каталоге laravel файл /nginx/conf.d/app.conf:
mkdir -p ~/laravel/nginx/conf.d
nano ~/laravel/nginx/conf.d/app.confВнутри файла определим конфигурацию прокси-сервера:
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
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;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}Внутри блока server используем следующие директивы:
Listen— порт, на котором сервер будет отлавливать запросы.Index— индексные файлы веб-приложения.Error_log,access_log— файлы для записи журналов ошибок и запросов к серверу.root— корневой каталог веб-приложения.
Внутри первого блока location определим настройки PHP. В частности, укажем, что служба app прослушивает 9000 порт. Директива fastcgi_pass указывает, что сервер PHP-FPM должен выполнять прослушивание через сокет TCP. Второй блок location задаёт правила перенаправления всех запросов на индексный файл index.php с сохранением параметров.
Настройка MySQL осуществляется аналогично конфигурации веб-сервера и PHP. Сначала мы создадим файл в каталоге, который указали внутри файла docker-compose.yml:
mkdir ~/laravel/mysql
nano ~/laravel/mysql/my.cnfВ этом файле определим общие правила журналирования:
[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.logПосле того, как мы определили конфигурацию для основных служб, можно запускать контейнеры. Но перед этим укажем настройки приложения Laravel в специальном файле .env. Внутри каталога Laravel уже есть пример такого файла, который поставляется в дистрибутиве — .env.example. Копируем его и указываем свои настройки там, где это нужно:
cd ~/laravel
cp .env.example .env
nano .envОсновная настройка для приложения — доступ для подключения к базе данных и адрес сервера. В файле найдём строку APP_URL и укажем домен или IP-адрес нашего сайта, далее в блоке DB_CONNECTION укажем наши данные:
APP_URL=http://domain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=p@$w0rd
MYSQL_ROOT_PASSWORD=p@$w0rdКогда все настройки будут определены, нужно выполнить всего одну команду для запуска контейнеров, служб и подключений:
При первом вызове Docker будет загружать в систему образы, поэтому запуск может занять некоторое время. После сохранения образов на локальной машине Docker Compose создаст наши контейнеры. При этом, чтобы обеспечить их работу в фоновом режиме, мы должны использовать флаг -d.
Вы можете проверить корректность запуска всех процессов с помощью команды docker ps. Она отобразит список контейнеров, их уникальные идентификаторы, имена, образы и статусы.
Для корректной работы приложения Laravel мы должны сгенерировать ключ APP_KEY в .env-файл. Для этого воспользуемся docker-compose exec, эта утилита позволяет выполнять команды в конкретных контейнерах:
docker-compose exec app php artisan key:generate… и сохраним настройки в кэш для ускорения загрузки:
docker-compose exec app php artisan config:cacheПри кэшировании настройки будут загружены в файл /var/www/bootstrap/cache/config.php.
Теперь, если ввести IP-адрес вашего сервера в адресную строку браузера, вы увидите стартовую страницу Laravel.
Создание пользователя MySQL
Только после того, как мы запустили контейнеры, можно приступить к созданию пользователя и базы данных для приложения Laravel.
По умолчанию MySQL создаётся только одна учётная запись — root. Но использовать её в веб-среде небезопасно, поскольку root-пользователь обладает неограниченными привилегиями.
Воспользуемся командой docker-compose exec для того, чтобы перейти в интерактивную оболочку bash в контейнере db:
docker-compose exec db bashПоскольку при создании файла docker-compose.yml мы определили базу данных laravel, она уже создана. Убедимся в этом:
show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| laravel |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.01 sec)Создаём учётную запись laravel __ с доступом только к этой базе данных. Пароль нужно указать такой же, как и в файле .env:
GRANT ALL ON laravel.* TO 'laravel'@'%' IDENTIFIED BY 'p@$w0rd';Обновляем привилегии, закрываем MySQL и выходим из контейнера:
mysql> FLUSH PRIVILEGES;
mysql> EXIT;
# exitВ этой статье мы рассмотрели преимущества использования контейнеризации в работе с веб-приложениями. Среди основных плюсов — независимость приложений друг от друга и от сервера, на котором они находятся.
Для упрощения работы с контейнерами использовали Docker Compose, который позволяет создавать группу контейнеров Docker, а не запускать каждый по отдельности. В качестве демонстрации простоты работы с контейнерами создали простое Laravel-приложение, используя стек LEMP.
В официальном канале Simple-Server собрали комьюнити из специалистов, которые говорят про IT-тренды, делятся полезными инструкциями и даже приглашают к себе работать.
Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.