Коротка відповідь:
EXPOSE- це спосіб документування
--publish(Або -p) є способом відображення на хост - порт до включеному контейнерного порту
Зауважте нижче:
EXPOSEпов'язаний з Dockerfiles( документування )
--publishпов'язано з docker run ...( виконання / час виконання )
Розкриття та публікація портів
У мережах Docker є два різних механізми, які безпосередньо включають мережеві порти: відкриття та публікація портів. Це стосується мостової мережі за замовчуванням та визначених користувачем мостових мереж.
Ви відкриваєте порти, використовуючи EXPOSEключове слово в Dockerfile або --exposeпрапор для запуску докера . Розкриття портів - це спосіб документувати, які порти використовуються, але насправді не відображає та не відкриває жодних портів . Розкривати порти необов’язково.
Ви публікуєте порти, використовуючи --publishабо --publish-allпрапор для docker run. Це повідомляє Docker, які порти відкривати в мережевому інтерфейсі контейнера. Коли порт публікується, він відображається на доступний порт високого замовлення (вище, ніж 30000) на хост-машині, якщо ви не вказали порт, для якого потрібно виконати карту на хост-машині під час виконання. Ви не можете вказати порт, на який буде розміщено карту на хост-машині під час створення зображення (у Dockerfile), оскільки немає способу гарантувати, що порт буде доступний на хост-машині, де ви запускаєте зображення .
від: Мережа контейнерів Docker
Оновлення жовтня 2019 року : вищевказаний фрагмент тексту більше не міститься в документах, але тут знаходиться архівована версія: docs.docker.com/v17.09/engine/userguide/networking/#exposed-and-publishing-ports
Можливо, поточна документація наведена нижче:
Опубліковані порти
За замовчуванням, коли ви створюєте контейнер, він не публікує жодного зі своїх портів у зовнішній світ. Щоб зробити порт доступним для служб за межами Docker або контейнерів Docker, які не підключені до мережі контейнера, використовуйте прапор --publishабо -p. Це створює правило брандмауера, яке відображає порт контейнера на порт хоста Docker.
і їх можна знайти тут: docs.docker.com/config/containers/container-networking/#publish-ports
Також,
ВИДАЧА
... EXPOSEІнструкція фактично не публікує порт . Він функціонує як тип документації між людиною, яка створює зображення, і особою, яка управляє контейнером, про які порти призначені для публікації.
від: Довідкова довідка
Доступ до послуг, коли EXPOSE/ --publishне визначено:
У відповіді @Golo Roden зазначено, що:
"Якщо ви не вкажете жодного з них, послуга в контейнері не буде доступна з будь-якого місця, за винятком всередині самого контейнера."
Можливо, це було саме в той момент, коли писалася відповідь, але зараз здається, що навіть якщо ви не використовуєте EXPOSEабо --publish, hostта інcontainers з тих же мереж , матиме можливість доступу до послуги ви можете почати всередині цього контейнера.
Як це перевірити:
Я використав наступне Dockerfile. В основному я починаю з ubuntu і встановлюю крихітний веб-сервер:
FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd
Я buildзображую як "testexpose" і runновий контейнер з:
docker run --rm -it testexpose bash
Всередині контейнера я запускаю кілька примірників mini-httpd:
root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090
Тоді я можу використовувати curlз хоста чи інших контейнерів, щоб отримати домашню сторінку mini-httpd.