Как стать автором
Обновить

Среда разработки PHP на базе Docker

Время на прочтение 12 мин
Количество просмотров 55K

Решение, которое позволит создать на локальном компьютере универсальную среду разработки на PHP за 30 — 40 минут.

Почему Docker?

  • Docker не является VM-системой, он не моделирует аппаратное обеспечение компьютера. Используя Docker вы получите минимальное потребление ресурсов. Docker-контейнеры взаимодействуют напрямую с ядром вашего компьютера (или ядром хоста), но при этом изолируют программу на уровне процесса.

  • Высокая скорость развертывания. Вы можете использовать готовые docker-образы, которые устанавливаются и запускаются за секунды.

  • Приложения, находящееся внутри docker-контейнеров, можно запустить на любом компьютере с установленным Docker, при этом окружение будет одинаковым.

  • Возможность простой сегрегации пользовательских данных и контейнеров-сервисов. Если вы сломаете или удалите docker-контейнер, то данные не потеряются, так как они не будут принадлежать контейнеру. Контейнер выполняет лишь функцию сервиса, и не хранит данные, которые нельзя потерять между запусками.

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

Требования

  • Git.

  • Docker engine 19.x и выше.

Возможности и особенности среды разработки 

  • Несколько версий PHP — 7.3 и 7.1 с набором наиболее востребованных расширений.

  • Возможность использовать для web-проектов разные версии PHP.

  • Готовый к работе монитор процессов Supervisor.

  • Предварительно сконфигурированный веб-сервер Nginx.

  • Базы данных: MySQL 5.7MySQL 8PostgreSQL (latest), MongoDB 4.2Redis (latest).

  • Настройка основных параметров окружения через файл .env.

  • Возможность модификации сервисов через docker-compose.yml.

  • Последняя версия docker-compose.yml.

  • Все docker-контейнеры базируются на официальных образах.

  • Структурированный Dockerfile для создания образов PHP.

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

В целом, среда разработки удовлетворяет требованию — при использовании Docker каждый контейнер должен содержать в себе только один сервис.

Репозиторий проекта

https://github.com/drandin/docker-php-workspace

Структура проекта 

Рассмотрим структуру проекта.

├── .env-example
├── .gitignore
├── .ssh
├── README.md
├── docker-compose.yml
├── mongo
├── mysql-5.7
├── mysql-8
├── nginx
├── php-ini
├── php-workers
├── php-workspace
├── postgres
├── projects
└── redis

Примечание

В некоторых каталогах можно встретить пустой файл .gitkeep. Он нужен лишь для того, чтобы была возможность добавить каталог под наблюдение Git.

.gitkeep — является заполнением каталога, это фиктивный файл, на который не следует обращать внимание.

.env-example 

Пример файла с основными настройками среды разработки.

# Временная зона
WORKSPACE_TIMEZONE='Europe/Moscow'

# XDEBUG
DOCKER_PHP_ENABLE_XDEBUG='on'

# Настройки Nginx
# Порт, который следует использовать
# для соединения с локального компьютера
NGINX_PORT=80

# Настройки Redis
# Порт, который следует использовать
# для соединения с локального компьютера
REDIS_PORT=6379
# Настройки Postgres
POSTGRES_DB=test
POSTGRES_USER=pg_user
POSTGRES_PASSWORD=secret
POSTGRES_PORT=54322

# Настройки общие для MySQL 8.x и MySQL 5.7.x
MYSQL_ROOT_PASSWORD=secret
MYSQL_DATABASE=test

# Настройки MySQL 8.x
# Порт, который следует использовать
# для соединения с локального компьютера
MYSQL_8_PORT=4308

# Настройки MySQL 5.7.x
# Порт, который следует использовать
# для соединения с локального компьютера
MYSQL_5_7_PORT=4307

# Настройки MongoDB
# Порт, который следует использовать
# для соединения с локального компьютера
MONGO_PORT=27017

# Настройки PHP 7.3
# Внешний порт, доступен с локального компьютера
PHP_7_3_PORT=9003

# Настройки PHP 7.1
# Внешний порт, доступен с локального компьютера
PHP_7_1_PORT=9001

.gitignore

Каталоги и файлы, в которых хранятся пользовательские данные, код ваших проектов и ssh-ключи внесены в. gitignore.

.ssh 

Этот каталог предназначен для хранения ssh-ключей.

readme.md 

Документация.

docker-compose.yml 

Документ в формате YML, в котором определены правила создания и запуска многоконтейнерных приложений Docker. В этом файле описана структура среды разработки и некоторые параметры необходимые для корректной работы web-приложений.

mongo 

Каталог базы данных MongoDB.

├── configdb
│   └── mongo.conf
├── db
└── dump

mongo.conf — Файл конфигурации MongoDB. В этот файл можно добавлять параметры, которые при перезапуске MongoDB будут применены.

db — эта папка предназначена для хранения пользовательских данных MongoDB.

dump — каталог для хранения дампов.

mysql-5.7 

Каталог базы данных MySQL 5.7.

├── conf.d
│   └── config-file.cnf
├── data
├── dump
└── logs

config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 5.7 будут применены.

data — эта папка предназначена для хранения пользовательских данных MySQL 5.7.

dump — каталог для хранения дампов.

logs — каталог для хранения логов.

mysql-8 

Каталог базы данных MySQL 8.

├── conf.d
│   └── config-file.cnf
├── data
├── dump
└── logs

config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 8 будут применены.

data — эта папка предназначена для хранения пользовательских данных MySQL 8.

dump — каталог для хранения дампов.

logs — каталог для хранения логов.

nginx 

Эта папка предназначена для хранения файлов конфигурации Nginx и логов.

├── conf.d
│   ├── default.conf
│   └── vhost.conf
└── logs

default.conf — файл конфигурации, который будет применён ко всем виртуальным хостам.

vhost.conf — здесь хранятся настройки виртуальных хостов web-проектов.

Рассмотрим vhost.conf подробнее:

server {
    listen 80;
    index index.php index.html;
    server_name project-1.localhost;
    error_log /var/log/nginx/project-1.error.log;
    access_log /var/log/nginx/project-1.access.log combined if=$loggable;
    root /var/www/project-1.ru;

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-7.3:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
    }
}

server {
    listen 80;
    index index.php index.html;
    server_name project-2.localhost;
    error_log /var/log/nginx/project-2.error.log;
    access_log /var/log/nginx/project-2.access.log combined if=$loggable;
    root /var/www/project-2.ru;

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-7.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
    }
}

В файле конфигурации описаны настройки для двух web-проектов — project-1.localhost и project-2.localhost.

Здесь следует обратить внимание на то, как производится перенаправление запросов к нужному docker-контейнеру.

Например, для проекта project-1.localhost указано:

fastcgi_pass php-7.3:9000;

php-7.3 — название docker-контейнера, а 9000 — порт внутренней сети. Контейнеры между собой связаны через внутреннюю сеть, которая определена в файле docker-compose.yml.

php-ini 

В этом каталоге находятся файлы конфигурации PHP.

├── 7.1
│   └── php.ini
└── 7.3
    └── php.ini

Для каждой версии PHP — свой файл конфигурации.

php-workers 

Место для хранения файлов конфигурации Supervisor.

├── 7.1
│   └── supervisor.d
│       
└── 7.3
    └── supervisor.d

Для каждой версии PHP — могут быть добавлены свои файлы с настройками.

php-workspace 

Здесь хранится файл, в котором описаны действия, выполняемые при создании образов docker-контейнеров PHP.

└── Dockerfile

Dockerfile — это текстовый документ, содержащий все команды, которые следует выполнить для сборки образов PHP.

postgres

Каталог для системы управления базами данных PostgreSQL.

├── .gitkeep
├── data
└── dump

data — эта папка предназначена для хранения пользовательских данных PostgreSQL.

dump — каталог для хранения дампов.

projects 

Каталог предназначен для хранения web-проектов.

Вы можете создать в это каталоге папки, и поместить в них ваши web-проекты.

Например:

project-1.ru
project-2.ru 
...

Содержимое каталога projects доступно из контейнеров php-7.1 и php-7.3.

Если зайти в контейнер php-7.1 или php-7.3, то в каталоге /var/www будут доступны проекты, которые расположены в projects на локальной машине.

redis 

Каталог key-value хранилища Redis.

├── conf
└── data

conf — папка для хранения специфических параметров конфигурации.

data — если настройки конфигурации предполагают сохранения данных на диске, то Redis будет использовать именно этот каталог.

Программы в docker-контейнерах PHP 

Полный перечень приложений, которые установлены в контейнерах php-7.xможно посмотреть в php-workspace/Dockerfile.

Здесь перечислим лишь некоторые, наиболее важные:

  • bash

  • htop

  • curl

  • Git

  • Сomposer

  • make

  • wget

  • NodeJS

  • Supervisor

  • npm

Начало работы 

1. Выполните клонирование данного репозитория в любое место на вашем компьютере.

git clone https://github.com/drandin/docker-php-workspa

Перейдите в директорию, в которую вы клонировали репозиторий. Все дальнейшие команды следует выполнять именно в этой директории.

2. Скопируйте файл .env-example в .env

cp .env-example .env

Если это необходимо, то внесите изменения в файл .env. Измените настройки среды разработки в соответствии с вашими требованиями.

3. Выполните клонирование web-проектов в каталог projects.

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

project-1.ru
project-2.ru

project-1.ru — будет работать на версии PHP 7.3, а project-2.ru — на PHP 7.1.

4. Отредактируйте настройки виртуальных хостов Nginx.

Файл конфигурации виртуальных хостов находится в каталоге ./nginx/conf.d/.

5. Настройте хосты (доменные имена) web-проектов на локальной машине.

Необходимо добавить названия хостов web-проектов в файл hosts на вашем компьютере.

В файле hosts следует описать связь доменных имён ваших web-проектов в среде разработки на локальном компьютере и IP docker-контейнера Nginx.

На Mac и Linux этот файл расположен в /etc/hosts. На Windows он находится в C:\Windows\System32\drivers\etc\hosts.

Строки, которые вы добавляете в этот файл, будут выглядеть так:

127.0.0.1   project-1.localhost
127.0.0.1   project-2.localhost

В данном случае, мы исходим из того, что Nginx, запущенный в docker-контейнере, доступен по адресу 127.0.0.1 и web-сервер слушает порт 80.

Не рекомендуем использовать имя хоста с .dev на конце в среде разработки. Лучшей практикой является применение других названий — .localhost или .test.

6[опционально, если это необходимо] Настройте маршрутизацию внутри контейнеров web-проектов.

Web-проекты должны иметь возможность отправлять http-запросы друг другу и использовать для этого название хостов.

Из одного запущенного docker-контейнера php-7.1 web-приложение № X должно иметь возможность отправить запрос к другому web-приложению № Y, которое работает внутри docker-контейнера php-7.3. При этом адресом запроса может быть название хоста, которое указано в файле /etc/hosts локального компьютера.

Чтобы это стало возможным нужно внутри контейнеров так же внести соответствующие записи в файл /etc/hosts.

Самый простой способ решить данную задачу — добавить секцию extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.

Пример:

...  
  php-7.1:  
  ...
    extra_hosts:
      - 'project-1.localhost:IP_HOST_MACHINE'
      - 'project-2.localhost:IP_HOST_MACHINE'
  ...

IP_HOST_machine — IP адрес, по которому из docker-контейнера доступен ваш локальный компьютер.

Если вы разворачиваете среду разработки на Mac, то внутри docker-контейнера вам доступен хост docker.for.mac.localhost.

Узнать IP адрес вашего Mac можно при помощи команды, который нужно выполнить на локальной машине:

docker run -it alpine ping docker.for.mac.localhost

В результате вы получите, что-то подобное:

PING docker.for.mac.localhost (192.168.65.2): 56 data bytes
64 bytes from 192.168.65.2: seq=0 ttl=37 time=0.286 ms
64 bytes from 192.168.65.2: seq=1 ttl=37 time=0.504 ms
64 bytes from 192.168.65.2: seq=2 ttl=37 time=0.801 ms

После того, как вам станет известен IP-адрес, укажите его в секции extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.

...  
  php-7.1:  
  ...
    extra_hosts:
      - 'project-1.localhost:192.168.65.2'
      - 'project-2.localhost:192.168.65.2'
  ...

8. Настройте параметры соединения с системами хранения данных.

Хосты и порты сервисов

Для того, чтобы настроить соединения с базами данных из docker-контейнеров php-7.1 и php-7.3 следует использовать следующие названия хостов и порты:

Сервис

Название хоста

Порт

MySQL 5.7

mysql-5.7

3308

MySQL 8

mysql-8

3308

PostgreSQL

postgres

5432

MongoDB

mongo

27017

Redis

redis

6379

Именно эти параметры следует использовать для конфигурации web-проектов.

Для соединения с базами данных с локальной машины:

  • Хост для всех баз данных — 127.0.0.1.

  • Порты — значения указанные в .env.

7. Создайте контейнеры и запустите их.

Выполните команду:

docker-compose build && docker-compose up -d

Создание контейнеров займёт некоторое время. Обычно от 10 до 30 минут. Дождитесь окончания процесса. Ваш компьютер не должен потерять доступ в интернет.

Если вы всё сделали правильно, то контейнеры будут созданы и запущены. 

Откройте Docker Dashboard и убедитесь в этом:

8. Создайте SSH-ключи.

Для работы web-проектов могут потребоваться SSH-ключи, например для того, чтобы из контейнера при помощи Composer можно было установить пакет из приватного репозитория.

Создать SSH-ключи можно при помощи следующей команды:

ssh-keygen -f ./.ssh/id_rsa -t rsa -b 2048 -C "your-name@example.com"

Вместо your-name@example.com укажите свой Email.

В папку .ssh/ будут сохранены 2 файла — публичный и приватный ключ.

9. Проверьте созданные docker-контейнеры.

Выполните команду:

docker ps

Если создание контейнеров прошло успешно, то вы увидите примерно такой результат:

CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                               NAMES
8d348959c475        docker-php-workspace_php-7.1   "docker-php-entrypoi…"   6 minuts ago        Up 54 seconds       0.0.0.0:9001->9000/tcp              php-7.1
a93399727ff6        docker-php-workspace_php-7.3   "docker-php-entrypoi…"   6 minuts ago        Up 53 seconds       0.0.0.0:9003->9000/tcp              php-7.3
5cd80ac95388        nginx:stable-alpine            "/docker-entrypoint.…"   6 minuts ago        Up 51 seconds       0.0.0.0:80->80/tcp                  nginx
70182bc9e44c        mysql:5.7                      "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       33060/tcp, 0.0.0.0:4307->3306/tcp   mysql-5.7
46f2766ec0b9        mysql:8.0.21                   "docker-entrypoint.s…"   6 minuts ago        Up 53 seconds       33060/tcp, 0.0.0.0:4308->3306/tcp   mysql-8
a59e7f4b3c61        mongo:4.2                      "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       0.0.0.0:27017->27017/tcp            mongo
eae8d62ac66e        postgres:alpine                "docker-entrypoint.s…"   6 minuts ago        Up 53 seconds       0.0.0.0:54322->5432/tcp             postgres
bba24e86778a        redis:latest                   "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       0.0.0.0:6379->6379/tcp              redis

10. Установка зависимостей для web-приложений.

Если для работы web-приложений необходимо установить зависимости, например через менеджер пакетов Composer или NPM, то сейчас самое время сделать это.

В контейнерах php-7.1 и php-7.3 уже установлен и Composer и NPM.

Войдите в контейнер php-7.1:

docker exec -it php-7.1 bash

или php-7.3:

docker exec -it php-7.3 bash

Перейдите в рабочий каталог необходимого web-проекта и выполните требуемые действия.

Например, установите зависимости через Composer при помощи команды:

composer install

Вопросы и ответы 

Несколько важных вопросов и ответов.

Как зайти в работающий docker-контейнер? 

Выполните команду:

docker exec -it container_name bash

container_name — имя контейнера.

Как останавливать и удалить контейнеры и другие ресурсы среды разработки, которые были созданы? 

docker-compose down

Как получить список всех контейнеров? 

docker ps -a

Как получить подробную информацию о docker-контейнере? 

docker inspect containername

containername — имя контейнера.

Как получить полный список расширений PHP, которые установлены в контейнере php-7.3? 

Если контейнер php-7.3 запущен, то выполните команду:

docker exec -it php-7.3 php -m

Как удалить все контейнеры? 

Удаление всех контейнеров:

docker rm -v $(docker ps -aq)

Удаление всех активных контейнеров:

docker rm -v $(docker ps -q)

Удаление всех неактивных контейнеров:

docker rm -v $(docker ps -aq -f status=exited)

Развёртывание дампов MySQL, PostgreSQL и MongoDB

Если для работы web-проектов требуются перенести данные в хранилища, то следуйте описанным ниже инструкциям.

Как развернуть дамп PostgreSQL? 

Выполните следующую команду на локальной машине:

docker exec -i postgres psql --username user_name database_name < /path/to/dump/pgsql-backup.sql

Или зайдите в контейнер postgres и выполните:

psql --username user_name database_name < /path/to/dump/pgsql-backup.sql

user_name — имя пользователя. Значение postgres_USER (см. файл .env).

database_name — название базы данных. Значение postgres_DB (см. файл .env).

Как развернуть дамп MySQL? 

Существует два варианта.

Вариант 1

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

В файле mysql/conf.d/config-file.cnf отключите лог медленных запросов slow_query_log=0 или установите большое значение long_query_time, например 1000.

Если дамп сжат утилитой gzip, сначала следует распаковать архив:

gunzip databases-dump.sql.gz

Затем можно развернуть дамп, выполнив на локальном компьютере команду:

docker exec -i mysql mysql --user=root --password=secret --force < databases-dump.sql

Указывать пароль в командной строке — плохая практика, не делайте так в производственной среде.

MySQL выдаст справедливое предупреждение:

mysql: [Warning] Using a password on the command line interface can be insecure

Ключ --force говорит MySQL, что ошибки следует проигнорировать и продолжить развёртывание дампа. Этот ключ иногда может пригодится, но лучше его без необходимости не применять.

Вариант 2

Воспользоваться утилитой Percona XtraBackup.

Percona XtraBackup — это утилита для горячего резервного копирования баз данных MySQL.

О том, как работать с XtraBackup можно узнать по ссылке: https://medium.com/@drandin/создание-резервной-копии-mysql-при-помощи-утилиты-xtrabackup-26bd3f843075

Как развернуть дамп MongoDB? 

  • Скопируйте фалы дампа в каталог mongo/dump.

  • Войдите в контейнер mongo:

docker exec -it mongo sh

Выполните следующую команду, чтобы развернуть дамп базы database_name:

mongorestore -d database_name /dump/databases/database_nam

Git-репозиторий проекта: https://github.com/drandin/docker-php-workspace

Теги:
Хабы:
+19
Комментарии 38
Комментарии Комментарии 38

Публикации

Истории

Работа

PHP программист
171 вакансия
DevOps инженер
39 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн