Після оновлення локального Laradock я хотіла повернути один конкретний сервіс. Команда виглядала точково: запустити Nginx, який уже існував як контейнер.
Але Compose почав запускати також workspace-84 і workspace-85, а workspace для PHP 8.3 не зміг стартувати через зайнятий порт 5173. У результаті проста на вигляд команда торкнулася значно більшої частини середовища, ніж я очікувала.
Проблема була не в Laravel і не в самому Nginx. Щоб зрозуміти поведінку, потрібно було подивитися на фактичну Compose-конфігурацію, набір Compose-файлів, залежності сервісів і поточний стан контейнерів.
Одна команда Compose працює з об’єднаною конфігурацією
У Laradock конфігурація може складатися не з одного файлу. Базовий Compose-файл доповнюється іншими файлами, а змінна COMPOSE_FILE може визначати їхній набір за замовчуванням.
Тому команда docker compose start nginx працює не з тим фрагментом конфігурації, який я пам’ятаю, а з тією моделлю, яку Compose реально зібрав у цей момент.
cd ~/Projects/laradock || exit 1 grep -E '^COMPOSE_FILE=' .env || true docker compose config -qДивимося весь список сервісів, який бачить Compose
cd ~/Projects/laradock || exit 1 docker compose config --servicesЦе проста, але корисна перевірка. Вона показує не тільки Nginx або PHP-FPM, а всі сервіси, які входять у поточну Compose-модель.
У моєму випадку серед них були окремі PHP-FPM для 8.3, 8.4 і 8.5, відповідні workspace, phpMyAdmin, бази даних, Redis, MinIO, Mailpit, Nginx та інші локальні залежності.
Вже на цьому етапі видно, що Laradock - це не один контейнер Laravel, а граф пов’язаних сервісів.
Перед запуском фіксуємо поточний стан контейнерів
cd ~/Projects/laradock || exit 1 docker compose ps -a \ nginx \ workspace \ workspace-84 \ workspace-85 \ php-fpm \ php-fpm-84 \ php-fpm-85У моєму Laradock ім’я workspace відповідало гілці PHP 8.3, а workspace-84 і workspace-85 - PHP 8.4 і 8.5.
Це важлива деталь: назва сервісу не завжди містить повну версію. Якщо дивитися лише на назву контейнера, легко неправильно оцінити, який саме PHP runtime зачепить команда.
Перевіряємо залежності сервісів у вже злитій конфігурації
Сам список сервісів ще не пояснює, чому команда для Nginx зачепила workspace. Для цього потрібно подивитися depends_on після злиття всіх Compose-файлів.
Я не публікую повний docker compose config, тому що він може містити розгорнуті значення змінних середовища. Замість цього можна витягнути тільки назви сервісів та їхні залежності.
cd ~/Projects/laradock || exit 1 docker compose config --format json |python3 -c 'import jsonimport sys data = json.load(sys.stdin) for name, service in data.get("services", {}).items(): dependencies = service.get("depends_on", {}) if not dependencies: continue if isinstance(dependencies, dict):Що сталося в моєму випадку
Після того як захищена чотирифайлова Compose-конфігурація стала конфігурацією за замовчуванням, я звільнила порт 80 і виконала перевірку конфігурації, а потім спробувала запустити Nginx:
cd ~/Projects/laradock || exit 1 docker compose config -q &&docker compose start nginxЗамість запуску тільки Nginx Compose також почав піднімати workspace-84 і workspace-85. Спроба запустити workspace для PHP 8.3 завершилася помилкою, тому що порт 5173 на хості вже був зайнятий.
Цей результат був важливим: помилка одного workspace перервала очікуваний сценарій запуску Nginx, хоча сам Nginx не був першопричиною.
Помилка порту одного залежного сервісу може виглядати як проблема всього запуску
sudo ss -H -ltnp \ '( sport = :5173 )'Тут важливо не робити висновок "Laravel не запускається". Конфлікт published port - це окрема проблема Docker-рівня.
Спочатку потрібно визначити, хто слухає порт, чи потрібен цей процес, і чи взагалі потрібен workspace 8.3 у поточній роботі. Не варто автоматично завершувати невідомий процес лише для того, щоб Compose пройшов далі.
docker compose up -d може торкнутися ще більшої частини середовища
Пізніше під час відновлення локального середовища звичайний docker compose up -d запустив бази даних, Redis, PostgreSQL, MinIO, Mailpit, phpMyAdmin та workspace 8.4/8.5, а потім зупинився на тому самому конфлікті порту workspace 8.3.
Це хороший приклад того, чому перед up -d потрібно розуміти всю Compose-модель. Така команда призначена не для "одного сайту", а для приведення набору сервісів проєкту до описаного стану.
Коли потрібно запустити рівно один уже створений контейнер
У моєму випадку, коли потрібно було повернути лише вже створений Nginx і не зачіпати workspace, безпечнішим точковим кроком став прямий запуск існуючого контейнера Docker.
docker start laradock-nginx-1 docker exec \ laradock-nginx-1 \ nginx -tПісля невдалого запуску перевіряємо фактичний стан, а не припускаємо
cd ~/Projects/laradock || exit 1 docker compose ps -a echoecho "===== RUNNING =====" docker ps \ --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'Якщо Compose завершився помилкою на одному сервісі, це не означає, що всі попередні дії були відкочені. Частина контейнерів уже може бути запущена.
Саме тому після помилки я не повторюю команду автоматично. Спочатку дивлюся фактичний стан контейнерів і лише потім вирішую наступний крок.
Мій короткий порядок діагностики
Коли Compose запускає більше, ніж я очікувала, я перевіряю це в такому порядку:
- дивлюся
COMPOSE_FILEі переконуюся, які файли Compose використовуються; - виконую
docker compose config -q; - переглядаю
docker compose config --services; - перевіряю
depends_onу злитій конфігурації; - фіксую стан потрібних workspace, PHP-FPM і Nginx через
docker compose ps -a; - якщо є конфлікт порту, перевіряю власника порту через
ss; - після будь-якої часткової помилки знову перевіряю фактичний стан контейнерів і не запускаю ту саму команду навмання.
Команда називає сервіс, але реальну область її впливу визначає вся Compose-модель і залежності між сервісами.
Підсумок
Мій випадок із Laradock показав просту річ: перед запуском Compose недостатньо дивитися лише на назву команди. Потрібно знати, які Compose-файли злиті, які залежності має сервіс і які контейнери вже існують.
docker compose start nginx виглядав як точкова дія, але фактична модель пов’язувала його з workspace. Один конфлікт порту в PHP 8.3 workspace змінив увесь сценарій запуску.
Тому після складного оновлення я спочатку перевіряю конфігурацію і залежності, а вже потім запускаю сервіси. Це значно безпечніше, ніж дізнаватися про граф залежностей під час помилки.



