라이브 Docker 컨테이너에 포트 노출
완전한 가상 머신처럼 작동하는 Docker 컨테이너를 만들려고합니다. Dockerfile 내에서 EXPOSE 명령을 사용하여 포트를 노출 할 수 있으며 -p
with 플래그를 사용하여 docker run
포트를 할당 할 수 있지만 컨테이너가 실제로 실행되면 추가 포트를 열거 나 매핑하는 명령이 있습니까?
예를 들어 sshd를 실행하는 Docker 컨테이너가 있다고 가정 해 봅시다. 컨테이너 ssh를 사용하는 다른 사람이 httpd를 설치하고 설치합니다. 컨테이너에서 포트 80을 노출하고 호스트에서 포트 8080으로 매핑하여 컨테이너에서 다시 시작하지 않고도 컨테이너에서 실행되는 웹 서버를 방문 할 수있는 방법이 있습니까?
Docker를 통해이 작업을 수행 할 수는 없지만 호스트 시스템에서 컨테이너의 노출되지 않은 포트에 액세스 할 수 있습니다.
포트 8000에서 실행중인 컨테이너가있는 경우 다음을 실행할 수 있습니다.
wget http://container_ip:8000
컨테이너의 IP 주소를 얻으려면 다음 두 명령을 실행하십시오.
docker ps
docker inspect container_name | grep IPAddress
내부적으로 Docker는 이미지를 실행할 때 iptables를 호출하기 위해 껍질을 벗기므로 약간의 변형이 가능합니다.
로컬 호스트 포트 8001에서 컨테이너의 포트 8000을 노출하려면 :
iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000
이것을 해결할 수있는 한 가지 방법은 원하는 포트 매핑으로 다른 컨테이너를 설정하고 iptables-save 명령 의 출력을 비교하는 것입니다 (트래커가 트래픽을 도커를 통과하도록 강제하는 다른 옵션 중 일부를 제거해야했습니다) 대리).
참고 : 이것은 도커를 파괴하는 것이므로 푸른 연기를 생성 할 수 있다는 인식으로 수행해야합니다
또는
또 다른 대안은 무작위 호스트 포트를 사용하는 (새로운? post 0.6.6?) -P 옵션을 확인한 다음 연결하는 것입니다.
또는
0.6.5에서는 LINKs 기능을 사용하여 기존 컨테이너와 대화하는 새 컨테이너를 가져올 수 있으며 컨테이너의 -p 플래그에 대한 추가 릴레이가 있습니까? (아직 LINK를 사용하지 않았습니다)
또는
도커 0.11? docker run --net host ..
컨테이너를 호스트의 네트워크 인터페이스에 직접 연결 하는 데 사용할 수 있습니다 (즉, net은 이름 간격이 아님). 따라서 컨테이너에서 연 모든 포트가 노출됩니다.
내가 할 일은 다음과 같습니다.
- 라이브 컨테이너를 커밋하십시오.
- 포트가 열린 상태에서 새 이미지로 컨테이너를 다시 실행하십시오 (공유 볼륨을 마운트하고 ssh 포트도 여는 것이 좋습니다)
sudo docker ps
sudo docker commit <containerid> <foo/live>
sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t <foo/live> /bin/bash
기존 컨테이너 의 새 포트를 노출 할 수는 없지만 동일한 Docker 네트워크에서 새 컨테이너를 시작하고 트래픽을 원래 컨테이너로 전달할 수 있습니다.
# docker run \
--rm \
-p $PORT:1234 \
verb/socat \
TCP-LISTEN:1234,fork \
TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT
작동 예
포트 80에서 수신 대기하지만 내부 포트 80을 노출 하지 않는 웹 서비스를 시작하십시오 (oops!) :
# docker run -ti mkodockx/docker-pastebin # Forgot to expose PORT 80!
Docker 네트워크 IP를 찾으십시오.
# docker inspect 63256f72142a | grep IPAddress
"IPAddress": "172.17.0.2",
verb/socat
포트 8080이 노출 된 상태에서 시작 하여 TCP 트래픽을 해당 IP의 포트 80으로 전달하십시오.
# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80
이제 http : // localhost : 8080 / 에서 pastebin에 액세스 할 수 있으며 요청이로 socat:1234
전달 pastebin:80
되고 응답이 동일한 경로를 반대로 이동합니다.
적어도 Docker 1.4.1에서는 IPtables 해킹이 작동하지 않습니다.
가장 좋은 방법은 노출 된 포트로 다른 컨테이너를 실행하고 socat으로 릴레이하는 것입니다. 이것이 SQLPlus로 데이터베이스에 (일시적으로) 연결 한 것입니다.
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus
도커 파일 :
FROM debian:7
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
CMD socat -dddd TCP-LISTEN:1521,reuseaddr,fork TCP:db:1521
다른 아이디어가 있습니다. SSH를 사용하여 포트 전달을 수행하십시오. Docker 호스트가 VM 인 경우 OS X (및 아마도 Windows)에서도 작업 할 수 있다는 이점이 있습니다.
docker exec -it <containterid> ssh -R5432:localhost:5432 <user>@<hostip>
나는이 같은 문제를 해결해야했고 실행중인 컨테이너를 멈추지 않고 해결할 수있었습니다. 이 솔루션은 2016 년 2 월 현재 Docker 1.9.1을 사용하는 최신 솔루션입니다. 어쨌든,이 답변은 @ ricardo-branco의 답변에 대한 자세한 버전이지만 새로운 사용자에게는 더 깊이 있습니다.
내 시나리오에서는 컨테이너에서 실행되는 MySQL에 임시로 연결하고 싶었고 다른 응용 프로그램 컨테이너가 컨테이너에 연결되어 있기 때문에 데이터베이스 컨테이너를 중지, 재구성 및 다시 시작하는 것은 시작이 아닙니다.
SSH 터널링을 통해 Sequel Pro에서 외부로 MySQL 데이터베이스에 액세스하고 싶기 33306
때문에 호스트 컴퓨터에서 포트를 사용하려고 합니다. 3306
외부 MySQL 인스턴스가 실행중인 경우에는 아닙니다 .
iptables를 한 시간 정도 조정하면 다음과 같은 결과가 나타나지 않습니다.
단계별로 여기 내가 한 일이 있습니다.
mkdir db-expose-33306
cd db-expose-33306
vim Dockerfile
dockerfile
이것을 안에 넣고 편집하십시오 .
# Exposes port 3306 on linked "db" container, to be accessible at host:33306
FROM ubuntu:latest # (Recommended to use the same base as the DB container)
RUN apt-get update && \
apt-get -y install socat && \
apt-get clean
USER nobody
EXPOSE 33306
CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306
그런 다음 이미지를 빌드하십시오.
docker build -t your-namespace/db-expose-33306 .
그런 다음 실행중인 컨테이너에 연결하여 실행하십시오. ( 명시 적으로 중지하고 제거 할 때까지 백그라운드에서 유지하는 -d
대신 사용하십시오 -rm
.이 경우 일시적으로 실행하기를 원합니다.)
docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306 your-namespace/db-expose-33306
허용되는 답변 iptables
솔루션에 추가하기 위해 호스트에서 두 개의 명령을 더 실행하여 외부 세계에서 열어야했습니다.
HOST> iptables -t nat -A DOCKER -p tcp --dport 443 -j DNAT --to-destination 172.17.0.2:443
HOST> iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source 172.17.0.2 --destination 172.17.0.2 --dport https
HOST> iptables -A DOCKER -j ACCEPT -p tcp --destination 172.17.0.2 --dport https
참고 : 포트 https (443)를 열었습니다. 도커 내부 IP는 172.17.0.2
참고 2 :이 규칙과 임시는 컨테이너가 다시 시작될 때까지만 지속됩니다.
SSH를 사용하여 터널을 만들고 컨테이너를 호스트에 노출시킬 수 있습니다.
컨테이너에서 호스트로, 호스트에서 컨테이너로, 두 가지 방법으로 모두 수행 할 수 있습니다. 그러나 OpenSSH와 같은 SSH 도구가 필요합니다 (하나의 클라이언트와 다른 서버의 서버).
예를 들어 컨테이너에서 다음을 수행 할 수 있습니다.
$ yum install -y openssh openssh-server.x86_64
service sshd restart
Stopping sshd: [FAILED]
Generating SSH2 RSA host key: [ OK ]
Generating SSH1 RSA host key: [ OK ]
Generating SSH2 DSA host key: [ OK ]
Starting sshd: [ OK ]
$ passwd # You need to set a root password..
컨테이너의이 줄에서 컨테이너 IP 주소를 찾을 수 있습니다.
$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2
그런 다음 호스트에서 다음을 수행 할 수 있습니다.
sudo ssh -NfL 80:0.0.0.0:80 root@172.17.0.2
Weave Net 과 같은 오버레이 네트워크를 사용하면 각 컨테이너에 고유 한 IP 주소를 할당하고 모든 포트를 네트워크의 모든 컨테이너 부분에 암시 적으로 노출합니다.
Weave는 호스트 네트워크 통합 도 제공 합니다 . 기본적으로 비활성화되어 있지만 호스트에서 컨테이너 IP 주소 및 모든 포트에 액세스하려면 간단히 run을 실행할 수 있습니다 weave expose
.
전체 공개 : 저는 Weaveworks에서 근무합니다.
편리한 HAProxy 래퍼가 있습니다.
docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy
대상 컨테이너에 HAProxy가 작성됩니다. 쉬워요.
Ricardo 의 답변을 먼저 읽으십시오 . 이것은 나를 위해 일했습니다.
그러나 docker-compose를 사용하여 실행중인 컨테이너가 시작된 경우 작동하지 않는 시나리오가 있습니다. docker-compose (docker 1.17을 실행 중임)가 새 네트워크를 생성하기 때문입니다. 이 시나리오를 해결하는 방법은
docker network ls
그런 다음 다음을 추가하십시오 docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
누군가에게 응답이없는 경우-대상 컨테이너가 이미 docker 네트워크에서 실행 중인지 확인하십시오.
CONTAINER=my-target-container
docker inspect $CONTAINER | grep NetworkMode
"NetworkMode": "my-network-name",
나중에 변수에 저장하십시오 $NET_NAME
.
NET_NAME=$(docker inspect --format '{{.HostConfig.NetworkMode}}' $CONTAINER)
그렇다면 동일한 네트워크에서 프록시 컨테이너를 실행해야합니다.
다음으로 컨테이너의 별명을 찾으십시오.
docker inspect $CONTAINER | grep -A2 Aliases
"Aliases": [
"my-alias",
"23ea4ea42e34a"
나중에 변수에 저장하십시오 $ALIAS
.
ALIAS=$(docker inspect --format '{{index .NetworkSettings.Networks "'$NET_NAME'" "Aliases" 0}}' $CONTAINER)
이제 socat
네트워크의 컨테이너에서 실행 $NET_NAME
하여 $ALIAS
ed 컨테이너의 노출 된 (발행되지 않은) 포트 에 브리지하십시오 .
docker run \
--detach --name my-new-proxy \
--net $NET_NAME \
--publish 8080:1234 \
alpine/socat TCP-LISTEN:1234,fork TCP-CONNECT:$ALIAS:80
라이브 포트 매핑은 불가능하지만 Docker 컨테이너에 가상 머신과 같은 실제 인터페이스에 필요한 양을 여러 가지 방법으로 제공 할 수 있습니다.
맥 블란 인터페이스
Docker는 이제 Macvlan 네트워크 드라이버를 포함합니다 . Docker 네트워크를 "실제"인터페이스에 연결하고 해당 네트워크 주소를 컨테이너에 직접 할당 할 수 있습니다 (가상 머신 브리지 모드).
docker network create \
-d macvlan \
--subnet=172.16.86.0/24 \
--gateway=172.16.86.1 \
-o parent=eth0 pub_net
pipework
실제 인터페이스 를 컨테이너에 매핑 하거나 이전 버전의 Docker에서 하위 인터페이스 를 설정할 수도 있습니다 .
라우팅 IP
네트워크를 제어 할 수 있는 경우 컨테이너에서 사용하기 위해 추가 네트워크 를 Docker 호스트로 라우팅 할 수 있습니다 .
그런 다음 해당 네트워크를 컨테이너에 할당하고 Docker 네트워크를 통해 패킷을 라우팅하도록 Docker 호스트를 설정하십시오.
공유 호스트 인터페이스
이 --net host
옵션을 사용하면 호스트 인터페이스를 컨테이너로 공유 할 수 있지만 공유 특성으로 인해 하나의 호스트에서 여러 컨테이너를 실행하기에는 적합하지 않습니다.
해결책은 다음과 같습니다.
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
컨테이너를 실행하는 동안 포트를 매핑하는 솔루션입니다.
docker run -d --net = host myvnc
포트를 자동으로 호스트에 노출하고 매핑합니다.
참고 URL : https://stackoverflow.com/questions/19897743/exposing-a-port-on-a-live-docker-container
'development' 카테고리의 다른 글
“bar가 포함 된 foo”에 대한 CSS 선택기? (0) | 2020.02.25 |
---|---|
프리 플라이트 요청에 대한 응답이 액세스 제어 확인을 통과하지 못함 (0) | 2020.02.25 |
파이썬 인터프리터에서 업데이트 된 패키지를 다시 가져 오는 방법은 무엇입니까? (0) | 2020.02.25 |
잠금, 뮤텍스, 세마포… 차이점은 무엇입니까? (0) | 2020.02.25 |
에 대한 모든 변경 사항을 감지 (0) | 2020.02.25 |