Docker에서 "노출"과 "게시"의 차이점은 무엇입니까?


517

Dockerfiles를 실험 중이며 대부분의 논리를 이해한다고 생각합니다. 그러나이 컨텍스트에서 포트를 "노출"과 "게시"하는 것의 차이점은 보이지 않습니다.

내가 본 모든 튜토리얼 EXPOSE은 Dockerfile에 다음 명령을 포함합니다 .

...
EXPOSE 8080
...

그런 다음이 Dockerfile에서 이미지를 작성합니다.

$ docker build -t an_image - < Dockerfile

그런 다음 이미지를 실행할 때 위와 동일한 포트 를 게시 하십시오.

$ docker run -d -p 8080 an_image

또는 모든 포트를 사용하여 게시

$ docker run -d -P an_image

Dockerfile에 포트가 노출 될 경우 포트가 노출되는 시점은 무엇입니까? 포트를 먼저 노출하고 나중에 게시 하지 않아야 합니까? 효과적으로, 이미지를 만들 때 Dockerfile에서 사용할 모든 포트를 지정한 다음 다시 방해하지 않고 간단히 다음과 같이 실행합니다.

$ docker run -d an_image

이것이 가능한가?

답변:


731

기본적으로 세 가지 옵션이 있습니다.

  1. 지정 EXPOSE하거나 지정 하지 마십시오-p
  2. 지정 만 EXPOSE
  3. 지정 EXPOSE하고-p

1) 당신은 지정하지 둘 경우 EXPOSE-p, 컨테이너의 서비스는에서 액세스 할 수 있습니다 내부 컨테이너 자체.

2) EXPOSE포트 인 경우 컨테이너의 서비스는 Docker 외부가 아니라 다른 Docker 컨테이너 내부에서 액세스 할 수 있습니다. 컨테이너 간 통신에 좋습니다.

3) 귀하 EXPOSE-p포트 인 경우 컨테이너의 서비스는 Docker 외부에서도 어디서나 액세스 할 수 있습니다.

두 가지가 분리 된 이유는 다음과 같은 이유로 IMHO입니다.

  • 호스트 포트 선택은 호스트에 따라 다르므로 Dockerfile에 속하지 않습니다 (그렇지 않으면 호스트에 따라 다름).
  • 컨테이너의 서비스를 다른 컨테이너에서 액세스 할 수 있으면 충분합니다.

문서는 명시 적으로 상태 :

EXPOSE명령은 링크 내에서 사용할 포트를 제공합니다.

또한 컨테이너연결 하는 방법을 알려줍니다. 기본적으로 내가 이야기 한 컨테이너 간 통신입니다.

추신 : 당신이 -p하지는 않지만 EXPOSEDocker는 암시 적을 수행합니다 EXPOSE. 포트가 공개적으로 열려 있으면 다른 Docker 컨테이너에도 자동으로 열려 있기 때문입니다. 따라서 -p포함됩니다 EXPOSE. 그렇기 때문에 위의 네 번째 사례로 나열하지 않았습니다.


57
EXPOSE가 틀렸다고 생각합니다. 다른 컨테이너에서 모든 컨테이너 포트를 노출하지 않고 액세스 할 수 있습니다. 나는 그것을 시도했다. 여기서 중요한 점은 컨테이너 IP 주소를 예측할 수 없다는 것입니다. 연결을 활성화하지 않고 연결하려는 컨테이너를 지정하기 위해 링크가 사용된다고 믿습니다 (따라서 특정 컨테이너 IP에 연결).
Jiri

7
"당신이 그 중 하나를 지정하지 않으면"당신이 "사람들은"당신이 의미있는 것이 분명하면 유용 할 수 EXPOSE-p와 세 개의 총알 점은 이미 기재하지. 조금 혼란스러워했습니다.
Pithikos

4
당신은 지정하지 않은 : 완전히 완료하려면이 대답은 네 번째 가능한 경우를 해결해야한다 EXPOSE,하지만 당신은 않았다 지정합니다 -p. 그것은 당신이 항상 사용하는 경우 나의 이해의 -p개별 용기를 실행 한 후 EXPOSE생략 괜찮지 만 사용하는 경우는 / 도움이 필요하게 -P--link. (그리고 당신은 다른 사람들이 당신의 이미지를 어떻게 사용할지 모르기 때문에 EXPOSE공개 이미지로 지정해야합니다.)
GrandOpener

6
문서에서 더 이상 "EXPOSE 명령어는 링크 내에서 사용할 포트를 노출합니다"라고 표시하지 않습니다.
Lorin Hochstein

11
이것이 실질적으로 올바르지 않기 때문에 공감. Expose는 기본적으로 문서이며 사용하지 않으면 액세스가 제한되지 않습니다. 누군가가 액세스를 제한하기 위해 의존한다면 이것은 오해의 위험입니다.
mc0e

166

짧은 답변:

  • EXPOSE문서화 하는 방법입니다
  • --publish(나 -p)의 방법 으로 매핑 호스트 포트를 실행에 컨테이너 포트

아래에 주목하십시오 :

  • EXPOSE관련 Dockerfiles( 문서화 )
  • --publish관련 docker run ...( 실행 / 런타임 )

포트 노출 및 게시

Docker 네트워킹에는 네트워크 포트를 직접 포함하는 두 가지 메커니즘, 즉 포트 노출 및 게시가 있습니다. 이는 기본 브리지 네트워크 및 사용자 정의 브리지 네트워크에 적용됩니다.

  • EXPOSEDockerfile 의 키워드 또는 --exposedocker run 의 플래그를 사용하여 포트를 노출 합니다. 포트 노출 은 사용되는 포트 를 문서화 하는 방법 이지만 실제로 포트를 매핑하거나 열지는 않습니다 . 포트 노출은 선택 사항입니다.

  • --publish또는 --publish-all플래그를 사용하여 포트를 게시 합니다 docker run. 이것은 Docker에게 컨테이너의 네트워크 인터페이스에서 열 포트를 알려줍니다. 포트가 게시 될 때 30000런타임에 호스트 시스템에 매핑 할 포트를 지정하지 않는 한 포트는 호스트 시스템에서 사용 가능한 상위 포트 (보다 큼 )에 매핑됩니다. 이미지를 빌드 할 때 (Dockerfile에서) 이미지를 실행하는 호스트 시스템에서 포트를 사용할 수 있는지 보장 할 방법없기 때문에 호스트 시스템에서 맵핑 할 포트를 지정할 수 없습니다 .

from : 도커 컨테이너 네트워킹

2019 년 10 월 업데이트 : 위의 텍스트는 더 이상 문서에 없지만 보관 된 버전은 다음과 같습니다. docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports

현재 문서는 다음과 같습니다.

게시 된 포트

기본적으로 컨테이너를 만들면 해당 컨테이너의 포트가 외부에 게시되지 않습니다. Docker 외부의 서비스 또는 컨테이너 네트워크에 연결되지 않은 Docker 컨테이너에서 포트를 사용 가능하게하려면 --publish또는 -p플래그를 사용하십시오 . 컨테이너 포트를 Docker 호스트의 포트에 매핑하는 방화벽 규칙을 만듭니다.

docs.docker.com/config/containers/container-networking/#published-ports 에서 찾을 수 있습니다.

또한,

폭로

... EXPOSE명령 은 실제로 포트를 게시하지 않습니다 . 이미지를 작성하는 사람과 컨테이너를 실행하는 사람 사이에서 공개 할 포트에 대한 문서 유형으로 작동합니다.

from : Dockerfile 참조






EXPOSE/ --publish가 정의되지 않은 경우 서비스 액세스 :

에서 @Golo 로덴의 대답은 그것은 것을 주장한다 ::

"이 중 하나를 지정하지 않으면 컨테이너 내부의 서비스를 제외하고는 컨테이너의 서비스에 액세스 할 수 없습니다."

어쩌면 답이 기록되는 당시 사건이었다,하지만 지금은 사용하지 않는 경우에도 것 같습니다 EXPOSE또는 --publishhost다른 containers같은 네트워크의 사용자가 해당 컨테이너 안에 시작할 수있는 서비스에 액세스 할 수 있습니다.

이것을 테스트하는 방법 :

나는 다음을 사용했다 Dockerfile. 기본적으로 우분투로 시작하여 작은 웹 서버를 설치합니다.

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있습니다.


16
이것은 이제 정답입니다. 허용 된 답변은 이전 버전을 기반으로합니다.
Luke W

curl에 사용한 호스트 포트는 무엇입니까?
brain storm

컨테이너의 IP (와 같은 것 172.17.0.2)와 내가 언급 한 모든 포트를 사용했습니다. Mac / Windows 용 Docker를 사용하는 경우 네트워킹이 다릅니다. docker0다리 가 없습니다 .
tgogos

"-P"플래그를 사용하여 모든 EXPOSEd 포트를 게시 할 때 호스트에서 사용되는 포트를 어떻게 알 수 있습니까?
sixty4bit

1
@ sixty4bit이 질문을 살펴보십시오 : Docker가 선택한 임의의 포트를 어떻게 알 수 있습니까? .
tgogos

9

공식 문서 참조를 참조하십시오 : https://docs.docker.com/engine/reference/builder/#expose

EXPOSE당신이 컨테이너가 실행 중일 때의 이미지 빌드시에 노출 개인 (용기)과 공공 (호스트) 포트를 정의 할 수 있습니다 경우 당신이 용기를 실행합니다 -P.

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

공개 포트 및 프로토콜은 선택 사항입니다. 공개 포트가 지정되지 않은 경우 Docker가 호스트에서 임의의 포트를 선택하여 Dockerfile의 지정된 컨테이너 포트를 표시합니다.

호스트 당 하나의 컨테이너 만 제한하므로 공용 포트를 지정하지 않는 것이 좋습니다 (두 번째 컨테이너는 이미 사용중인 포트를 처리 함).

당신은 사용할 수 있습니다 -pdocker run노출 된 용기 포트가 연결 가능한 일 무슨 공공 포트를 제어 할 수 있습니다.

어쨌든 EXPOSE( -P도커 실행시) 또는 -p을 사용하지 않으면 포트가 노출되지 않습니다.

항상 사용하는 경우 -pdocker run당신이 할 필요가 수행 EXPOSE하지만, 당신이 사용하는 경우 EXPOSE당신 docker run더 간단 할 수있다 명령을 EXPOSE사용하면 포트가 호스트에 노출 될 것을 걱정하지 않는 경우에 유용 할 수 있습니다, 또는 당신은 단지 하나의 컨테이너의 확신하는 경우로드됩니다.


이것이 맞습니다. Dockerfile에 EXPOSE portNumber가 있으면 -P를 사용하여 docker run을 호출해야합니다.
KunYu Tsai

6

Dockerfile의 EXPOSE 키워드 또는 --expose 플래그를 사용하여 포트를 docker run에 노출합니다. 포트 노출은 사용되는 포트를 문서화하는 방법이지만 실제로는 포트를 맵핑하거나 열지 않습니다. 포트 노출은 선택 사항입니다.

출처 : github commit


3

대부분의 사람들은 도커 작성 네트워크를 사용합니다. 설명서 에는 다음 이 명시되어 있습니다.

Docker 네트워크 기능은 네트워크 내에서 포트를 노출 할 필요없이 네트워크 생성을 지원합니다. 자세한 내용은이 기능의 개요를 참조하십시오).

컨테이너 간 통신에 네트워크를 사용하는 경우 포트 노출에 대해 걱정할 필요가 없습니다.


-5

EXPOSE는 로컬 포트 ​​컨테이너 포트를 매핑하는 데 사용됩니다. 즉, docker 파일에 노출을 지정하면

EXPOSE 8090

localhost 포트 8090을 컨테이너 포트 8090에 매핑합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.