완전한 가상 머신처럼 작동하는 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 :이 규칙과 임시는 컨테이너가 다시 시작될 때까지만 지속됩니다.