Что такое EXPOSE в Dockerfile?

Ответ

Инструкция EXPOSE в Dockerfile — это декларация о том, что контейнер будет прослушивать указанные сетевые порты на определённом транспортном протоколе (по умолчанию TCP). Это метаинформация, а не команда, открывающая порты.

Как я использую EXPOSE на практике:

  1. Документация: Это явное указание для других разработчиков (и для меня в будущем), какие порты использует приложение внутри контейнера. Например, веб-сервер — 80, HTTPS — 443, дебаг-порт приложения — 5005.

    FROM nginx:alpine
    # Документируем, что контейнер использует стандартные порты HTTP/HTTPS
    EXPOSE 80/tcp 443/tcp
  2. Автоматическое пробрасывание портов с флагом -P: При запуске docker run -P Docker автоматически сопоставит каждый порт из EXPOSE со случайным высоким портом (например, 32768+) на хосте. Это удобно для тестирования.

    # Запуск с автоматической публикацией портов
    docker run -d -P my-nginx
    docker port <container_id> # Покажет сопоставление 80/tcp -> 0.0.0.0:32768

Критически важное уточнение: EXPOSE НЕ делает порт доступным снаружи хоста. Для публикации порта наружу используется флаг -p (публикация на конкретный порт) или -P (автоматическая публикация).

# EXPOSE 80 в Dockerfile, но без этих флагов порт 80 будет доступен ТОЛЬКО внутри Docker-сети.
# Правильная публикация порта на хост:
docker run -p 8080:80 my-nginx  # Теперь приложение доступно на localhost:8080

В CI/CD пайплайнах и оркестраторах (Kubernetes, Docker Compose) информация из EXPOSE также может использоваться для автоматической настройки сетевых правил.

Ответ 18+ 🔞

Давай разберём эту тему про EXPOSE в Dockerfile, чтобы всё встало на свои места, как надо. Это одна из тех вещей, про которую думают: «Ну указал порт и всё работает», а потом охуевают, когда снаружи нихуя не открывается.

По факту, EXPOSE — это не команда, а скорее бумажка с пометкой. Как настройка в инструкции: «Внимание! Внутри этой банки-контейнера что-то будет слушать вот эти дырочки (порты)». Это чистая метаинформация, декларация намерений.

Зачем мне это на практике, спросишь?

  1. Чтобы не быть распиздяем. Это документация для самого себя и для команды. Открываешь Dockerfile и сразу видишь: ага, тут веб-сервер на 80-м порту торчит, а тут дебаггер на 5005-м висит. Всё понятно, не надо копаться в логах приложения.

    FROM nginx:alpine
    # Читаем и понимаем: контейнер будет слушать 80-й и 443-й порты по TCP. Всё, логично.
    EXPOSE 80/tcp 443/tcp
  2. Для ленивых (или умных) — флаг -P. Если запустить контейнер с этой волшебной буквой, Docker сам возьмёт все порты из EXPOSE и пробросит их на свободные высокие порты хоста (типа 32768, 32769...). Удобно для быстрого теста, чтобы не париться с цифрами.

    # Запустил и забыл. Докер сам всё сделает.
    docker run -d -P my-nginx
    # А потом смотришь, куда он это пробросил:
    docker port <container_id>
    # И видишь что-то вроде: 80/tcp -> 0.0.0.0:32768

А теперь главное, блядь, уточнение, без которого будет пиздец: Сама по себе инструкция EXPOSE НИХУЯ не открывает порт для доступа с твоего локального компьютера или из интернета. Ноль. Она только говорит, что порт потенциально используется. Это как объявить: «У меня есть дверь», но не сказать, где ключ.

Чтобы порт реально стал доступен, его нужно опубликовать (publish). Для этого есть флаги -p (точное указание) или тот самый -P (автоматическое).

# Ситуация: в Dockerfile есть EXPOSE 80.
# Если запустить вот так, то до порта 80 внутри контейнера можно будет достучаться ТОЛЬКО из других контейнеров в той же Docker-сети. С твоего ноута — никак.
docker run my-nginx

# А вот так — уже можно. Мы явно говорим: «Свяжи порт 8080 на моём хосте с портом 80 внутри контейнера».
docker run -p 8080:80 my-nginx
# Теперь открываешь браузер на localhost:8080 — и всё работает, ёпта.

В разных CI/CD пайплайнах или в оркестраторах вроде Kubernetes эта информация из EXPOSE тоже может пригодиться — системы могут её читать и автоматически настраивать какие-то сетевые правила. Но для базового использования запомни: EXPOSE = декларация, -p = действие. Без второго первое — просто информация для размышления.