Как выложить PHP-сайт в интернет

PHP-сайт из одного файла index.php поднимается локально одной командой, а вот публикация в интернет — это отдельная задача: сервер, нужная версия PHP с расширениями, composer, веб-сервер с корнем в нужной папке, php-fpm, права на запись, сертификат и база. Каждый пункт прост сам по себе, а вместе это вечер работы и ещё один — на разбор пустой страницы вместо сайта. На Dockbox эту часть берёт на себя платформа: вы загружаете код, она сама определяет PHP-проект, ставит зависимости по composer.json, собирает его и выдаёт публичную HTTPS-ссылку. Ниже — что подготовить в проекте, чтобы всё заработало с первого раза.

Почему простой PHP-сайт всё равно упирается в сервер

Привычный путь — длинный чек-лист: арендовать сервер, собрать нужную версию PHP, пройти composer install, поставить nginx и php-fpm, выпустить сертификат, поднять базу.

Версия PHP и расширения. Код может требовать PHP 8.2 или новее и набор расширений — pdo_mysql, mbstring, curl, gd, zip. Не хватает одного — и composer install падает, а сайт отдаёт белый экран.

Корень сайта. Веб-сервер должен смотреть туда, где лежит точка входа, а не в корень проекта с .env и исходниками. Если корень выставлен неверно, по адресу example.com/.env откроется файл с доступом к базе.

Права на запись. Папки для кэша, логов и загрузок пользователей должны быть доступны пользователю PHP — иначе 500 и Permission denied в логе.

Веб-сервер и порт. Для разработки хватает встроенного php -S, но в интернет так выкладывать нельзя: нужен php-fpm за nginx, слушающий тот порт, который даёт платформа.

Плюс сервер стоит денег все тридцать дней — даже если сайт открывают раз в сутки. Платформа деплоя снимает эту часть: она видит composer.json, ставит зависимости и отдаёт публичную HTTPS-ссылку.

Шаг 1. index.php — точка входа проекта

Убедитесь, что в проекте есть index.php — файл, с которого начинается обработка запроса. Обычный PHP на нём работает из коробки, а фреймворки вроде Laravel или Symfony уже устроены как нужно: вся маршрутизация идёт через один вход. Менять структуру проекта не придётся — достаточно стандартного вида.

Шаг 2. composer.json в корне, vendor — не в архив

composer.json — признак, по которому платформа понимает, что перед ней PHP-проект, и по которому ставит зависимости при сборке. Рядом положите composer.lock: он фиксирует точные версии пакетов, и без него сборка подтянет более свежие, с которыми проект никто не проверял.

Список зависимостей выглядит привычно:

"require": {
  "php": "^8.2",
  "monolog/monolog": "^3.0",
  "guzzlehttp/guzzle": "^7.8"
}

Папку vendor в архив не кладите. Это те же библиотеки, которые платформа поставит сама из composer.lock: лишние десятки мегабайт, долгая загрузка и риск, что локальные версии разойдутся с продом. Запускать composer install руками тоже не нужно.

Шаг 3. .env не едет в архив, секреты — в переменные окружения

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

Типичный набор:

APP_ENV=production
APP_DEBUG=false
DB_HOST=db
DB_PORT=3306
DB_DATABASE=app
DB_USERNAME=app
DB_PASSWORD=***

В коде читайте их из окружения, а не из файла: getenv('DB_PASSWORD') или $_ENV['DB_PASSWORD']. Если .env уже лежал в репозитории, считайте секреты утёкшими и смените пароли.

Шаг 4. Порт берётся из окружения, а не из кода

Если проект поднимает собственный веб-сервер (встроенный php -S или FrankenPHP), слушайте тот порт, который даёт платформа. Жёстко прописанный номер — причина номер один, по которой приложение работает, а ссылка не открывается.

Плохой вариант:

php -S 127.0.0.1:8000 -t public

Правильный:

php -S 0.0.0.0:$PORT -t public

Слушайте на 0.0.0.0, а не на 127.0.0.1. Первый адрес принимает трафик извне контейнера, второй виден только внутри него. Для обычного сайта на php-fpm за nginx об этом думать не нужно — порт и связку серверов платформа настраивает сама.

Шаг 5. Корень сайта — public, права на запись

Корень — папка с точкой входа. Если index.php лежит в public/, корень должен указывать именно туда: тогда .env и src недоступны по URL. На платформе корень выставляется автоматически — важно не выносить точку входа из public.

Папкам для записи нужны права. Логи, кэш шаблонов и загрузки должны быть доступны пользователю PHP:

chmod -R 775 storage cache public/uploads

Если после деплоя вылезает Permission denied или 500 — дело почти всегда в правах, а не в коде.

Шаг 6. Загрузите код и получите HTTPS-ссылку

Проект попадает на платформу ZIP-архивом или импортом репозитория GitHub, включая приватный. Дальше она сама определяет, что это PHP, ставит зависимости, собирает и запускает приложение: настраивать nginx, php-fpm и корень public руками не нужно, версию PHP выбирать тоже. Логи сборки и запуска видны в панели в реальном времени, поэтому ошибка проявляется сразу. Свой домен подключается в настройках проекта: записи DNS подсказываются в панели, сертификат выпускается автоматически.

Сколько это стоит и как работают контейнеры

Администрировать сервер не нужно — контейнеры работают постоянно, без ограничения по часам и без «засыпания». Упавший контейнер платформа перезапускает сама.

Starter — 990 ₽/мес. 1 vCPU, 2 GB RAM, первый месяц бесплатно. Для одного PHP-сайта этого достаточно, и лимита по времени работы у тарифа нет.

Pro — 2 490 ₽/мес. Больше ресурсов и до пяти проектов — если рядом с сайтом живут база, очередь и воркер.

Team — 4 990 ₽/мес — для команд, которым нужен запас ресурсов и SLA.

Тарифы и подробности — на dockbox.host.

Частые вопросы

Нужно ли настраивать nginx и php-fpm?

Нет. Связка php-fpm и nginx, корень в public и порт настраиваются при сборке. От вас нужен код проекта с composer.json — и всё.

Что делать с файлом .env?

Не класть ни в архив, ни в репозиторий. Значения переносятся в переменные окружения — они хранятся зашифрованными, а в коде вы читаете их через getenv(). .env в архиве — самый простой способ потерять пароль к базе.

Можно ли выложить сайт на встроенном сервере php -S?

Локально — да, для разработки это удобно. В интернет так выкладывать не стоит: у встроенного сервера нет нормальной обработки параллельных запросов и логирования. На платформе за это отвечает php-fpm за nginx.

Сайт отдаёт 500 или пустую страницу — с чего начать?

Три частые причины: не заданы переменные окружения, включая доступ к базе; нет прав на запись в папки кэша и логов; не установлены зависимости из composer.lock. Настоящая ошибка написана в логах — откройте их в панели.

Куда девать файлы, которые загружают пользователи?

Всё, что приложение пишет внутрь контейнера, при обновлении кода пересоздаётся. Загрузки держите на постоянном диске или во внешнем S3-совместимом хранилище, а не в папке проекта.