Categories: Скрипты

Пример docker-compose для развертывания веб-сервера с Laravel

Используемые термины: Docker , PHP , NGINX , MariaDB , Linux .

В инструкции мы рассмотрим простой пример сценария docker-compose, который позволит быстро развернуть инфраструктуру с Laravel. Ссылки на страницы с дополнительной информацией по работе с docker будут приведены в конце инструкции .

Laravel является фреймворком общего назначения, который разработан на PHP. Значит нам понадобится инфраструктура с веб-сервером, базой данных и интерпретатором PHP. В итоге мы получим систему, состоящую из:

  • Веб-сервера NGINX.
  • СУБД MariaDB.
  • PHP версии 8.1.
  • phpMyAdmin (опционально).

Нами будут выполнены следующие шаги:

Также рекомендую к прочтению статью на хабре Laravel+Docker+Gitlab. С чего начать .

Готовим систему

Подготовим операционную систему к работе.

1. Установка Docker.

Для запуска сценария нам необходимо установить docker и docker-compose. Для каждого типа Linux необходимо выполнить свой набор команд.

Подробнее процесс описан в инструкции Установка Docker на Linux .

2. Каталог для работы.

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

mkdir /opt/laravel

cd /opt/laravel

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

Сценарий и настройка сервера

Создаем файл docker-compose:

vi docker-compose.yml

  1. services:
  2. laravel_nginx:
  3. image: nginx
  4. hostname: laravel_nginx
  5. container_name: laravel_nginx
  6. restart: unless-stopped
  7. environment:
  8. TZ: «Europe/Moscow»
  9. ports:
  10. — 80:80
  11. — 443:443
  12. volumes:
  13. — ./nginx/conf.d:/etc/nginx/conf.d
  14. — ./nginx/ssl:/etc/nginx/ssl
  15. — ./www_data:/usr/share/nginx/html
  16. laravel_php:
  17. build:
  18. context: ./php/
  19. hostname: laravel_php
  20. container_name: laravel_php
  21. restart: unless-stopped
  22. user: root
  23. environment:
  24. TZ: «Europe/Moscow»
  25. volumes:
  26. — ./www_data:/var/www/html
  27. — ./php/php.ini:/usr/local/etc/php/php.ini
  28. laravel_db:
  29. image: mariadb
  30. hostname: laravel_db
  31. container_name: laravel_db
  32. restart: unless-stopped
  33. environment:
  34. TZ: «Europe/Moscow»
  35. MARIADB_DATABASE: laravel
  36. MARIADB_USER: laravel
  37. MARIADB_PASSWORD: laravel123
  38. MARIADB_ROOT_PASSWORD: root_password123
  39. volumes:
  40. — ./mysql_data:/var/lib/mysql
  41. laravel_pma:
  42. image: phpmyadmin
  43. hostname: laravel_pma
  44. container_name: laravel_pma
  45. restart: unless-stopped
  46. environment:
  47. TZ: «Europe/Moscow»
  48. PMA_HOST: laravel_db
  49. UPLOAD_LIMIT: 50M
  50. ports:
  51. — 81:80

* сценарий создаст 4 контейнера:

  • laravel_nginx — веб-сервер, на базе nginx.
  • laravel_php — интерпретатор PHP.
  • laravel_db — сервер баз данных MariaDB.
  • laravel_pma — веб-инструмент для работы с базами данных MySQL/MariaDB.
5 — 18 Создаем контейнер веб-сервера nginx. В качестве образа используем одноименный nginx.
16 Конфигурационные файлы будут находится в каталоге nginx/conf.d хостовой машины (в каталоге с docker-compose.yml) и /etc/nginx/conf.d внутри контейнера.
17 Каталоги для хранения сертификатов.
18 Файлы веб-приложения — www_data на хосте docker и /usr/share/nginx/html внутри контейнера.
20 — 31 Контейнер с PHP.
21 — 22 Мы не будем брать готовый образ и сами соберем контейнер с использованием Dockerfile. Создание и описание последнего будет ниже в инструкции.
30 Как и для веб-сервера мы используем каталог www_data с рабочими файлами сайта, но пробрасываем их в каталог /var/www/html внутри контейнера.
31 Файл с настройками PHP.
33 — 45 Контейнер с базой данных MariaDB.
40 При инициализации СУБД будет создана база с именем laravel .
41 При инициализации базы будет создан пользователь с именем laravel .
42 Пароль пользователя laravel будет laravel123 .
43 Указываем пароль для суперпользователя root.
47 — 57 Контейнер с phpMyAdmin.
54 С помощью данной переменной окружения говорим, на каком контейнере запущена СУБД.
55 Разрешаем передачу файлов размером не более 50 Мб. По умолчанию ограничение в 2 Мб.
57 Обратите внимание, что данный контейнер мы вешаем на внешний 81 порт.

Создадим каталог для хранения Dockerfile — он нам нужен для сборки контейнера с PHP:

mkdir php

Создадим в данном каталоге файл Dockerfile:

vi php/Dockerfile

  1. FROM php:8.1-fpm
  2. MAINTAINER Dmitriy Mosk <master@remontka.com>
  3. ENV TZ=Europe/Moscow
  4. RUN apt update &&
  5. apt -y —no-install-recommends install libonig-dev libxml2-dev zlib1g-dev libzip-dev libcurl4-openssl-dev &&
  6. docker-php-ext-install mysqli bcmath mbstring xml ctype zip pdo_mysql curl filter

* с помощью данного файла будет собран контейнер с интерпретатором php и компонентом php-fpm, принимающим запросы на обработку скриптов.

1 В качестве базового образа берем php:8.1-fpm. Из его названия видно, что версия php будет 8.1. Меняем на версию, которая нужна, именно, вам, но не забываем сверить ее с документацией к Laravel .
7 — 9 Дополнительно установим php расширения, которые нужны для работы фреймворка. Данный список также можно найти на официальном сайте разработчика .

Создадим конфигурационный файл php.ini:

vi php/php.ini

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
short_open_tag = On
post_max_size = 1G
upload_max_filesize = 512M
date.timezone = «Europe/Moscow»

* где:

  • error_reporting — для продуктива лучше не отображать информацию об устаревших функциях (E_DEPRECATED), плохой совместимости кода (E_STRICT) и информации о потенциальных проблемах (E_NOTICE).
  • short_open_tag — позволяет использовать короткую нотацию для раскрытия блока код PHP.
  • post_max_size — максимальный объем данных, которые можно передать на сервер методом POST.
  • upload_max_filesize — максимальный объем загружаемого файла.
  • date.timezone — часовой пояс.

Создаем каталог:

mkdir -p nginx/conf.d

И создаем конфигурационный файл nginx для виртуального домена:

vi nginx/conf.d/default.conf

  1. server {
  2. listen 80 default_server;
  3. listen 443 ssl default_server;
  4. server_name _;
  5. location ~ /.well-known {
  6. root /usr/share/nginx/html;
  7. allow all;
  8. }
  9. if ($scheme = ‘http’) {
  10. return 301 https://$host$request_uri;
  11. }
  12. ssl_certificate /etc/nginx/ssl/laravel.localnet.crt;
  13. ssl_certificate_key /etc/nginx/ssl/laravel.localnet.key;
  14. root /usr/share/nginx/html/public;
  15. error_log /var/log/nginx/error.log;
  16. index index.php;
  17. location / {
  18. try_files $uri $uri/ /index.php?$query_string;
  19. gzip_static on;
  20. }
  21. location ~ .php$ {
  22. set $root_path /var/www/html/public;
  23. fastcgi_pass laravel_php:9000;
  24. fastcgi_index index.php;
  25. fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
  26. include fastcgi_params;
  27. fastcgi_param DOCUMENT_ROOT $root_path;
  28. }
  29. }

* данный файл описывает поведение и ответ веб-сервера nginx при обращении к nginx.

2 — 3 Сервер будет слушать на портах 80 и 443. Обратите внимание, что описываемая конфигурация является конфигурацией по умолчанию, то есть, если обращение идет не на конкретный или несуществующий виртуальный домен, то будет применяться, именно, она.
5 Указывает, для какого домена будет действовать данная настройка. В нашем примере это домен по умолчанию, поэтому пишем просто _.
7 — 10 Данная настройка понадобится, если мы захотим получить бесплатный сертификат от Let’s Encrypt.
12 — 14 Перенаправляет запросы с http на https.
16 — 17 Пути до файлов сертификатов. Необходимы для работы https.
30 — 37 Данный блок описывает поведение nginx при обработке файлов с расширением php. В нашем примере запросы будут передаваться контейнеру laravel_db.

Создаем каталог для хранения сертификатов:

mkdir nginx/ssl

Генерируем самоподписанные сертификаты:

openssl req -new -x509 -days 1461 -nodes -out nginx/ssl/laravel.localnet.crt -keyout nginx/ssl/laravel.localnet.key -subj «/C=RU/ST=SPb/L=SPb/O=Global Security/OU=IT Department/CN=laravel.localnet/CN=www.laravel.localnet»

* данная команда сформирует ключи laravel.localnet.crt и laravel.localnet.key в каталоге nginx/ssl относительно нашей рабочей папки.

Для тестирования веб-сервера нам будет достаточно самозаверенного сертификата. На него будет ругаться браузер, но с игнорирование предупреждения, портал можно будет открыть.

Для продуктивной среды лучше получить сертификаты от доверенного центра (купить или получить бесплатно от Let’s Encrypt).

Сценарий для развертывания веб-сервера готов.

Запуск и тестирование веб-сервера

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

docker-compose up -d

Запуск контейнеров займет какой-то время. Ждем.

Создадим файл:

vi www_data/index.php

<?php

phpinfo();

?>

Можно проверить работу сервера из командной строки:

curl -k https://127.0.0.1

Мы должны получить ответ в виде html-страницы с параметрами PHP.

Того же самого эффекта можно добиться в браузере, перейдя по адресу https://<IP-адрес хоста docker>. При получении предупреждения безопасности, игнорируем его.

Установка и настройка Laravel

Мы подготовили сервер, теперь установим и запустим Laravel.

Смотрим образы с названием laravel, которые есть в системе:

docker images | grep laravel

Нам нужен образ для php. В нашем случае, название будет:

laravel-laravel_php

На основе найденного образа запустим контейнер:

docker run —rm -it -v ./www_data:/var/www/html laravel-laravel_php bash

* данный контейнер будет удален после работы с ним.

Скачаем php composer и установим его в каталог /usr/local/bin:

# curl -sS https://getcomposer.org/installer | php — —install-dir=/usr/local/bin —filename=composer

Проверим, что композер установлен:

# composer —version

Удалим ранее созданный файл index.php:

# rm -f index.php

С помощью php composer создадим новый проект laravel:

# composer create-project laravel/laravel ./

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

Сгенерируем ключ приложения Laravel:

# php artisan key:generate —ansi

* данный ключи будет использоваться для защиты сеансов пользователя.

Выставим владельца www-data для файлов в текущем каталоге:

# chown -R www-data:www-data ./

Выходим из контейнера:

# exit

Откроем теперь файл конфигурации:

vi www_data/.env

Найдем секцию настройки подключения к СУБД mysql и зададим нужные значения:


DB_CONNECTION=mysql
DB_HOST=laravel_db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=laravel123

* где:

  • DB_HOST — имя контейнера СУБД.
  • DB_DATABASE — имя созданной базы данных.
  • DB_USERNAME — логин для подключения к СУБД.
  • DB_PASSWORD — пароль пользователя DB_USERNAME.

Почистим старый кэш и создадим новый:

docker-compose exec laravel_php php artisan config:cache

Мы можем увидеть что-то на подобие:

Configuration cache cleared!
Configuration cached successfully!

Проверяем, что фреймворк может работать с базой, выполнив незавершенные миграции:

docker-compose exec laravel_php php artisan migrate

Мы должны увидеть что-то на подобие:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.03 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.03 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)

Пробуем подключиться к порталу, перейдя по ссылке https://<IP-адрес хоста docker> . Если браузер выкинет предупреждение безопасности из-за самоподписанного сертификата, игнорируем, продолжая загрузку страницы.

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

В итоге, мы должны увидеть страницу Laravel:

Laravel поднят.

Сертификат от Let’s Encrypt

Ранее мы настроили веб-сервер с самоподписанным сертификатом, но в рабочей среде нам нужен сертификат, которому доверяют многие системы. Проще всего использовать бесплатный сертификат от Let’s Encrypt. Для его получения сначала открываем наш файл docker-compose:

vi docker-compose.yml

И добавляем новый volume для контейнера laravel_nginx:

services:

laravel_nginx:

volumes:

— ./nginx/well-known/:/usr/share/nginx/html

* мы пробрасываем внутрь контейнера каталог nginx/well-known .

Теперь можно запустить команду:

docker run -it —rm —name certbot -v «/opt/laravel/nginx/ssl:/etc/letsencrypt» -v «/opt/laravel/nginx/well-known:/usr/share/nginx/html» certbot/certbot certonly —webroot —agree-tos —email postmaster@remontka.com —webroot-path /usr/share/nginx/html/ -d remontka.com -d www.remontka.com

* данная команда создаст временный контейнер, который запросит сертификат для домена remontka.com и его поддомена www.remontka.com . В качестве каталога, где будет размещен временный файл проверки будет использоваться /usr/share/nginx/html , который является каталогом /opt/laravel/nginx/well-known на хосте docker и также смотри в папку /usr/share/nginx/html внутри веб-контейнера laravel_nginx.

Если настройка выполнена верно, мы должны получить файлы сертификата, которые будут находиться в каталоге /opt/laravel/nginx/ssl/live/remontka.com . Пропишем новые сертификаты:

vi nginx/conf.d/remontka.com.conf

ssl_certificate /etc/nginx/ssl/live/remontka.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/remontka.com/privkey.pem;

Перечитаем конфигурацию веб-сервером. Сначала проверим ее:

docker exec laravel_nginx nginx -t

И если ошибок нет:

docker exec laravel_nginx nginx -s reload

Для продления сертификата используем команду:

docker run -it —rm —name certbot -v «/opt/laravel/nginx/ssl:/etc/letsencrypt» -v «/opt/laravel/nginx/well-known:/usr/share/nginx/html» certbot/certbot renew

Читайте также

Дополнительная информация по работе с docker и веб-серверами:

1. Создание собственного образа Docker .

2. Настройка веб-сервера в Docker (NGINX + PHP + MariaDB) .

3. Шпаргалка по работе с docker-compose .

4. Docker-compose для создания nginx entrypoint .

admin

Share
Published by
admin

Recent Posts

Что такое Zulip

Zulip — программное обеспечение для реализации корпоративного чата. Разработан в 2012 году, в 2014 был…

2 месяца ago

Что такое Zookeeper

Zookeeper — cервис-координатор, который позволяет обеспечить контроль синхронизации данных. Разработан на Java компанией Apache Software…

2 месяца ago

Что такое Zimbra

Zimbra — программное обеспечение для реализации почтового сервиса или, если сказать точнее, автоматизации совместной деятельности…

2 месяца ago

Что такое Zabbix

Zabbix — бесплатная система мониторинга. Позволяет отслеживать состояние сетевых узлов, компьютеров и серверов. Возможности: Поддержка…

2 месяца ago

Что такое YouTube

YouTube — компания-владелец одноименного портала для просмотра и хранения видео. Чтобы пользоваться данным порталом достаточно…

2 месяца ago

Что такое yota

Yota — провайдер, предоставляющий доступ к сети Интернет по беспроводной связи. Впервые, сервис начал работать…

2 месяца ago