Разработка на Laravel с Docker. Часть 1



enter image description here
Одна из проблем, с которыми сталкивается каждая команда разработчиков - управление локальной средой разработки. Такие инструменты, как Vagrant в прошлом облегчили этот процесс, но работая с тяжелой ВМ они могут отнять много времени и ресурсов вашего компьютера.

Laravel является отличным PHP фреймворком для создания веб-приложений, кроме того он обеспечивает официальную поддержку некоторых решений, таких как Homestead и Valet. Но что, если вы хотите получить более тотальный контроль над локальным окружением, не обременяя себя управлением виртуальными машинами?
Вот здесь то нам и понадобится Docker!

Docker обеспечивает возможность создания и запуска легковесных контейнеров для любой службы, которая вам потребуется. Необходимо внести изменения в конфигурации PHP-FPM? Хотите изменить используемую версию PHP?
С Docker вы можете уничтожить всю локальную среду, перенастроить её и вернуть всё обратно в считанные секунды. tldr; Если вы просто хотите увидеть работающий пример кода на базе Laravel с установленным Docker - вот ссылка на репозиторий. В конце статьи есть GIF с примером того, как быстро вы можете уничтожить и восстановить всё окружение :)

Из-за интеграции Laravel со многими другими технологиями (MySQL, Redis, Memcached и т.д.), начальное конфигурирование может оказаться немного сложнее. Моя цель заключается в том, чтобы обеспечить высокий уровень понимания запуска приложений с Docker.

Установка Laravel

Для нашей цели подойдет установленный Laravel или Lumen. Если у вас уже есть приложение, вы можете пропустить этот шаг. Мы будем использовать установщик Laravel для быстрого создания нового приложения:
$ laravel new dockerApp
Application ready! Build something amazing.
Мы быстро можем проверить правильно ли установилось наше приложение с помощью встроенного сервера:
$ cd dockerApp
$ php artisan serve
enter image description here

Установка Docker

Docker доступен на платформах Mac, Windows и Linux. Выберите нужную платформу, а затем нажмите на неё, что бы чтобы установить определенную версию Docker. После этого у вас установится Docker, а также Docker Compose, который мы так же будем использовать.
После установки вы сможем запускать команды Docker:
$ docker –version
Docker version 1.12.0, build 8eab29e
$ docker-compose –version
docker-compose version 1.8.0, build f3628c7
$ docker ps
CONTAINER ID IMAGE COMMAND …
Если docker ps возвратил ошибку, убедитесь, что запущен демон Docker. Возможно, вам потребуется открыть Docker и запустить его вручную.
enter image description here

Локальная среда c Docker

Теперь самое интересное :) Скорее всего у вас есть установленная среда PHP, и, вероятно, вы знакомы с управлением веб-сервера (например, Apache или Nginx) в связке с PHP.

С Docker мы создаем контейнеры, в идеале предназначенные для какой-то единственной цели или вещи. Поэтому мы создадим один контейнер, который работает с Nginx для обработки веб-запросов, а другой контейнер для PHP-FPM, который будет обрабатывать запросы приложений. Концепция разделения двух этих вещей может показаться чем то странным, но именно она и реализует ту самую гибкость, которой славится Docker.

Вот краткий обзор того, что мы будем создавать.
enter image description here
Наши два контейнера cвязаны, таким образом они cмогут взаимодействовать друг с другом. Мы укажем точку для поступающего трафика на контейнер Nginx, который будет обрабатывать HTTP запросы, затем при необходимости связываться с PHP контейнером, который будет возвращать ответ.

Мы будем использовать Docker Compose, который облегчит задачу создания среды, что бы у нас не было необходимости каждый раз вручную создавать контейнеры. В корневом каталоге проекта добавим файл с названием docker-compose.yml:
    version: '2'
    services:
        web:
            build:
                context: ./
                dockerfile: web.docker
            volumes:
                - ./:/var/www
            ports:
                - "8080:80"
            links:
                - app
        app:
            build:
                context: ./
                dockerfile: app.docker
            volumes:
                - ./:/var/www
Если в кратце, здесь происходит следующее:
  • были объявлены 2 сервиса с названиями web и app
  • эти сервисы содержат в себе build, где устанавливается корневая директория для контекста, а так же перечисляются названия Dockerfiles, которые говорят Docker, как создавать контейнеры (мы создадим эти файлы ниже)
  • оба сервиса устанавливают /var/www как директорию для
    контейнеров
  • в web мы определяем порт нашей машины 8080, а так
    же указываем порт для контейнеров 80. Через него мы будем
    подключаться к нашему приложению. Вы можете изменить 8080 на любой предпочтительный порт.
  • web контейнер содержит “ссылку” на app контейнер. Это позволит ссылаться на app, как на хост для веб-контейнера, и Докер автоматически будет маршрутизировать трафика на этот контейнер
Вы можете найти больше информации о Docker Compose здесь, если хотите глубже его изучить.

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

Мы будем следовать стандартной конвенции именования Dockerfile файлов, которая приходится мне по душе - [service].docker. Создадим два файла в корневой директории проекта:
app.docker
FROM php:7-fpm

    RUN apt-get update && apt-get install -y libmcrypt-dev mysql-client \
        && docker-php-ext-install mcrypt pdo_mysql

    WORKDIR /var/www

web.docker
FROM nginx:1.10

    ADD ./vhost.conf /etc/nginx/conf.d/default.conf
    WORKDIR /var/www
С помощью dockerfile мы создаём базовый образ app, который использует официальный образ PHP с Docker Hub. Уже здесь мы можем увидеть одну из удивительных возможностей Docker. Если вы хотите использовать другую версию PHP - просто измените её в базовом образе, к примеру: php:5.6-fpm.

Затем мы запускаем пару команд шелла для установки расширения mcrypt (который в данный момент является зависимостью Laravel) и клиент MySQL, который мы будем использовать позже для нашей базы данных.

Контейнер web просто расширяет официальный образ Nginx и добавляет к контейнеру конфигурационный Nginx файл vhost.conf в /etc/nginx/conf.d. Теперь нам нужно создать этот файл.
vhost.conf
server {
        listen 80;
        index index.php index.html;
        root /var/www/public;

        location / {
            try_files $uri /index.php?$args;
        }

        location ~ \.php$ {
            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;
        }
    }
Это довольно стандартная конфигурация Nginx, которая будет обрабатывать запросы и проксировать трафик в наш PHP контейнер (через приложение name на порт 9000). Вспомните, как ранее мы назвали наш сервис app в Docker Compose и ссылались на него из контейнера web, теперь Docker просто ссылается на это имя, зная, что трафик нужно маршрутизировать в контейнер app. Довольно аккуратное решение!

Мы прошли неплохой путь. В корне проекта выполним команду:
$ docker-compose up -d
Она запускает контейнеры Docker в фоновом режиме. В первые, когда вы запускаете, загрузка двух базовых образов может занять несколько минут, потом она будет проходить намного быстрее. Теперь мы можем посмотреть на наше приложение на http://localhost:8080:
enter image description here
Ура! Вот некоторые команды, которые могут вам пригодиться, чтобы взаимодействовать с контейнерами:
$ docker-compose up -d # start containers in background
$ docker-compose kill # stop containers
$ docker-compose up -d –build # force rebuild of Dockerfiles
$ docker-compose rm # remove stopped containers
$ docker ps # see list of running containers
$ docker exec -ti [NAME] bash
Последняя команда служит для открытия SSH в ВМ. Вы можете получить имя контейнера с помощью docker ps, а затем использовать exec команду для открытия интерактивной bash сессии в контейнере.

Ссылка на оригинальную статью