# Запуск Laravel-приложения в Docker-Compose
Docker-контейнеры — способ запуска приложений. Они создают полностью изолированную среду разработки и позволяют запускать внутри себя сложные и требовательные к зависимостям приложения, при этом не устанавливая ничего на сам сервер — все манипуляции производятся исключительно внутри контейнеров.
Docker Compose — следующий шаг в развитии docker-контейнеров. Это приложение позволяет запустить одновременно несколько контейнеров и объединить их во внутреннюю сеть, которая будет поддерживаться Docker. Это бывает удобно, когда приложение использует не только фреймворк своего языка программирования, но и базу данных и веб-сервер для работы в сети.
В этой инструкции мы рассмотрим запуск Laravel-приложения c помощью Docker Compose.
Для начала работы нам понадобятся подготовленный к работе сервер под управлением Ubuntu, установленный Docker и установленный Docker Compose.
Мы будем запускать приложение, созданное Digital Ocean для своих образовательных нужд. Принцип запуска любого другого приложения, которое вы создадите и клонируете в один из общедоступных репозиториев, не будет отличаться.
# Скачивание приложения
Для начала работы нам понадобится загрузить файлы проекта с github на сервер:
curl -L https://github.com/do-community/travellist-laravel-demo/archive/tutorial-1.0.1.zip -o travellist.zip
Это приложение, которое хранит в базе список мест, которые мы посетили и которые хотели бы посетить.
Вышеуказанной командой мы скачали архив с приложением в текущую папку и сразу переименовали его в travellist.zip.
Теперь нам нужно установить программу для разархивирования:
sudo apt update
sudo apt install unzip
Следующим шагом распакуем наш архив и переименуем папку, в которую его помещаем, чтобы в дальнейшем с ней было удобнее работать:
unzip travellist.zip
mv travellist-laravel-demo-tutorial-1.0.1 travel
После этого можно переходить к настройке переменных среды нашего приложения.
# Настройка переменных среды
По умолчанию файлы с настройками переменных среды хранятся в папках Laravel-приложений в директории config. Мы создадим отдельный файл, который будет скрыт от просмотра и расположен в основной директории проекта. Наше скачанное приложение идёт с файлом настроек. Скопируем его, чтобы на его основе можно было создать новый файл с настройками:
cp .env.example .env
Теперь откроем его для редактирования в текстовом редакторе:
vim .env
В открывшемся файле нужно найти раздел, отвечающий за подключение к базе данных. Он должен выглядеть примерно так:
APP_NAME=travel
APP_ENV=dev
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost:8000
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=travel_list
DB_USERNAME=travel_list_user
DB_PASSWORD=password
…
Здесь:
APP_URL
— адрес, по которому будет доступно наше приложение в сети, когда будет запущено;DB_HOST
— адрес базы данных для внутреннего обращения — обратите внимание, что по умолчанию он указан 127.0.0.1, но поскольку мы будем запускать приложение через Compose, нужно указать здесь параметр db, как один из контейнеров Docker Compose;DB_DATABASE
,DB_USERNAME
иDB_PASSWORD
— их вы можете изменить по своему усмотрению, они будут переданы и назначены в указанном виде.
# Создание докерфайла
MySQL и Nginx для работы нашего приложения будут развёрнуты из стандартных образов, которые есть на DockerHub, но вот самому нашему приложению потребуются дополнительные зависимости и приложения. Их установку мы и опишем в докерфайле.
Создадим его:
vim dockerfile
В докерфайле мы обозначим, что устанавливать будем PHP:7.4-fpm, затем пропишем установку всех необходимых зависимостей для работы приложения, скопируем официальный образ Composer в качестве менеджера зависимостей для PHP и создадим рабочую директорию:
FROM php:7.4-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www
USER $user
# Настройка веб-сервера и базы данных
Мы создадим конфигурационные файлы для веб-сервера и базы данных внутри директории docker-compose:
mkdir -p /docker-compose/nginx
Флаг -p
здесь указывает на то, что будет создана не только конечная папка, но и все, которые указаны в команде, но ещё не созданы.
В папке веб-сервера создадим конфигурационный файл:
vim travel.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;
}
}
Здесь мы указали, что Nginx будет «слушать» порт 80, что основным индексным файлом будет index.php, а основные документы приложения будут располагаться по адресу /var/www/public
. Также мы указали, что для работы с файлами php Nginx должен использовать порт 9000.
Это основные параметры веб-сервера. Теперь конфигурационный файл можно закрыть и перейти к настройкам базы данных.
Файл с настройками базы также будет лежать в папке /docker-compose. Создадим нужную папку:
mkdir docker-compose/mysql
Поместим в неё конфигурационный файл базы:
vim docker-compose/mysql/init_db.sql
Сюда мы поместим набор команд, добавляющих в наше приложение таблицу с посещёнными местами:
DROP TABLE IF EXISTS `places`;
CREATE TABLE `places` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`visited` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `places` (name, visited) VALUES ('Tokyo',0),('Budapest',0),('Verkhnyaa Sinyachikhai',1),('Strassbourg',0),('Penza',1),('Serov',1),('Nevyansk',1),('Nairobi',0),('Edinburg',1),('Kirovgrad',1),('Alapayevsk',0);
В таблице places в данном случае будет три столбца: порядковый номер, место и факт посещения места.
Когда вы заполните таблицу своими данными, можно будет переходить к созданию Docker Compose-файла.
# Создание Docker Compose — файла
Docker Compose настраивается быстро — вся конфигурация системы контейнеров (какие образы скачивать, по каким портам соединяться с сетью, какой контейнер от какого зависит и т.д.) указываются в одном файле. Этот файл — docker-compose.yml — мы сейчас и создадим:
vim docker-compose.yml
Сначала мы добавим в compose-файл первые и последние строки файла: в первых строках указывается версия Docker Compose, которая будет использована, в последних — описывается внутренняя сеть, которая будет создана для связи контейнеров между собой: указывается имя сети и её тип. В нашем случае начало и конец compose-файла будут выглядеть так:
version: "3.7"
services:
networks:
travel:
driver: bridge
Здесь мы указали, что будем использовать версию 3.7 Docker Compose, внутренняя сеть будет называться travel и будет использоваться для связи контейнеров — параметр bridge.
После этого переходим к описанию непосредственно контейнеров, которые будут созданы при запуске приложения, и указанию их свойств и зависимостей.
# Описание приложения
Чтобы описать приложение в compose-файле, после строки services:
добавим блок описания нашего приложения:
app:
build:
args:
user: User
uid: User_id
context: ./
dockerfile: dockerfile
image: travellist
container_name: travel-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- travel
Важно проконтролировать значения в строках user
и uid
— здесь мы указываем пользователя, от чьего имени будет запускаться приложение. Это должен быть ваш системный пользователь. ID всех существующих на сервере пользователей можно посмотреть командой getent passwd
.
В строке dockerfile
указываем имя нашего докер-файла (обратите внимание — этот параметр чувствителен к регистру), а в networks
— имя нашей внутренней сети, которое мы создали на первом шаге.
# Описание базы данных
Отделим предыдущий раздел пустой строкой и создадим описание базы данных, которая будет работать с приложением:
…
db:
image: mysql:5.7
container_name: travellist-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- travel
…
Здесь в строке image
мы указываем, какую конкретно версию MySQL должен будет скачать Docker Compose при старте. Параметр volumes
создаёт общий том, к которому будет доступ у всех контейнеров — это важно, потому что доступ к базе данных должен быть как у самого приложения, так и у веб-сервера.
Остальные строки копируют переменные среды из конфигурационного файла базы данных и приложения (блок environment
) и определяют внутреннюю сеть, в которой будет работать контейнер (networks
).
В конце добавим блок, отвечающий за работу веб-сервера.
# Настройка веб-сервера
Перед запуском Docker Compose нам осталось только описать контейнер, отвечающий за работу веб-сервера. Добавим информацию о веб-сервере в compose-файл после описания приложения и базы данных:
…
nginx:
image: nginx:1.17-alpine
container_name: travellist-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d
networks:
- travellist
…
Здесь мы также указываем версию образа Nginx, которую хотим использовать, имя контейнера, порты, на которых будет работать веб-сервер, и описываем тома — общие папки, с которыми будут работать контейнеры.
Наш compose-файл готов, можно переходить к запуску приложения.
# Запуск приложения
Вводим команду:
docker compose build app
После этого стартует длительный процесс запуска приложения: Docker Compose будет скачивать все необходимые приложения, образы и зависимости, создавать контейнеры для приложений и внутреннюю сеть для их работы. По завершении работ на экран будет выведено сообщение:
# Output
Build complete.
Don't forget to run 'make test'.
…
Successfully built 44a6f75243be
Successfully tagged travel:latest
После завершения создания можно запустить работу приложения в фоновом режиме:
docker-compose up -d
Теперь проверим, что приложение запущено. Например, проверим список доступных контейнеров:
docker compose ps
# Output
NAME COMMAND SERVICE STATUS PORTS
travellist-app "docker-php-entrypoi…" app running 9000/tcp
travellist-db "docker-entrypoint.s…" db running 33060/tcp
travellist-nginx "/docker-entrypoint.…" nginx running 0.0.0.0:8000->80/tcp, :::8000->80/tcp
Далее установим менеджер зависимостей Composer, который будет поддерживать в актуальном состоянии все существующие зависимости нашего приложения:
docker compose exec composer update laravel/framework
docker compose exec composer install
Перед запуском приложения нам осталось только сгенерировать ключ, который будет шифровать все данные:
docker-compose exec app php artisan key:generate
Теперь можно заходить в браузер по адресу your_server_ip:8000
и проверять работу приложения.
Если ваш VPS расположен на Джино, и вы не используете выделенный IP, то в адресной строке браузера нужно указывать технический адрес вашего сервера. Порт для подключения нужно перенаправить. В разделе УправлениеПеренаправление портов создайте перенаправление для порта 8000 и укажите новый номер порта в адресной строке браузера после указания технического адреса.
Если всё было сделано правильно, вы увидите 2 списка мест — которые вы уже посетили и хотите посетить.
# Завершение работы Docker Compose
Приостановить работу вашего приложения можно командой pause
, а возобновить её — обратной командой unpause
:
docker compose pause
docker compose unpause
Если вы хотите полностью остановить запущенное приложение, введите команду down
:
docker compose down
Мы изложили основы работы с Docker Compose при запуске приложений. Опираясь на эту инструкцию, вы можете переходить к самостоятельной разработке приложений и их запуску в Docker Compose.