Docker'da “ifşa” ve “yayınla” arasındaki fark nedir?


517

Dockerfiles ile denemeler yapıyorum ve mantığın çoğunu anladığımı düşünüyorum. Ancak, bu bağlamda bir portun "teşhir edilmesi" ile "yayınlanması" arasındaki farkı görmüyorum.

Ben ilk gördüğüm tüm öğreticiler EXPOSEDockerfile komutu içerir :

...
EXPOSE 8080
...

Daha sonra bu Dockerfile'dan bir görüntü oluştururlar:

$ docker build -t an_image - < Dockerfile

Ve sonra görüntüyü çalıştırırken yukarıdaki ile aynı bağlantı noktasını yayınlayın :

$ docker run -d -p 8080 an_image

veya kullanarak tüm bağlantı noktalarını yayınlayın

$ docker run -d -P an_image

Yine de yayınlanacaksa, Dockerfile'daki bir bağlantı noktasını göstermenin anlamı nedir? Daha önce bir limanı açığa çıkarmaya ve sonra yayınlamaya gerek olmaz mıydı? Etkili bir şekilde, görüntüyü oluştururken Dockerfile'da kullanacağım tüm bağlantı noktalarını belirtmek ve daha sonra onlarla tekrar uğraşmamak, sadece bunları kullanarak çalıştırmak istiyorum:

$ docker run -d an_image

Mümkün mü?

Yanıtlar:


731

Temel olarak, üç seçeneğiniz vardır:

  1. Ne belirtin EXPOSEne de-p
  2. Sadece belirtin EXPOSE
  3. Belirtin EXPOSEve-p

1) Ne belirttiğinizi ne EXPOSEde belirtirseniz -p, kapsayıcıdaki hizmete yalnızca kapsayıcı içinden erişilebilir .

2) EXPOSEBağlantı noktanız varsa , kapsayıcıdaki hizmete Docker'ın dışından değil, diğer Docker kaplarının içinden erişilebilir. Bu, konteynerler arası iletişim için iyidir.

3) Siz EXPOSEve -pbir bağlantı noktası varsa , kaptaki hizmete Docker'ın dışında bile her yerden erişilebilir.

Her ikisinin de ayrılmasının nedeni IMHO'dur çünkü:

  • bir ana makine bağlantı noktasının seçilmesi ana makineye bağlıdır ve bu nedenle Dockerfile'a ait değildir (aksi halde ana bilgisayara bağlı olacaktır),
  • ve genellikle bir kaptaki bir hizmete diğer kaplardan erişilebiliyorsa yeterlidir.

Dokümantasyon açıkça belirtmektedir:

EXPOSETalimat linkleri içinde kullanılmak için bağlantı noktalarını ortaya çıkarır.

Ayrıca , temelde bahsettiğim konteynerler arası iletişim olan konteynerlerin nasıl bağlanacağına da işaret ediyor.

Not: Yaparsanız -p, ama yapmazsanız EXPOSE, Docker örtük yapar EXPOSE. Bunun nedeni, bir bağlantı noktası halka açıksa, otomatik olarak diğer Docker kaplarına da açık olmasıdır. Dolayısıyla -piçerir EXPOSE. Bu yüzden yukarıda dördüncü bir vaka olarak listelemedim.


57
Bence EXPOSE ile doğru değilsiniz. Diğer kapsayıcılardan, tüm kapsayıcı bağlantı noktalarına maruz kalmadan erişebilirsiniz. Bunu denedim. Buradaki yakalama, kapsayıcı IP adresinin tahmin edilemez olmasıdır. Bağlantının, etkinleştirmek için değil, hangi kapsayıcıyı bağlamak istediğinizi belirtmek için kullanıldığını (belirli kapsayıcı IP'sine bağlandığınızı) düşünüyorum.
Jiri

7
"Onlardan herhangi belirtmezseniz" Eğer birlikte "o" Şunu açıklık eğer yararlı olacağını EXPOSEve -püç mermi noktaları konmuşturlar değil. Biraz kafam karıştı.
Pithikos

4
Eğer belirtmedi: Tamamlanmayan olmak gerekirse, bu cevabı da dördüncü olası vaka ele almalıdır EXPOSE, ama vermedi belirtmek -p. Anladığım kadarıyla, her zaman -payrı kapları kullanır ve çalıştırırsanız EXPOSE, atlamak iyidir, ancak -Pveya kullanılırken yararlı / gerekli hale gelir --link. (Ve başkalarının resminizi nasıl kullanacağını bilmediğiniz için, EXPOSEherkese açık resimlerde belirtilmelidir.)
GrandOpener

6
Dokümanlar artık "EXPOSE talimatı bağlantı noktalarını bağlantılarda kullanılmak üzere açığa çıkarıyor" olarak belirtmiyor.
Lorin Hochstein

11
Downvote çünkü bu büyük ölçüde yanlış. Expose temel olarak belgelerdir ve kullanmamak erişimi kısıtlamaz. Birisi erişimi sınırlamak için ona güvenirse, bu bir dangeros yanlış anlaşılmasıdır.
mc0e

166

Kısa cevap:

  • EXPOSEbelgelemenin bir yolu
  • --publish(veya -p) bir ana makine bağlantı noktasını çalışan bir konteyner bağlantı noktasına eşlemenin bir yoludur

Bunun altında dikkat edin:

  • EXPOSEile ilgili Dockerfiles( belgeleme )
  • --publishile ilgili docker run ...( yürütme / çalışma zamanı )

Portları açığa çıkarma ve yayınlama

Docker ağında, doğrudan ağ bağlantı noktalarını içeren iki farklı mekanizma vardır: bağlantı noktalarını açığa çıkarma ve yayınlama. Bu, varsayılan köprü ağı ve kullanıcı tanımlı köprü ağları için geçerlidir.

  • Bağlantı noktalarını EXPOSEDockerfile'daki anahtar sözcüğü veya --exposedocker çalıştırması için bayrağı kullanarak açığa çıkarırsınız . Bağlantı noktalarını açığa çıkarmak, hangi bağlantı noktalarının kullanıldığını belgelemenin bir yoludur , ancak gerçekte herhangi bir bağlantı noktasını eşlemez veya açmaz . Bağlantı noktalarını göstermek isteğe bağlıdır.

  • Bağlantı noktalarını --publishveya --publish-allişaretini kullanarak yayınlarsınız docker run. Bu, Docker'a kapsayıcının ağ arabiriminde hangi bağlantı noktalarının açılacağını bildirir. Bir bağlantı noktası yayınlandığında, 30000çalışma zamanında ana makinede eşlenecek bağlantı noktasını belirtmediğiniz sürece, ana makine üzerindeki kullanılabilir yüksek dereceli bir bağlantı noktasına (daha yüksek ) eşlenir . Görüntüyü oluştururken (Dockerfile dosyasında) ana makinede eşlenecek bağlantı noktasını belirleyemezsiniz, çünkü bağlantı noktasının görüntüyü çalıştırdığınız ana makinede bulunacağını garanti etmenin bir yolu yoktur .

from: Docker konteyner ağı

Ekim 2019'u güncelleyin : yukarıdaki metin artık dokümanlarda değil, arşivlenmiş bir sürüm burada: docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports

Belki şu anki belgeler aşağıdadır:

Yayınlanan bağlantı noktaları

Varsayılan olarak, bir kapsayıcı oluşturduğunuzda, bağlantı noktalarından hiçbirini dış dünyaya yayınlamaz. Bağlantı noktasını Docker dışındaki hizmetlerin veya kabın ağına bağlı olmayan Docker kapsayıcılarının kullanımına sunmak için --publishveya -pişaretini kullanın . Bu, bir kapsayıcı bağlantı noktasını Docker ana bilgisayarındaki bir bağlantı noktasına eşleyen bir güvenlik duvarı kuralı oluşturur.

ve burada bulunabilir: docs.docker.com/config/containers/container-networking/#published-ports

Ayrıca,

MARUZ BIRAKMAK

... EXPOSETalimat aslında bağlantı noktasını yayınlamıyor . Görüntüyü oluşturan kişi ile kapsayıcıyı çalıştıran kişi arasında, hangi bağlantı noktalarının yayımlanması amaçlandığı arasında bir tür belge işlevi görür .

from: Dockerfile başvurusu






Tanımlanmadığında EXPOSE/ --publishtanımlanmadığında hizmet erişimi :

At @Golo Roden en cevabı o belirtilmektedir ::

"Bunlardan herhangi birini belirtmezseniz, kapsayıcıdaki hizmete, kabın kendisinden başka hiçbir yerden erişilemez."

Belki cevap yazılmış ediliyordu anda böyleydi ama şimdi öyle görünüyor ki kullandığınız dahi EXPOSEya --publish, hostve diğercontainers aynı ağın o kabın içine başlayabilir bir hizmete erişmek mümkün olacak.

Bu nasıl test edilir:

Aşağıdakileri kullandım Dockerfile. Temel olarak, ubuntu ile başlıyorum ve küçük bir web sunucusu yüklüyorum:

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd

Ben buildgörüntü "testexpose" ve runyeni bir kapsayıcı olarak:

docker run --rm -it testexpose bash

Konteynerin içinde birkaç örnek açtım mini-httpd:

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090

Sonra curlana sayfasını almak için ana bilgisayardan veya diğer kapsayıcılar kullanabilirsiniz mini-httpd.


16
bu şimdi doğru cevap. Kabul edilen cevap önceki versiyonlara dayanıyor gibi görünüyor.
Luke W

kıvırmak için kullandığınız ana bilgisayar bağlantı noktası nedir?
beyin fırtınası

Konteynerin IP'sini (bir şey gibi 172.17.0.2) ve bahsettiğim tüm portları kullandım. Mac / Windows için Docker kullanıyorsanız, ağ iletişimi farklıdır. docker0Köprü yok .
tgogos

"-P" bayrağıyla tüm EXPOSEd bağlantı noktalarını yayınlarken, ana bilgisayarda hangi bağlantı noktasının kullanıldığını nasıl anlayabilirim?
sixty4bit


9

Resmi dokümantasyon referansına bakın: https://docs.docker.com/engine/reference/builder/#expose

EXPOSEEğer konteyner çalışırken için görüntü oluşturma sırasında açığa özel (konteyner) ve kamu (ana bilgisayar) bağlantı noktalarını tanımlamak için izin eğer sen kabı çalıştırın -P.

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

Ortak bağlantı noktası ve protokol isteğe bağlıdır, genel bağlantı noktası belirtilmezse, Dockerfile üzerinde belirtilen kapsayıcı bağlantı noktasını göstermek için docker tarafından ana bilgisayarda rasgele bir bağlantı noktası seçilir.

İyi bir uygulama genel bağlantı noktası belirtmez, çünkü ana bilgisayar başına yalnızca bir kapsayıcı sınırlar (ikinci bir kapsayıcı zaten kullanımda olan bir bağlantı noktasını atar).

Sen kullanabilirsiniz -piçinde docker runmaruz konteyner limanları bağlanabilen ne olacağını kamu liman kontrol etmek.

Her neyse, EXPOSE( -Pliman işçisindeyken) kullanmazsanız veya -phiçbir bağlantı noktası gösterilmez.

Hep kullanırsanız -pde docker runsizin değil gereğini yapmak EXPOSEancak kullanırsanız EXPOSEsizin docker rundaha basit olabilir komutu, EXPOSEsen liman ana bilgisayarda maruz olacak umurumda değil yararlı olabilir ya da sadece bir kabın eminseniz yüklenecektir.


doğru. Dockerfile içinde EXPOSE portNumber varsa, -P ile docker çalıştırmayı çağırmayı unutmayın.
KunYu Tsai

6

Bağlantı noktalarını Dockerfile'daki EXPOSE anahtar sözcüğünü veya --expose bayrağını kullanarak docker çalıştırmasına maruz bırakırsınız. Bağlantı noktalarını ortaya çıkarmak, hangi bağlantı noktalarının kullanıldığını belgelemenin bir yoludur, ancak gerçekte herhangi bir bağlantı noktasını eşlemez veya açmaz. Bağlantı noktalarını göstermek isteğe bağlıdır.

Kaynak: github


3

Çoğu kişi docker oluşturmayı ağlarla kullanır. Dokümantasyon durumları:

Docker ağ özelliği, ağ içindeki bağlantı noktalarını açmaya gerek kalmadan ağ oluşturmayı destekler, ayrıntılı bilgi için bu özelliğe genel bakış konusuna bakın).

Bu, kapsayıcılar arasında iletişim için ağlar kullanırsanız, bağlantı noktalarını açığa çıkarmak için endişelenmenize gerek olmadığı anlamına gelir.


-5

EXPOSE, yerel bağlantı noktası kapsayıcı bağlantı noktasını eşlemek için kullanılır; örneğin: docker dosyasında açıkta belirtme

EXPOSE 8090

Ne yapacak, localhost portu 8090'ı konteyner portu 8090 ile eşleyecek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.