Compose override добавил второй порт вместо замены: проверяем объединение файлов

Основной Compose публикует web на 8080. Для локального окружения добавили override с 9090 и ожидали, что старый порт исчезнет. После запуска доступны оба адреса. Compose объединяет файлы по правилам модели, и список ports имеет собственный ключ уникальности. Чтобы убрать лишнюю публикацию, сначала посмотрим получившуюся конфигурацию без запуска контейнера.

Воспроизводим объединение двух файлов

Сохраните первый файл как base.yaml. Порт привязан к loopback, чтобы учебный веб-сервер не открывался на всех интерфейсах хоста:

services:
  web:
    image: nginx:stable-alpine
    ports:
      - "127.0.0.1:8080:80"

Во втором файле extra.yaml задайте другую публикацию того же container port:

services:
  web:
    ports:
      - "127.0.0.1:9090:80"
docker compose version
docker compose -p mergelab -f base.yaml -f extra.yaml config

В итоговой модели будут две записи published: 8080 и published: 9090. Compose объединяет последовательности, а для ports учитывает уникальность по ip, target, published и protocol. Здесь published отличается, поэтому записи не являются одним элементом. Одинаковый target:80 ещё не означает замену порта хоста.

Явно заменяем список

В актуальном Compose можно применить тег !override. Сохраните такой вариант второго файла как replace.yaml:

services:
  web:
    ports: !override
      - "127.0.0.1:9090:80"
docker compose -p mergelab -f base.yaml -f replace.yaml config

Теперь у web должна остаться одна публикация 9090. !override требует Docker Compose 2.24.4 или новее; установленную версию проверьте до использования файла в CI и у разработчиков. Это специальный тег Compose, поэтому обычный YAML-парсер без его поддержки может отклонить файл, хотя Compose принимает его правильно.

Если нужно полностью убрать публикацию, используйте в override ports: !reset []. Пустой обычный список ports: [] не следует считать универсальной командой очистки ранее объявленных значений. Для старой среды без нужных тегов измените структуру файлов: оставьте общий base без ports, а публикацию задавайте только в отдельном файле окружения. Это часто делает намерение понятнее, чем цепочка взаимно отменяющих настроек.

Порядок файлов — часть команды релиза

Проверьте фактический вызов из скрипта. Список -f, переменная COMPOSE_FILE и автоматически подхватываемый compose.override.yaml могут отличать ручной запуск от CI. Не сравнивайте один override сам с собой: итог определяется всем набором и порядком файлов. config показывает модель после слияния и подстановки переменных; сохраняйте её с защитой чувствительных environment-значений.

Относительные пути нескольких файлов обычно трактуются относительно первого базового файла. Поэтому перенос override в другой каталог не обязательно меняет основу bind mount так, как ожидает автор. Эта тема шире ports, но её стоит проверить, если вместе с портом неожиданно изменился каталог конфигурации. Одно объединение может менять несколько частей модели.

После проверки применяем новую модель

docker compose -p mergelab -f base.yaml -f replace.yaml up -d
docker compose -p mergelab -f base.yaml -f replace.yaml ps web
docker compose -p mergelab -f base.yaml -f replace.yaml port web 80

Команды запуска предназначены для учебного проекта mergelab. config не обращается к работающему контейнеру, поэтому правильная модель ещё не доказывает применение к нужному проекту. После up проверьте фактическую публикацию. Простое restart не пересоздаёт контейнер с изменённой конфигурацией портов; нужен управляемый up с теми же файлами.

Если старый порт всё ещё отвечает, проверьте, не принадлежит ли он другому Compose-проекту или процессу на хосте. Не удаляйте случайные контейнеры ради освобождения адреса. В записи исправления полезно оставить две модели до и после: какие элементы объединились и какое явное правило заменило список. Тогда следующий override можно оценить до открытия лишнего порта.

Ещё по теме

Продолжить изучение

Хотите разобраться в контейнеризации целиком, от образа до работающего окружения? Сборка, сети, данные и запуск приложений входят в программу «Docker и Docker Compose: контейнеризация приложений».

Продолжить на практике

  • Docker и Docker Compose: контейнеризация приложений ↗

    Упакуйте приложение в Docker и запустите его с PostgreSQL через Compose. Образы, сети, тома, диагностика поломок, обновление версий и восстановление данных — с практикой и итоговым проектом.