Запуск проекта на Laravel с использованием docker-compose

https://github.com/maxyc/laravel-tickets/blob/master/docker-compose.yml

Данная конфигурация кочует со мной из проекта в проект

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

  • php-fpm 7.4+ with xdebug
  • mysql | postgresql | sqlite
  • nginx | apache
  • redis | … etc…

Давайте попробуем на примере php-fpm 7.4 + mysql + nginx

Создадим папку нашего проекта /var/www/example.loc/ и создадим в ней файл docker-compose.yml, также нам понадобится папка ./docker где будем хранить конфигурации наших сервисов.

Внутренняя сеть

В нашей сборке ничего, кроме nginx не будет смотреть наружу. Ни какие порты, кроме 80. Нам не требуется извне иметь доступ к 9000 порту php или 3306 бд. Все контейнеры будут залинкованы между собой внутренней сетью, которую можно описать следующим образом:

networks:
  internal:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.220.0/28

База данных

db:
    image: mysql
    restart: always
    command: --default-authentication-plugin=mysql_native_password
    networks:
      - internal
    environment:
      - MYSQL_DATABASE=${DB_DATABASE}
      - MYSQL_USER=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
    volumes:
      - ./docker/mysql/datadir:/var/lib/mysql

Нам необходимо в корне папки создать файл .env, в котором будут наши настройки БД

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=user
DB_PASSWORD=123456

Эти данные в дальнейшем будут в .env файле нашего проекта на Laravel.

Стоит обратить внимание на DB_HOST=db. Здесь нельзя указывать localhost или еще какой ip. За счет удобной внутренней сети докера мы можем использовать имя сервиса в качестве пути к серверу базы данных. в нашем случае это db

Т.к. после перезапуска контейнера все данные удаляются, то нам необходимо вынести файлы таблиц базы данных. Поэтому помещаем их в папку docker/mysql

volumes:
- ./docker/mysql/datadir:/var/lib/mysql

Если вдруг вам потребуется mariadb, то вместо image: mysql, впишите image: mariadb. Конфигурация остается та же.

А что, если мы захотим использовать postgresql? Все так же просто:

db:
  image: postgres
  restart: always
  networks:
    - internal
  environment:
    - POSTGRES_DB=${DB_DATABASE}
    - POSTGRES_USER=${DB_USERNAME}
    - POSTGRES_PASSWORD=${DB_PASSWORD}
  volumes:
    - ./docker/postgres/datadir:/var/lib/postgresql/data

С базами данных закончили.

php-fpm

Будем использовать кастомную сборку php-fpm, т.к. нам необходимо добавить поддержку работы с базой данных, поддержку xdebug и пр.

Для начала опишем сервис. Условимся, что наш docker-compose.yml и папка docker будет лежать в корне laravel проекта на одном уровне с папкой app

php-fpm:
    build:
      context: docker/php-fpm
    volumes:
      - ./:/var/www
    environment:
      XDEBUG_CONFIG: "remote_host=192.168.220.1 remote_enable=1"
      PHP_IDE_CONFIG: "serverName=Docker"
    depends_on:
      - db
    networks:
      - internal

Т.к. наша сборка кастомная, то вместо image секции, нам необходимо указать путь к настройкам:

build:
context: docker/php-fpm

Создаем папку ./docker/php-fpm и в ней два файла php.ini и Dockerfile, в котором далее будем описывать процесс сборки php-fpm

В php.ini мы можем указать желаемые нами параметры, например:

max_execution_time = 1000
max_input_time = 1000

error_reporting=E_ALL
display_errors=on

short_open_tags=off

Перейдем к Dockerfile. В этом файле (с большой буквы) хранятся построчно все инструкции по установке php внутри контейнера.

FROM php:7.4-fpm

RUN apt-get update \
    && apt-get install -y wget git unzip libpq-dev libicu-dev libpng-dev libzip-dev libjpeg-dev libfreetype6-dev\
    && pecl install xdebug-2.9.1 \
    && docker-php-ext-enable xdebug \
    && docker-php-ext-install pdo_pgsql \
    && docker-php-ext-install pgsql \
    && docker-php-ext-install zip \
    && docker-php-ext-install gd \
    && docker-php-ext-enable pgsql

ADD ./php.ini /usr/local/etc/php/php.ini

RUN wget https://getcomposer.org/installer -O - -q \
    | php -- --install-dir=/bin --filename=composer --quiet

USER 1000

WORKDIR /var/www

В первой строке (команда FROM) мы указали какую версию image файла нам использовать. В данном случае php:7.4-fpm

Следующая команда RUN устанавливает требуемые зависимости

Далее, мы указываем контейнеру, что php.ini необходимо брать из нашей текущей папки.
Далее, Устанавливаем composer. Он нужен нам только на уровне php-fpm контейнера.

Ну и наконец указываем контейнеру, где лежат все наши файлы со стороны контейнера. В нашем случае, мы указали, что корень нашего сервера это /var/www

Вы можете с легкостью указать любую другую версию php, например php:7.3-fpm, но учтите, для этой версии может потребуется xdebug более низкой версии, например 2.7.1

Nginx

nginx:
    build:
      context: docker/nginx
    volumes:
      - ./:/var/www/
      - ./storage/app/public/:/var/www/public/storage/
    ports:
      - 80:80
    depends_on:
      - php-fpm
    networks:
      - internal

Обратите внимание, что папку storage мы пробрасываем на уровне конфигурации. Симлинки не работают между контейнерами. В нашем случае nginx и php-fpm

Nginx у нас так же имеет кастомную сборку, потому указываем путь к файлу Dockerfile как в прошлом примере.

Создаем папку ./docker/nginx и там файл Dockerfile и папку conf.d
В conf.d у нас будут храниться виртуальные хосты, обычно 1-2 достаточно. Обрабатываются только файлы с расширением .conf. Например, default.conf:

server {
    charset utf-8;
    client_max_body_size 128M;

    listen 80; ## listen for ipv4

    server_name example.loc localhost;
    root /var/www/public;
    index       index.php;

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

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        fastcgi_read_timeout 1000;
        #fastcgi_pass unix:/var/run/php5-fpm.sock;
        try_files $uri =404;
        #fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location ~* /\. {
        deny all;
    }
}

Настроим Dockerfile следующим образом:

FROM nginx

ADD ./conf.d /etc/nginx/conf.d/

WORKDIR /var/www

На этом настройка окружения для нашего проекта закончена. Нам остается только запустить контейнеры командой

docker-compose up -d --build

Если все ок, то наше приложение теперь доступно по адресу http://localhost

Одна из возможных причин, почему не запустилось, может крыться в том, что 80 порт может быть уже занят. В любом случае, понять причину ошибки можно запустив команду docker-compose logs и проанализировав ее.

Установка Laravel

Предположим, что мы разворачиваем фреймфорк впервые на машине, где не установлен php. Для того, чтобы установить фреймворк, нам необходимо скачать его командой

git clone https://github.com/laravel/laravel.git laravelapp

И скопировать все файлы в папке laravelapp в корень нашего сервера.

Для того, чтобы можно было использовать artisan, нам необходимо обращаться к нему внутри контейнера, а именно docker-compose exec php-fpm php artisan make:controller, либо запускать команды внутри контейнера запустив команду docker-compose exec php-fpm bash, а затем уже использовать php artisan make:controller

Часто у новичков и не только, у кого локально установлен php? возникает ошибка подключения к базе данных, при использовании команд artisan. Для решения которой, как бы не было это глупо и банально, предлагаю проверить как вы запускаете команду. Возможно вы запускаете ее локально, а не в контейнере. =)

Рейтинг
( Пока оценок нет )
Maxyc Webber/ автор статьи
Мне 35 лет. Опыт профессиональной разработки 15 лет. Занимаюсь разработкой и поддержкой корпоративных систем автоматизации бизнеса, а также высоконагруженными проектами. Мне нравится решать нестандартные проблемы бизнеса. Имею опыт формирования команд под проект, налаживания процесса разработки, коммуникации программистов и заказчиков. Есть опыт работы с зарубежными заказчиками (ОАЭ, Польша, Германия, Швейцария).
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.