Когда мы пишем веб-приложение (сайт) на php, мы не реализуем веб-сервер . На самом деле мы пишем только кусочек веб-приложения, который потом соединяется с одним из универсальных веб-серверов.
На хостинге веб-сервер обычно уже настроен и вам нужно просто положить ваши php-файлы в определённую папку, что бы всё заработало. При разработке веб-приложения на своём компьютере, придётся установить и настроить какой-нибудь веб-сервер.
php -S – примитивный веб-сервер, который у вас уже есть, если у вас установлен php. Его возможностей достаточно для обучения и совсем простых проектов.
apache – популярный веб-сервер, который связывается с php с помощью специального модуля. Я бы рекомендовал его, если вы работаете с готовым проектом, который рассчитан на интеграцию именно с apache.
nginx – один из самых популярных веб-серверов у разработчиков на php. nginx интегрируется с php по fastCGI. Для большинства проектов я бы советовал именно его.
apache или nginx можно просто установить на свой компьютер и настроить как надо. Для новичков настройка может показаться сложной, поэтому существуют проекты-сборки типа LAMP ( xampp, openserver, denver…), которые содержат всё необходимое для разработки с подходящими настройками. Я против таких решений. Если вы только изучаете php, то воспользуйтесь встроенным сервером , это позволит вам лучше понять как всё работает. А когда возможностей встроенного сервера вам станет мало, научитесь настраивать, например, nginx.
Если вы уже научились использовать встроенный сервер php, хотите начать работать с базами данных и другими компонентами веб-приложений, то вам пригодится docker.
💡 Если вы только начинаете осваивать PHP, то не спешите настраивать docker или какую-нибудь сборку типа LAMP. Разберитесь с основами, используя встроенный сервер php. Это даст вам лучшее понимание как работает веб и сэкономит кучу сил и нервов на старте.
Сегодня разработчики не устанавливают на свои компьютеры apache или nginx обычным способом. Дело в том, что один разработчик на одном компьютере может разрабатывать много разных приложений с разными требованиями к веб-серверам и их настройкам. Docker предоставляет возможность завести совершенно разные окружения (веб-серверы, базы данных и прочее) для разных проектов.
Вот как это работает:
Получается, что для организации разработки на вашем компьютере, вам надо установить docker и в каждом проекте описать необходимое окружение в специальном формате. После этого, для работы над проектом, надо перейти в соответствующую папку и запустить виртуальное окружение и локальный сайт станет доступен из браузера.
Предположим вы разрабатываете сайт в папке mySite
. Чтобы начать использовать
докер, надо описать все сервисы сайта в специальном
файле compose.yaml. Я
рекомендую положить этот файл в отдельную папку docker
, в которой хранить всё
что связано с запуском dev-окружения: конфиги сервисов, файлы данных и прочее.
mySite
├── docker
│ └── compose.yaml
└── src
└── public
└── index.php
А вот как может выглядеть ваш первый compose.yaml:
services:
php:
image: php # используем официальный образ php https://hub.docker.com/_/php
ports:
- 8080:8080 # пробрасываем порт 8080
volumes:
- ../src:/mySite # монтируем нашу папку src в контейнер в папку /mySite
working_dir: /mySite/public # переключаемся в public папку в контейнере
entrypoint: [php, -S, 0.0.0.0:8080] # запускаем встроенный сервер php на 8080 порту
Теперь если перейти в папку docker в консоли и выполнить docker compose up -d
,
то docker поднимет сервис php (первый запуск может занять много времени, докеру
нужно скачать образ php). После чего, можно зайти
на localhost:8080 и увидеть рабочий сайт. Чтобы
остановить mySite, надо выполнить docker compose down
.
Преимущества такого подхода заключаются в том, что вы можете использовать разные версии php для разных проектов, иметь разные настройки php.ini для разных проектов, устанавливать разные модули. Закоммитьте папку docker в репозиторий и ваши коллеги смогут развернуть у себя точно такое же окружение. Это очень удобно.
В официальном образе php не установлены модули для работы с базой данных. Чтобы это исправить, надо описать свой образ на базе исходного, добавив специальные инструкции по установке расширений.
Создайте в паке docker
папку php
, а в ней создайте файл Dockerfile
:
FROM php
# копируем базовый production-конфиг в php.ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# устанавливаем pdo и mysql модули
RUN docker-php-ext-install pdo pdo_mysql
Также создайте конфиг mySite.ini
в папке docker/php
. Этот конфиг перезапишет
настройки по умолчанию:
date.timezone = Europe/Moscow
Создайте папку docker/mysql
, а в ней конфиг MySite.cnf
:
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqld]
init-connect='SET NAMES utf8mb4'
collation_server=utf8mb4_unicode_ci
character_set_server=utf8mb4
Теперь надо поменять compose.yaml
:
services:
php:
build: php # собираем свой образ php из Dockerfile
ports:
- 8080:8080
volumes:
- ./php/mySite.ini:/usr/local/etc/php/conf.d/mySite.ini:ro # :ro -- read only
- ../src:/mySite
working_dir: /mySite/public
entrypoint: [php, -S, 0.0.0.0:8080]
depends_on:
- mysql # наш сайт не может работать без базы данных
mysql: # раз уж мы решили работать с mysql, то нам нужен mysql-сервер
image: mysql # используем официальный образ mysql https://hub.docker.com/_/mysql
environment: # переменные окружения управляют настройками mysql в контейнере, читайте об этом в описании образа https://hub.docker.com/_/mysql
MYSQL_DATABASE: mySite
MYSQL_USER: mySite
MYSQL_PASSWORD: passw0rd
MYSQL_RANDOM_ROOT_PASSWORD: true
volumes:
- ./mysql/mySite.cnf:/etc/mysql/conf.d/mySite.cnf:ro
- ./mysql/data:/var/lib/mysql # файлы базы данных из контейнера пробросим в локальную папку mysql/data, чтобы не терять данные при перезапуске контейнера
Теперь, если запустить docker compose up -d
, то стартует php с нашими
расширениями и mysql! Из php-контейнера, mysql-контейнер доступен по
адресу mysql
(то есть в dsn пишем не localhost, a mysql).
Если вы хотите подключаться к базе данных с локального клиента (например из IDE) , то не забудьте пробросить порт базы данных.
# ...
mysql:
# ...
ports:
- 3306:3306
Встроенный сервер php отлично подходит для обучения, но в рабочих проектах
обычно используется nginx. Вы можете добавить nginx в compose.yaml
.
Nginx взаимодействует с php по протоколу FastCGI, поэтому понадобится
fpm-сервер. php/Dockerfile
будет выглядеть так:
FROM php:fpm-alpine
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
RUN docker-php-ext-install pdo pdo_mysql
Ещё понадобится конфиг mySite.conf
, создайте его в папке docker/nginx
:
server {
listen 80;
server_name localhost;
root /usr/nginx/share/html;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME /mySite/public$fastcgi_script_name;
include fastcgi_params;
}
}
Теперь проект выглядит так:
├── docker
│ ├── compose.yaml
│ ├── mysql
│ │ ├── data
│ │ └── mySite.cnf
│ ├── nginx
│ │ └── mySite.conf
│ └── php
│ ├── Dockerfile
│ └── mySite.ini
└── src
└── public
└── index.php
А файл compose.yaml так:
services:
php:
build: php
volumes:
- ./php/mySite.ini:/usr/local/etc/php/conf.d/mySite.ini:ro
- ../src:/mySite
depends_on:
- mysql
nginx:
image: nginx
ports:
- 8080:80
volumes:
- ./nginx/mySite.conf:/etc/nginx/conf.d/default.conf:ro
- ../src/public:/mySite:ro
depends_on:
- php
mysql:
image: mysql
environment:
MYSQL_DATABASE: mySite
MYSQL_USER: mySite
MYSQL_PASSWORD: passw0rd
MYSQL_RANDOM_ROOT_PASSWORD: true
volumes:
- ./mysql/mySite.cnf:/etc/mysql/conf.d/mySite.cnf:ro
- ./mysql/data:/var/lib/mysql
Теперь, запуская docker compose up -d
, вы получите окружение для разработки
сайта на PHP и MySQL. При необходимости вы легко можете добавлять и другие
компоненты инфраструктуры вашего сайта.
Изучите возможности докера. Этот инструмент используется очень широко, и умение пользоваться им для разработки сделает вас более ценным сотрудником в любой компании.
🐞 Хотя я запускал тестовый сайт на этом окружении, когда писал заметку, но запросто мог ошибиться или опечататься. Если вы заметили ошибку, напишите мне в ишьюс.