기존 Docker 컨테이너에 포트 매핑을 어떻게 할당합니까?


436

여기에서 뭔가 잘못 이해했는지 확실하지 않지만 이미지에서 새 컨테이너를 만들어 포트 매핑을 설정하는 것이 가능한 것처럼 보입니다. 기존 Docker 컨테이너에 포트 매핑을 할당하는 방법이 있습니까?


3
iptables를 사용하면 다음과 같이 작동 할 수 있습니다 . Live Docker 컨테이너에 포트 노출
Choldrim

2
나는 이것이 의도적이라고 생각합니다. Docker는 사용자가 "반복 가능"하도록 강요하려고하며 컨테이너는 "기록 시스템"의 한 유형입니다. 컨테이너에 영향을 미치지 않는 단계로 수행하는 모든 작업은 쉽게 수동 단계를 잃게됩니다. 다른 방법 : 컨테이너가 작동하는 데 필요한 모든 구성을 나타내기를 원합니다. 따라서 새 포트를 열려면 새 컨테이너를 만들어야합니다.
랜스 종류

2
오래된 질문에 대답하지는 않지만이 질문과 답변을지지하는 사람들과 사람들이 도커의 개념을 완전히 이해하지 못했을 수 있습니다. Docker는 여러 번 확장하거나 축소 할 수있는 상태 비 저장 응용 프로그램 용입니다. 다시 만들 수없는 프로덕션 환경을 위해 컨테이너 내부에 무언가를 유지해서는 안되며, 유지해야 할 경우 디렉토리를 매핑하십시오. Docker는 "light vm"과 같은 것이 아니며 아마도 linuxcontainers.org 일 것입니다. lxd는 docker 개념을 기반으로하지만 "light vm"을 염두에두고 있습니다.
Edgar Carvalho

이것이 도움이 될 수있는 경우, "Kitematic"도구를 사용하여 이미 실행중인 컨테이너에 포트 매핑을 추가 할 수 있습니다. 이것은 정확히 같은 일을하지만 약간의 인터넷 검색을 수행하는 docker 명령이 있어야 함을 암시해야합니다. : 행운
Yaffah

답변:


298

에서 hostconfig.json파일을 직접 편집하여 포트 매핑을 변경할 수 있습니다/var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

docker inspect <container_name>명령을 통해 [hash_of_the_container]를 결정할 수 있으며 "Id"필드의 값은 해시입니다.

1) stop the container 
2) stop docker service (per Tacsiazuma's comment)
3) change the file
4) restart your docker engine (to flush/clear config caches)
5) start the container

따라서이 방법으로 이미지를 만들 필요가 없습니다. 여기서 재시작 플래그를 변경할 수도 있습니다.

PS https://docs.docker.com/engine/admin/ 을 방문 하여 호스트 시스템에 따라 도커 엔진을 올바르게 다시 시작하는 방법을 배울 수 있습니다 . 내가 사용하는 sudo systemctl restart docker우분투 16.04에서 실행되는 내 고정 표시기 엔진을 다시 시작


17
도 커가 중지되면 변경 사항을 덮어 쓰는 것처럼 보이므로 2. 도커 중지, 3. 파일 변경, 4. 도커 엔진 시작
Tacsiazuma

5
나는 위의 시도하고 작동합니다. 자세한 내용은 다음을 참조하십시오 mybrainimage.wordpress.com/2017/02/05/...
rohitmohta

11
그것은 용기, 정지 고정 표시기 엔진과 변화 모두를 중지하는 것이 중요 hostconfig.json하고 config.v2.json이 작업을 할 수 있습니다. 자세한 내용을 보려면 @rohitmohta에서 제공 한 링크를 사용하십시오.
Kalpak Gadre

5
: Mac에서 고정 표시기 응용 프로그램을 사용하여, / lib 디렉토리 / 고정 표시기 / 용기 폴더 / var에 얻을 여기 지침을 따르는 경우에, 저를 위해 한 일을 일 stackoverflow.com/a/41226917/2048266 기본적으로 실행 screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty을 실행하는 TTY를 할 수 얻을 일단 당신 / var / lib / docker로 이동
nommer

14
Windows의 경우 누구든지 conatiners 폴더의 위치를 ​​공유 할 수 있습니까?
Vijay

463

나는 또한이 문제에 관심이있다.

으로 @Thasmo이 언급 한, 포트 포워딩 만 지정할 수 있습니다 docker run(와 docker create) 명령.
다른 명령 docker start-p옵션 이 없으며 docker port현재 전달 만 표시합니다.

포트 전달을 추가하려면 항상 다음 단계를 따르십시오.

  1. 컨테이너 실행 중지

    docker stop test01
    
  2. 컨테이너를 커밋

    docker commit test01 test02
    

    참고 :test02test01컨테이너 에서 구성하는 새로운 이미지입니다 .

  3. 커밋 된 이미지에서 다시 실행

    docker run -p 8080:8080 -td test02
    

여기서 첫 번째 8080은 로컬 포트이고 두 번째 8080은 컨테이너 포트입니다.


15
test01 이름을 유지하려면 어떻게합니까?
user69715

12
누구든지 Docker에 개방형 문제가 있는지 알고 docker start있습니까?
Elijah Lynn

8
이 시나리오에서 볼륨은 어떻게됩니까?
앤드류 Savinykh

78
이것은 끔찍한 해결책입니다. 어떻게 250 upvotes를 얻었는지 모르겠습니다. 어쩌면 공감 한 사람들은이 솔루션이 어떤 종류의 혼란을 초래하는지 알지 못했습니다. 예, 끔찍하며 다른 포트에서 실행되는 새 컨테이너를 시작하는 것과 같습니다.
Arrrr

25
@Arrrr 아마도 더 나은 답변을 남기고 싶습니까? 당신이 우리에게 이것을하는 더 좋은 방법을 말하면 우리 모두에게 감사 할 것입니다.
crockeea

40

"존재"가 "실행 중"을 의미하는 경우 (현재) 포트 매핑을 추가 할 수 없습니다.

그러나 서비스를 중지 / 다시 시작하지 않고 실행중인 컨테이너에 서비스를 노출해야하는 경우 Pipework 와 같은 새 네트워크 인터페이스를 동적으로 추가 할 수 있습니다 .


4
이것이 최고의 답변이되어야합니다. 간결하고 그것은 OP의 문제를 해결합니다. 때때로 부정적인 결과가 결과입니다!
부분적으로 흐린

19

실행중인 컨테이너에 포트 매핑을 적용 할 수 있는지 확실하지 않습니다. 새 컨테이너를 만드는 것과 다른 컨테이너를 실행하는 동안 포트 전달을 적용 할 수 있습니다.

$ docker run -p <public_port>:<private_port> -d <image>  

컨테이너 실행을 시작합니다. 이 자습서에서는 포트 리디렉션에 대해 설명합니다.


2
따라서 컨테이너 생성시 포트 매핑과 같은 옵션 만 설정할 수있는 것 같습니다.
thasmo

20
참고로이 답변은 완전히 정확하지 않습니다. docker run새 컨테이너를 작성하고 시작합니다. docker create다음에 수행하는 것과 같습니다 docker start.
Trevor Sullivan

19

hostconfig.json을 수정 하면 지금 작동하지 않는 것 같습니다. 해당 포트만 노출되지만 호스트에 게시되지는 않습니다. 컨테이너를 커밋하고 재생성하는 것이 최선의 방법은 아닙니다. 아무도 언급하지 않았 docker network습니까?

가장 좋은 솔루션은 동일한 네트워크 내에서 역방향 프록시를 사용하는 것입니다

  1. 이전 컨테이너가 명명 된 컨테이너에없는 경우 새 네트워크를 만듭니다.

    docker network create my_network

  2. 기존 컨테이너를 생성 된 네트워크에 가입

    docker network connect my_network my_existing_container

  3. 동일한 네트워크에 가입하여 필요한 포트를 게시하는 역방향 프록시 서비스 (예 : nginx)를 시작하십시오.

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    선택적 으로 nginx 에서 default.conf 를 제거하십시오

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. 새로운 nginx 설정 생성

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    구성을 nginx 컨테이너에 복사하십시오.

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. nginx를 다시 시작하십시오

    docker restart nginx

장점 : 새로운 포트를 게시하기 위해 비즈니스 컨테이너를 건드리지 않고 원하는대로 nginx 컨테이너를 안전하게 중지 / 업데이트 / 재 작성할 수 있습니다. nginx에 대한 다운 타임이 0 인 경우 동일한 네트워크에 참여하는 더 많은 프록시 서비스를 추가 할 수 있습니다. 또한 컨테이너는 둘 이상의 네트워크에 참여할 수 있습니다.

편집하다:

http가 아닌 프록시 서비스를 되돌리려면 구성 파일이 약간 다릅니다. 다음은 간단한 예입니다.

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}

1
놀랍고 실용적이지만 엔터프라이즈 시스템의 경우이 접근법은 난독 한 것으로 보입니다. 단일 시스템이 워크 플로우를 제어하게하는 것이 훨씬 더 좋습니다.
Afshin

1
@Afshin 엔터프라이즈 시스템이나 프로젝트의 경우이 솔루션이 재 작성 (다운 타임 발생) 또는 hostconfig.json 파일 해킹 (적어도 공식적으로 소개되지 않음)보다 낫습니다. 추가 컨테이너는 비즈니스 컨테이너의 내부 포트를 변경하지 않고 노출시킵니다.
Sean C.

1
멋진 접근법. 컨테이너가 프록시 뒤에서 작동하도록 nginx를 다르게 구성해야했지만 올바른 작업 방법처럼 보입니다. 청록색 배포에도 작동합니다.
Brooks DuBois 2016 년

18

Fujimoto Youichi의 ​​예 test01는 컨테이너이지만 test02이미지입니다.

수행하기 전에 docker run원래 컨테이너를 제거한 다음 컨테이너에 동일한 이름을 다시 지정할 수 있습니다.

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

( -P수동 할당 대신 임의의 포트에 포트를 노출하는 데 사용).


12
알아 두십시오. 내부 애플리케이션에 따라 모든 데이터를 잃게됩니다.
Barry

14

실행 docker run <NAME>하면 새로운 이미지가 생성되며 원하는 이미지가 아닐 수 있습니다.

현재 이미지를 변경하려면 다음을 수행하십시오.

docker ps -a

대상 컨테이너의 ID를 가져 와서 다음으로 이동하십시오.

cd /var/lib/docker/containers/<conainerID><and then some:)>

컨테이너를 중지하십시오.

docker stop <NAME>

파일 변경

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

그리고 파일 변경

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

도커를 다시 시작하면 작동합니다.


2
Docker 버전 17.09.0-ce에서는 작동하지 않았습니다. 컨테이너 구성 파일을 시작한 후 이전 값으로 다시 덮어 썼습니다.
thegeko

3
호스트 시스템 @thegeko에서 다시 시작 고정 표시기 서비스
yurenchen

1
이 작동합니다! tks! 1.stop 용기, 2.change 파일, 3.restart 고정 표시기, 4.start 백 컨테이너
datdinhquoc

12

Docker 깊이 구성 IPtable에 익숙하지 않은 경우 다른 방법으로 친구가 될 수 있습니다.

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

이것은 컨테이너를 멈출 수 없기 때문에 이것이 내 시나리오에서 작동하는 권장 방법이 아닌 트릭입니다.


이것은 좋은 대답입니다! 감사합니다! 에 매핑 DOCKER_PORT하려면 MACHINE_PORT어떤 부분을 변경해야합니까?
Ciprian Tomoiagă

도커는이 수동 추가에 대해 알지 못합니다. Docker가 포트를 올바르게 노출시켜 나중에 서비스를 다시 시작할 때 SO 항목이 제거되지 않습니다. 따라서 변경 사항이 있으면 iptables를 매우 신중하게 확인하십시오. 특히 중복 항목을 찾으십시오!
앤서니

8

우리는 이것을 쉽게 달성하기 위해 ssh와 같은 편리한 도구를 사용합니다.

우분투 호스트와 우분투 기반 도커 이미지를 사용하고있었습니다.

  1. 내부 도커에는 openssh-client가 설치되어 있습니다.
  2. 외부 도커 (호스트)에는 openssh 서버 서버가 설치되어 있습니다.

새 포트를 매핑해야 할 때

도커 내부에서 다음 명령을 실행하십시오.

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1은 docker 인터페이스의 IP였습니다 ( ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "호스트에서 실행 하여 얻을 수 있음 ).

여기에 로컬 8888 포트가 호스트 8888에 다시 매핑되었습니다. 필요에 따라 포트를 변경할 수 있습니다.

하나 이상의 포트가 필요한 경우 새 포트를 사용하여 ssh를 종료하고 -R 라인을 하나 더 추가 할 수 있습니다.

나는 netcat으로 이것을 테스트했다.


2
  1. 도커 엔진과 해당 컨테이너를 중지하십시오.
  2. /var/lib/docker/containers/${container_id}디렉토리로 이동하여 편집hostconfig.json
  3. PortBindings.HostPort변경을 원하는 것으로 편집하십시오 .
  4. 도커 엔진 및 컨테이너를 시작하십시오.

-1

Windows 및 Mac 사용자의 경우 매핑 포트를 변경하는 매우 쉽고 친숙한 또 다른 방법이 있습니다.

  1. kitematic 다운로드

  2. 컨테이너의 설정 페이지로 이동하여 포트 탭에서 게시 된 포트를 직접 수정할 수 있습니다.

  3. 컨테이너를 다시 시작하십시오


2
나는이 접근법을 시도했다. 키네마 틱은 실제로 포트 매핑을 적용했습니다. 그러나 그것들을 적용하기 위해 원본 이미지에서 컨테이너를 다시 만들었습니다. 따라서 컨테이너 자체의 변경 사항을 잃어 버릴 염려가 있으면이 방법을 사용하지 마십시오.
VeganHunter

1
나는 이것을 선호했는데 질문에 대답하지 않고 새 컨테이너를 만듭니다. 그러나 적어도 효과가 있으며이 검색 결과는 내 검색 중에 나타났습니다. +1
2b77bee6-5445-4c77-b1eb-4df3e5 19

-7

짧은 답변 : 기존 Docker 컨테이너에 포트 매핑을 할당 할 수 없습니다

새 컨테이너가 필요합니다.


4
태도가 필요 없습니다. 또한이 답변에는 세부 사항이 완전히 없습니다.
lovefaithswing

1
세부 사항이 필요하지 않습니다. 톤은이 시간 절약 답변과 임시 컨테이너의 특성을 전달하는 데 중요합니다.
stephen

-11

단순히 실행중인 컨테이너의 포트를 변경하려면 다음을 수행하십시오.

  1. 기존 컨테이너 중지

    sudo docker stop NAME

  2. 이제 새로운 포트 매핑으로 다시 시작

    sudo docker run -d -p 81:80 이름

어디서?

"-d"를 도커 배경 / 데몬으로

"-p"포트 매핑 활성화

브라우저로 액세스하는 데 사용하는 "81"외부 (노출) 포트

"80"내부 도커 컨테이너 청취 포트


4
이것은 단지 잘못이다. 에서 docker run명령 NAME에 반해에서 컨테이너를 실행하는 화상의 이름 docker stop(가) NAME정지 용기의 이름을 말한다는.
jonatan

1
"docker run"은 새 컨테이너를 만듭니다. 해당 이름의 컨테이너를 하나만 가질 수 있으므로 중지 된 컨테이너 이름과 동일한 컨테이너 이름을 사용할 수 없습니다. 따라서 "docker stop NAME", 도커 컨테이너 rm NAME, "docker run -d -p 81:80 NAME"을 작성해야합니다.
랜스 종류
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.