Поширене непорозуміння: EXPOSE 80 «відкриває порт». Насправді EXPOSE нічого не відкриває - це документація в метаданих образу: «застосунок у контейнері слухає цей порт».
EXPOSE 8080
Що EXPOSE робить:
- записує порт у метадані образу (
docker image inspect→ExposedPorts); - слугує підказкою для людей і інструментів;
- використовується прапорцем
-P(--publish-all): Docker опублікує всі задекларовані порти на випадкові порти хоста.
Що EXPOSE не робить:
- не публікує порт на хості - без
-pконтейнер недоступний ззовні, зEXPOSEчи без; - не обмежує доступ: інші контейнери в тій самій мережі можуть звертатися до будь-якого порту, на якому слухає процес, - навіть незадекларованого;
- не змушує застосунок слухати цей порт - це має налаштувати сам застосунок.
Публікація порту - при запуску:
docker run -p 8080:80 nginx # хост:8080 → контейнер:80, на всіх інтерфейсах хоста
docker run -p 127.0.0.1:8080:80 nginx # лише локально
# compose
services:
web:
ports:
- "8080:80"
Пастка безпеки з -p 3306:3306: опублікований порт доступний на всіх інтерфейсах хоста (0.0.0.0), тобто з інтернету, якщо сервер має публічну адресу. Docker додає правила в iptables так, що вони можуть обійти налаштування фаєрвола хоста (ufw). Базу й Redis не публікують зовсім - сервіси звертаються до них через мережу Docker - або публікують лише на 127.0.0.1.
Протокол: за замовчуванням TCP; для UDP - EXPOSE 53/udp і -p 53:53/udp.
Чи писати EXPOSE взагалі: так - як документацію: той, хто запускає образ, одразу бачить, який порт слухає застосунок. Але покладатися на нього як на механізм безпеки чи мережі не можна.