0% прочитано

Як відрізнити конфлікт порту Docker від проблеми Laravel

Контейнер може не запуститися через зайнятий порт, навіть якщо Laravel повністю справний. На реальному випадку з Laradock workspace для PHP 8.3 і портом 5173 показую, як перевірити контейнер, порт, Docker-помилку та сам застосунок окремо.

2 листопада 2026 р. 9 хв читанняLaradock

Під час відновлення локального Laradock після PHP security-оновлення один із контейнерів не запускався. На перший погляд це легко сприйняти як проблему проєкту: "Laravel зламався після оновлення".

Насправді причина була на іншому рівні. Workspace для PHP 8.3 намагався опублікувати порт 5173, але цей порт уже використовував інший процес на хості.

Цей випадок добре показує, чому Docker-помилку потрібно спочатку локалізувати, а вже потім робити висновки про Laravel.

Починаємо зі стану контейнера, а не з Laravel

Якщо контейнер не запустився, перше питання просте: який його фактичний стан після команди?

Не потрібно одразу запускати artisan, очищати кеш або змінювати application config. Спочатку перевіряємо Docker.

Перевіряємо workspace після невдалого запуску
cd ~/Projects/laradock || exit 1 docker compose ps -a workspace docker ps -a \  --filter 'name=laradock-workspace' \  --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'

У моєму випадку workspace для PHP 8.3 залишався неактивним, тоді як інші PHP-FPM і workspace 8.4/8.5 уже могли працювати.

Це одразу звужує діагностику: проблема не виглядає як загальна поломка всього Laradock або всіх PHP runtime.

Дивимося Docker error для конкретного контейнера

Стан і остання Docker-помилка контейнера
docker inspect \  --format 'status={{.State.Status}} exit={{.State.ExitCode}} error={{.State.Error}}' \  laradock-workspace-1

.State.Error корисний саме для помилок, які виникають під час створення або запуску контейнера. Якщо Docker не зміг прив’язати published port, застосунок усередині контейнера міг навіть не дійти до запуску.

У такій ситуації Laravel ще не мав можливості "зламатися", тому що проблема сталася раніше, на рівні Docker runtime.

Перевіряємо, хто вже слухає порт 5173

Хто займає TCP-порт 5173
sudo ss -H -ltnp \  '( sport = :5173 )'

Якщо команда показує процес, який уже слухає 5173, причина конфлікту підтверджується на рівні хоста.

Далі важливо не завершувати цей процес автоматично. Спочатку потрібно зрозуміти, кому він належить і чи не використовує його інший локальний проєкт або активний dev server.

Перевіряємо published ports самого workspace

Port bindings контейнера
docker inspect \  --format '{{json .HostConfig.PortBindings}}' \  laradock-workspace-1

Ця перевірка відповідає на друге запитання: чи контейнер узагалі намагається опублікувати той порт, який уже зайнятий.

Якщо Docker configuration містить host binding для 5173, а ss показує іншого слухача, це вже достатньо сильний доказ конфлікту портів.

Logs корисні, але вони не завжди є головним доказом

Останні logs контейнера
docker logs \  --tail 100 \  laradock-workspace-1 \  2>&1

Якщо контейнер не зміг стартувати ще на етапі port binding, application logs можуть бути порожніми або не містити причини.

Тому для такого класу помилок я більше довіряю комбінації docker inspect .State.Error, published port configuration і ss, ніж відсутності або наявності Laravel stack trace.

Окремо доводимо, що Laravel працює

Після того як конфлікт порту локалізований, Laravel потрібно перевірити окремо в уже робочому PHP-FPM контейнері. У моєму середовищі PHP-FPM 8.5 був активний і вже використовував виправлений PHP.

Для базової перевірки достатньо довести, що Composer platform check проходить і Laravel може завантажитися та показати свою версію.

Laravel bootstrap у вже робочому PHP-FPM
cd ~/Projects/laradock || exit 1 docker compose exec -T php-fpm-85 \  php /var/www/icanup/vendor/composer/platform_check.php docker compose exec -T php-fpm-85 \  sh -lc 'cd /var/www/icanup && php artisan --version --no-ansi'
Шлях /var/www/icanup наведений як приклад для конкретного локального проєкту. У власному Laradock потрібно використовувати реальний mount path застосунку.

Конфлікт порту і проблема Laravel мають різні ознаки

Для себе я розділяю ці два класи помилок так:

  • Docker port conflict: контейнер не переходить у running, .State.Error вказує на bind або port allocation, ss показує іншого слухача, application logs можуть бути порожніми;
  • Laravel problem: контейнер уже працює, PHP виконується, але artisan, HTTP-запит або application logs показують помилку самого застосунку.

Це не абсолютне правило для всіх випадків, але воно добре не дає змішувати два різні рівні системи.

Не повторюємо docker compose up навмання

Після першої помилки легко просто ще раз виконати docker compose up -d. У складному Laradock це погана звичка.

Попередня команда могла вже запустити інші залежності, а новий повтор ще раз змінить стан середовища. Спочатку потрібно подивитися, що реально працює після частково невдалої операції.

Фактичний стан після помилки
cd ~/Projects/laradock || exit 1 docker compose ps -a echoecho "===== RUNNING =====" docker ps \  --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'

Мій порядок діагностики

Для подібної ситуації я використовую короткий порядок:

  1. перевіряю стан проблемного контейнера через docker compose ps -a;
  2. читаю .State.Error через docker inspect;
  3. перевіряю published ports контейнера;
  4. шукаю власника конфліктного порту через ss;
  5. дивлюся останні Docker logs, але не вважаю їх єдиним джерелом причини;
  6. окремо перевіряю Laravel у вже робочому PHP runtime;
  7. лише після цього вирішую, чи потрібно звільняти порт, змінювати конфігурацію або просто залишити цей workspace зупиненим.

Контейнер, який не зміг прив’язати порт, ще нічого не говорить про стан Laravel усередині іншого робочого PHP runtime.

Підсумок

У моєму випадку workspace PHP 8.3 не запускався через зайнятий 5173. Це була Docker-інфраструктурна проблема, а не доказ поломки Laravel.

Laravel окремо проходив базовий bootstrap у робочому PHP-FPM, інші PHP-сервіси працювали, а конфлікт локалізувався конкретним published port.

Головний висновок для мене: спочатку визначити рівень помилки. Docker, порт, PHP runtime і Laravel - це різні шари, і діагностувати їх потрібно окремо.