etc./StackOverFlow

Docker 컨테이너 내부에서 머신의 로컬 호스트에 어떻게 연결합니까?

청렴결백한 만능 재주꾼 2021. 12. 2. 00:26
반응형

질문자 :Phil


그래서 도커 컨테이너 내에서 실행 중인 Nginx가 있고 로컬 호스트에서 실행 중인 mysql이 있고 내 Nginx 내에서 MySql에 연결하고 싶습니다. MySql은 localhost에서 실행 중이며 외부 세계에 포트를 노출하지 않으므로 머신의 IP 주소에 바인딩되지 않고 localhost에 바인딩됩니다.

이 도커 컨테이너 내에서 이 MySql 또는 localhost의 다른 프로그램에 연결할 수 있는 방법이 있습니까?

이 질문은 도커 호스트의 IP 주소가 네트워크의 공용 IP 또는 사설 IP일 수 있다는 사실 때문에 "도커 컨테이너 내부에서 도커 호스트의 IP 주소를 얻는 방법"과 다릅니다. 도커 컨테이너 내에서 연결할 수 없습니다(AWS에서 호스팅되는 경우 공개 IP를 의미함). 도커 호스트의 IP 주소가 있더라도 Docker 네트워크가 오버레이, 호스트, 브리지, macvlan, 없음 등이 될 수 있으므로 해당 IP 주소가 주어지면 컨테이너 내에서 도커 호스트에 연결할 수 있다는 의미가 아닙니다. 그 IP 주소.



편집하다:

Mac용 Docker 또는 Windows용 Docker host.docker.internal 호스트를 사용하여 mysql 서비스에 연결하기만 하면 됩니다(연결 문자열 127.0.0.1

Linux용 Docker 20.10.0 이상을 사용하는 경우 --add-host host.docker.internal:host-gateway 옵션으로 Docker 컨테이너를 시작한 host.docker.internal

그렇지 않으면 아래를 읽으십시오


TLDR

docker run 명령에서 --network="host" 를 사용하면 127.0.0.1 이 도커 호스트를 가리킵니다.

참고: 이 모드는 설명서에 따라 Linux용 Docker에서만 작동합니다.


도커 컨테이너 네트워킹 모드에 대한 참고 사항

Docker는 컨테이너를 실행할 때 다양한 네트워킹 모드를 제공합니다. 선택한 모드에 따라 도커 호스트에서 실행되는 MySQL 데이터베이스에 다르게 연결합니다.

docker run --network="bridge"(기본값)

Docker는 기본적으로 docker0 이라는 브리지를 만듭니다. 도커 호스트와 도커 컨테이너 모두 해당 브리지에 IP 주소가 있습니다.

Docker 호스트에서 sudo ip addr show docker0 하면 다음과 같은 출력이 표시됩니다.

 [vagrant@docker:~] $ sudo ip addr show docker0 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff inet 172.17.42.1/16 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::5484:7aff:fefe:9799/64 scope link valid_lft forever preferred_lft forever

그래서 여기 내 고정 표시기 호스트는 IP 주소가 172.17.42.1docker0 네트워크 인터페이스를.

이제 새 컨테이너를 시작하고 셸을 가져옵니다. docker run --rm -it ubuntu:trusty bash 및 컨테이너 유형 내에서 ip addr show eth0 기본 네트워크 인터페이스가 어떻게 설정되었는지 확인합니다.

 root@e77f6a1b3740:/# ip addr show eth0 863: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 66:32:13:f0:f1:e3 brd ff:ff:ff:ff:ff:ff inet 172.17.1.192/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::6432:13ff:fef0:f1e3/64 scope link valid_lft forever preferred_lft forever

여기 내 컨테이너의 IP 주소는 172.17.1.192 입니다. 이제 라우팅 테이블을 살펴보십시오.

 root@e77f6a1b3740:/# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 172.17.42.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 * 255.255.0.0 U 0 0 0 eth0

172.17.42.1 의 IP 주소가 기본 경로로 설정되고 컨테이너에서 액세스할 수 있습니다.

 root@e77f6a1b3740:/# ping 172.17.42.1 PING 172.17.42.1 (172.17.42.1) 56(84) bytes of data. 64 bytes from 172.17.42.1: icmp_seq=1 ttl=64 time=0.070 ms 64 bytes from 172.17.42.1: icmp_seq=2 ttl=64 time=0.201 ms 64 bytes from 172.17.42.1: icmp_seq=3 ttl=64 time=0.116 ms

도커 실행 --network="호스트"

또는 네트워크 설정이 host 설정된 도커 컨테이너를 실행할 수 있습니다. 이러한 컨테이너는 네트워크 스택을 도커 호스트와 공유하고 컨테이너 관점에서 localhost (또는 127.0.0.1 )는 도커 호스트를 참조합니다.

도커 컨테이너에서 열린 모든 포트는 도커 호스트에서 열립니다. -p 또는 -P docker run 옵션 을 필요로 하지 않습니다.

내 도커 호스트의 IP 구성:

 [vagrant@docker:~] $ ip addr show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe98:dcaa/64 scope link valid_lft forever preferred_lft forever

호스트 모드의 도커 컨테이너에서 :

 [vagrant@docker:~] $ docker run --rm -it --network=host ubuntu:trusty ip addr show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe98:dcaa/64 scope link valid_lft forever preferred_lft forever

보시다시피 도커 호스트와 도커 컨테이너는 정확히 동일한 네트워크 인터페이스를 공유하므로 동일한 IP 주소를 갖습니다.


컨테이너에서 MySQL에 연결

브리지 모드

브리지 모드의 컨테이너에서 도커 호스트에서 실행되는 MySQL에 액세스하려면 172.17.42.1 IP 주소에서 연결을 수신하고 있는지 확인해야 합니다.

그렇게 하려면 MySQL 구성 파일(my.cnf)에 bind-address = 172.17.42.1 또는 bind-address = 0.0.0.0 이 있는지 확인하십시오.

게이트웨이의 IP 주소로 환경 변수를 설정해야 하는 경우 컨테이너에서 다음 코드를 실행할 수 있습니다.

 export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

그런 다음 애플리케이션에서 DOCKER_HOST_IP 환경 변수를 사용하여 MySQL에 대한 연결을 엽니다.

참고: bind-address = 0.0.0.0 을 사용하는 경우 MySQL 서버는 모든 네트워크 인터페이스에서 연결을 수신 대기합니다. 즉, 인터넷에서 MySQL 서버에 연결할 수 있습니다. 그에 따라 방화벽 규칙을 설정해야 합니다.

참고 2: bind-address = 172.17.42.1 을 사용 127.0.0.1 대한 연결을 수신하지 않습니다. MySQL에 연결하려는 도커 호스트에서 실행되는 프로세스는 172.17.42.1 IP 주소를 사용해야 합니다.

호스트 모드

호스트 모드에서 컨테이너에서 고정 표시기 호스트에서 실행 액세스 MySQL로, 당신은 유지할 수 있습니다 bind-address = 127.0.0.1 MySQL의 구성과 당신이 할 필요가에 연결하는 것입니다 127.0.0.1 당신의 용기에서 :

 [vagrant@docker:~] $ docker run --rm -it --network=host mysql mysql -h 127.0.0.1 -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 36 Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu) Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql>

참고: mysql -h localhost 아닌 mysql -h 127.0.0.1 사용하십시오. 그렇지 않으면 MySQL 클라이언트는 유닉스 소켓을 사용하여 연결을 시도합니다.


Thomasleveil

macOS 및 Windows용

Docker v 18.03 이상(2018년 3월 21일 이후)

내부 IP 주소를 사용하거나 호스트에서 사용하는 내부 IP 주소로 확인되는 특수 DNS 이름 host.docker.internal

Linux 지원 보류 https://github.com/docker/for-linux/issues/264

이전 버전의 Docker가 있는 MacOS

Mac용 Docker v 17.12 - v 18.02

위와 동일하지만 docker.for.mac.host.internal 사용합니다.

Mac용 Docker v 17.06 - v 17.11

위와 docker.for.mac.localhost 사용합니다.

Mac용 Docker 17.05 이하

도커 컨테이너에서 호스트 시스템에 액세스하려면 네트워크 인터페이스에 IP 별칭을 연결해야 합니다. 원하는 IP를 바인딩할 수 있습니다. 다른 IP에 사용하고 있지 않은지 확인하세요.

sudo ifconfig lo0 alias 123.123.123.123/24

그런 다음 서버가 위에서 언급한 IP 또는 0.0.0.0 수신하고 있는지 확인하십시오. 127.0.0.1 에서 수신 대기 중인 경우 연결을 수락하지 않습니다.

그런 다음 도커 컨테이너가 이 IP를 가리키도록 하면 호스트 시스템에 액세스할 수 있습니다!

테스트를 위해 컨테이너 내부에서 curl -X GET 123.123.123.123:3000 과 같은 것을 실행할 수 있습니다.

별칭은 재부팅할 때마다 재설정되므로 필요한 경우 시작 스크립트를 만듭니다.

솔루션 및 추가 문서: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


Janne Annala

사용

 host.docker.internal

대신에

 localhost

나를 위해 완벽하게 작동합니다.


DeyaEldeen

컨테이너의 별칭 이름(DNS)에 매핑할 로컬 IP를 가져오는 위의 게시물과 유사한 해킹을 수행합니다. 주요 문제는 Linux 및 OSX 호스트 IP 주소 에서 모두 작동하는 간단한 스크립트를 사용하여 동적으로 얻는 것입니다. 두 환경 모두에서 작동하는 이 스크립트를 수행했습니다( "$LANG" != "en_*" 구성된 Linux 배포판에서도).

 ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

따라서 Docker Compose를 사용하면 전체 구성은 다음과 같습니다.

시작 스크립트(docker-run.sh) :

 export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1) docker-compose -f docker-compose.yml up

docker-compose.yml :

 myapp: build: . ports: - "80:80" extra_hosts: - "dockerhost:$DOCKERHOST"

그런 다음 http://localhosthttp://dockerhost 로 변경합니다.

DOCKERHOST 스크립트를 사용자 정의하는 방법에 대한 고급 가이드는 작동 방식에 대한 설명과 함께 이 게시물 을 살펴보십시오.


Mariano Ruiz

localhost 에 연결할 수 있을 것으로 예상되는 네트워크나 코드를 건드리지 않고 NGINX/PHP-FPM 스택에서 저에게 효과적이었습니다.

호스트에서 컨테이너 내부로 mysqld.sock 을 마운트합니다.

mysql을 실행하는 호스트에서 mysql.sock 파일의 위치를 찾으십시오.
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'

도커에서 예상되는 위치에 해당 파일을 마운트합니다.
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock

mysqld.sock의 가능한 위치:

 /tmp/mysqld.sock /var/run/mysqld/mysqld.sock /var/lib/mysql/mysql.sock /Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP

user833482

Linux용 솔루션(커널 >=3.6).

좋아, 로컬 호스트 서버에는 IP 주소가 172.17.0.1 인 기본 도커 인터페이스 docker0 이 있습니다. 컨테이너가 기본 네트워크 설정 --net="bridge" 으로 시작되었습니다.

  1. docker0 인터페이스에 대해 route_localnet 활성화:
    $ sysctl -w net.ipv4.conf.docker0.route_localnet=1
  2. 다음 규칙을 iptables에 추가합니다.
    $ iptables -t nat -I PREROUTING -i docker0 -d 172.17.0.1 -p tcp --dport 3306 -j DNAT --to 127.0.0.1:3306
    $ iptables -t filter -I INPUT -i docker0 -d 127.0.0.1 -p tcp --dport 3306 -j ACCEPT
  3. '%'에서 액세스할 수 있는 mysql 사용자를 생성합니다. 즉, localhost를 제외한 모든 사용자로부터:
    CREATE USER 'user'@'%' IDENTIFIED BY 'password';
  4. 스크립트에서 mysql-server 주소를 172.17.0.1로 변경하십시오.


커널 문서에서 :

route_localnet - BOOLEAN: 라우팅하는 동안 루프백 주소를 화성 소스 또는 대상으로 간주하지 마십시오. 이렇게 하면 로컬 라우팅 목적으로 127/8을 사용할 수 있습니다( 기본값 FALSE ).


Ray D

host.docker.internal 이 모든 플랫폼에서 작동할 때까지 수동 설정 없이 NAT 게이트웨이 역할을 하는 내 컨테이너를 사용할 수 있습니다.

https://github.com/qoomon/docker-host


qoomon

Windows 10용 솔루션

Docker 커뮤니티 에디션 17.06.0-ce-win18 2017-06-28(안정)

docker.for.win.localhost 의 DNS 이름을 사용하여 내부 IP를 확인할 수 있습니다. (일부 출처는 windows win 해야 함을 경고합니다)

개요
Azure Storage EmulatorCosmosDB Emulator 실행 중인 로컬 호스트로 연결하는 것과 유사한 작업을 수행해야 했습니다.

Azure Storage Emulator 는 기본적으로 127.0.0.1 에서 수신 대기하지만 해당 IP도 변경할 수 있지만 기본 설정으로 작동하는 솔루션을 찾고 있었습니다.

이것은 또한 기본 포트 설정으로 내 호스트에서 로컬로 실행 SQL ServerIIS 로 연결하는 데에도 작동합니다.


Ralph Willgoss

매우 간단하고 빠르게 ifconfig(linux) 또는 ipconfig(windows)로 호스트 IP를 확인한 다음

docker-compose.yml

 version: '3' # specify docker-compose version services: nginx: build: ./ # specify the directory of the Dockerfile ports: - "8080:80" # specify port mapping extra_hosts: - "dockerhost:<yourIP>"

이렇게 하면 컨테이너가 호스트에 액세스할 수 있습니다. DB에 액세스할 때 이전에 지정한 이름(이 경우 "dockerhost" 및 DB가 실행 중인 호스트의 포트)을 사용하는 것을 기억하십시오.


Felipe Toledo

몇 가지 솔루션이 떠오릅니다.

  1. 먼저 종속성을 컨테이너로 이동
  2. 다른 서비스를 외부에서 액세스할 수 있도록 설정하고 해당 외부 IP로 연결
  3. 네트워크 격리 없이 컨테이너 실행
  4. 네트워크를 통한 연결을 피하고 대신 볼륨으로 마운트된 소켓을 사용하십시오.

이것이 기본적으로 작동하지 않는 이유는 컨테이너가 기본적으로 자체 네트워크 네임스페이스로 실행되기 때문입니다. 즉, localhost(또는 루프백 인터페이스를 가리키는 127.0.0.1)는 컨테이너별로 고유합니다. 이것에 연결하면 컨테이너 자체에 연결되며 도커 외부 또는 다른 도커 컨테이너 내부에서 실행되는 서비스는 연결되지 않습니다.

옵션 1 : 종속성을 컨테이너로 이동할 수 있다면 먼저 이 작업을 수행하겠습니다. 다른 사람들이 자신의 환경에서 컨테이너를 실행하려고 할 때 애플리케이션 스택을 이식 가능하게 만듭니다. 또한 마이그레이션되지 않은 다른 서비스가 여전히 연결할 수 있는 호스트에 포트를 게시할 수 있습니다. -p 127.0.0.1:3306:3306 과 같은 구문을 사용하여 외부에서 액세스할 수 없도록 하기 위해 도커 호스트의 localhost 인터페이스에 포트를 게시할 수도 있습니다.

옵션 2 : 컨테이너 내부에서 호스트 IP 주소를 감지하는 다양한 방법이 있지만 각각 작동하는 시나리오의 수가 제한되어 있습니다(예: Mac용 Docker 필요). 가장 이식 가능한 옵션은 환경 변수 또는 구성 파일과 같은 것으로 컨테이너에 호스트 IP를 주입하는 것입니다. 예:

 docker run --rm -e "HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')" ...

이를 위해서는 서비스가 해당 외부 인터페이스에서 수신 대기해야 하므로 보안 문제가 될 수 있습니다. 컨테이너 내부에서 호스트 IP 주소를 가져오는 다른 방법 은 이 게시물을 참조하세요 .

이식성이 약간 떨어지는 것은 host.docker.internal 을 사용하는 것입니다. 이것은 Windows용 Docker 및 Mac용 Docker의 현재 버전에서 작동합니다. 그리고 20.10에서는 다음을 사용하여 특수 호스트 항목을 전달할 때 Linux용 Docker에 기능이 추가되었습니다.

 docker run --add-host host.docker.internal:host-gateway ...

host-gateway 는 자동으로 호스트 IP로 확장되는 Docker 20.10에 추가된 특별한 값입니다. 자세한 내용은 이 PR을 참조하십시오.

옵션 3 : 네트워크 격리 없이 실행, 즉 --net host 로 실행하면 애플리케이션이 호스트 네트워크 네임스페이스에서 실행되고 있음을 의미합니다. 이는 컨테이너에 대한 격리가 덜하고 DNS를 사용하여 공유 도커 네트워크를 통해 다른 컨테이너에 액세스할 수 없음을 의미합니다(대신 게시된 포트를 사용하여 다른 컨테이너화된 애플리케이션에 액세스해야 함). 127.0.0.1 에서만 수신 대기하는 호스트의 다른 서비스에 액세스해야 하는 애플리케이션의 경우 이것이 가장 쉬운 옵션이 될 수 있습니다.

옵션 4 : 다양한 서비스에서 파일 시스템 기반 소켓을 통한 액세스도 허용합니다. 이 소켓은 바인드 마운트 볼륨으로 컨테이너에 마운트할 수 있으므로 네트워크를 통하지 않고 호스트 서비스에 액세스할 수 있습니다. /var/run/docker.sock 을 컨테이너에 마운트하는 예를 자주 볼 수 있습니다(해당 컨테이너에 호스트에 대한 루트 액세스 권한 부여). mysql을 사용하면 -v /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysql.sock 과 같은 것을 시도한 다음 mysql이 소켓을 사용하여 변환하는 localhost 연결할 수 있습니다.


BMitch

윈도우의 경우,

스프링 구성에서 데이터베이스 URL을 변경했습니다. spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/apidb

그런 다음 이미지를 빌드하고 실행합니다. 그것은 나를 위해 일했습니다.


Praveenkumar Beedanal

Windows 10 Home에서 Docker Toolbox를 사용할 때 어떤 답변도 작동 하지 않았지만 10.0.2.2 는 이 주소의 VM에 호스트를 노출하는 VirtualBox를 사용하기 때문에 작동했습니다.


Elad

Windows 사용자의 경우 브리지 네트워크 드라이버를 사용한다고 가정하면 MySQL을 hyper-v 네트워크 인터페이스의 IP 주소에 구체적으로 바인딩해야 합니다.

이것은 일반적으로 숨겨진 C:\ProgramData\MySQL 폴더 아래의 구성 파일을 통해 수행됩니다.

0.0.0.0에 바인딩하면 작동하지 않습니다. 필요한 주소는 도커 구성에도 표시되며 제 경우에는 10.0.75.1이었습니다.


Casey

이것은 실제 질문에 대한 답변이 아닙니다. 이것이 내가 비슷한 문제를 해결한 방법입니다. 솔루션은 전적으로 다음에서 비롯됩니다 . 컨테이너가 통신할 수 있도록 Docker 컨테이너 네트워킹을 정의 합니다. 닉 라보이 덕분에

한 컨테이너와 다른 컨테이너 간에 REST 호출을 수행하려는 다른 사용자를 위해 여기에 남겨둡니다. 질문에 답합니다. 도커 환경에서 localhost 대신 무엇을 사용해야 할까요?

네트워크가 어떻게 보이는지 확인하십시오. docker network ls

새 네트워크 docker network create -d my-net

첫 번째 컨테이너 docker run -d -p 5000:5000 --network="my-net" --name "first_container" <MyImage1:v0.1>

docker inspect first_container 대한 네트워크 설정을 확인하십시오. "네트워크": 'my-net'이 있어야 합니다.

두 번째 컨테이너 docker run -d -p 6000:6000 --network="my-net" --name "second_container" <MyImage2:v0.1>

docker inspect second_container 대한 네트워크 설정을 확인하십시오. "네트워크": 'my-net'이 있어야 합니다.

두 번째 컨테이너 docker exec -it second_container sh 또는 docker exec -it second_container bash ssh 하십시오.

ping first_container ping하여 첫 번째 컨테이너를 ping할 수 있습니다. http://localhost:5000 과 같은 코드 호출 http://first_container:5000 으로 대체될 수 있습니다.


Shirish Hirekodi

편집: 나는 GitHub에서 개념의 프로토타입을 완성했습니다. 확인: https://github.com/sivabudh/system-in-a-box


첫째, 내 대답은 Mac을 사용하는 사람과 Linux를 사용하는 사람의 두 그룹을 대상으로 합니다.

호스트 네트워크 모드는 Mac에서 작동하지 않습니다. IP 별칭을 사용해야 합니다( https://stackoverflow.com/a/43541681/2713729 참조).

호스트 네트워크 모드란 무엇입니까? 참조: https://docs.docker.com/engine/reference/run/#/network-settings

둘째, Linux를 사용하는 분들(내 직접적인 경험은 Ubuntu 14.04 LTS이었고 곧 프로덕션에서 16.04 LTS로 업그레이드할 예정입니다)입니다. , Docker 컨테이너 내에서 실행되는 서비스를 실행 중인 localhost Docker 호스트(예: 노트북).

어떻게?

핵심은 Docker 컨테이너를 실행할 때 호스트 모드로 실행해야 한다는 것입니다. 명령은 다음과 같습니다.

docker run --network="host" -id <Docker image ID>

당신이 할 때 ifconfig (당신이 필요합니다 apt-get install net-tools 하기위한 컨테이너를 ifconfig , 당신은 (네트워크 인터페이스가 부두 노동자 호스트의 것과 동일한 것을 볼 수 컨테이너 내부에서 호출 될) 예. 노트북을 ).

참고로 저는 Mac 사용자이지만 Parallels에서 Ubuntu를 실행하므로 Mac을 사용하는 것이 단점은 아닙니다. ;-)

localhost 실행되는 MySQL에 연결하는 방법입니다.


sivabudh

Mac OSX를 위한 가장 간단한 솔루션

Mac의 IP 주소를 사용하십시오. Mac에서는 다음을 실행하여 IP 주소를 가져오고 컨테이너 내에서 사용합니다.

 $ ifconfig | grep 'inet 192'| awk '{ print $2}'

Mac 또는 다른 도커 컨테이너에서 로컬로 실행되는 서버가 0.0.0.0을 수신하는 한 도커 컨테이너는 해당 주소에 연결할 수 있습니다.

0.0.0.0에서 수신 대기하는 다른 도커 컨테이너에 액세스하려면 172.17.0.1을 사용할 수 있습니다.


dansalmo

Thomasleveil의 답변에 동의하지 않습니다.

mysql을 172.17.42.1에 바인드하면 호스트의 데이터베이스를 사용하는 다른 프로그램이 접근하는 것을 방지할 수 있습니다. 이것은 모든 데이터베이스 사용자가 고정된 경우에만 작동합니다.

mysql을 0.0.0.0에 바인드하면 db가 외부 세계로 열릴 것입니다. 이는 매우 나쁜 일일 뿐만 아니라 원래 질문 작성자가 하려는 것과 반대입니다. 그는 명시적으로 "MySql은 localhost에서 실행 중이고 포트를 외부 세계에 노출하지 않으므로 localhost에 바인딩됩니다"라고 말합니다.

ivant의 의견에 답하려면

"mysql을 docker0에도 바인딩하지 않는 이유는 무엇입니까?"

이건 불가능 해. mysql/mariadb 문서에는 여러 인터페이스에 바인딩할 수 없다고 명시되어 있습니다. 0, 1 또는 모든 인터페이스에만 바인딩할 수 있습니다.

결론적으로 도커 컨테이너에서 호스트의 (localhost 전용) 데이터베이스에 도달하는 방법을 찾지 못했습니다. 그것은 확실히 매우 일반적인 패턴처럼 보이지만 어떻게 해야할지 모르겠습니다.


orzel

localhost 서비스가 바인딩되는 인터페이스를 변경할 수 없는 Linux의 경우

우리가 해결해야 할 두 가지 문제가 있습니다

  1. 호스트의 IP 얻기
  2. Docker에서 localhost 서비스를 사용할 수 있도록 설정

첫 번째 문제는 다른 답변에서 제공한 대로 qoomon의 docker-host image 를 사용하여 해결할 수 있습니다.

액세스할 수 있도록 이 컨테이너를 다른 컨테이너와 동일한 브리지 네트워크에 추가해야 합니다. dockerhost 를 ping할 수 있는지 확인합니다.

 bash-5.0# ping dockerhost PING dockerhost (172.20.0.2): 56 data bytes 64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.523 ms

이제 더 어려운 문제는 서비스를 도커에 액세스할 수 있게 만드는 것입니다.

텔넷을 사용하여 호스트의 포트에 액세스할 수 있는지 확인할 수 있습니다(이를 설치해야 할 수도 있음).

문제는 컨테이너가 SSH와 같은 모든 인터페이스에 바인딩되는 서비스에만 액세스할 수 있다는 것입니다.

 bash-5.0# telnet dockerhost 22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

그러나 localhost에만 바인딩된 서비스는 액세스할 수 없습니다.

 bash-5.0# telnet dockerhost 1025 telnet: can't connect to remote host (172.20.0.2): Connection refused

여기서 적절한 솔루션은 서비스를 도커 브리지 네트워크에 바인딩하는 것입니다. 그러나 이 답변은 사용자가 이를 변경할 수 없다고 가정합니다. 그래서 우리는 대신 iptables 를 사용할 것입니다.

ifconfig 와 함께 사용하는 브리지 네트워크의 이름을 찾아야 합니다. 이름 없는 브리지를 사용하는 경우 이는 docker0 입니다. 그러나 명명된 네트워크를 사용하는 경우 br- 시작하는 브리지가 대신 해당 도커를 사용하게 됩니다. 광산은 br-5cd80298d6f4 입니다.

이 브리지의 이름을 알고 나면 이 브리지에서 localhost로의 라우팅을 허용해야 합니다. 보안상의 이유로 기본적으로 비활성화되어 있습니다.

 sysctl -w net.ipv4.conf.<bridge_name>.route_localnet=1

iptables 규칙을 설정합니다. 컨테이너는 도커 브리지 네트워크의 포트에만 액세스할 수 있으므로 서비스가 실제로 이 네트워크의 포트에 바인딩된 것처럼 가장할 것입니다.

<docker_bridge>:port 에 대한 모든 요청 localhost:port

 iptables -t nat -A PREROUTING -p tcp -i <docker_bridge_name> --dport <service_port> -j DNAT --to-destination 127.0.0.1:<service_port>

예를 들어 포트 1025에 대한 내 서비스의 경우

 iptables -t nat -A PREROUTING -p tcp -i br-5cd80298d6f4 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025

이제 컨테이너에서 서비스에 액세스할 수 있습니다.

 bash-5.0# telnet dockerhost 1025 220 127.0.0.1 ESMTP Service Ready

JShorthouse

게이트웨이 를 알아야 합니다! 로컬 서버에 대한 내 솔루션은 0.0.0.0:8000 아래에 노출 한 다음 서브넷으로 docker를 실행하고 다음과 같은 컨테이너를 실행하는 것이 었습니다.

 docker network create --subnet=172.35.0.0/16 --gateway 172.35.0.1 SUBNET35 docker run -d -p 4444:4444 --net SUBNET35 <container-you-want-run-place-here>

http://172.35.0.1:8000 통해 루프백에 액세스할 수 있습니다.


storenth

이 시도:

 version: '3.5' services: yourservice-here: container_name: container_name ports: - "4000:4000" extra_hosts: # <---- here - localhost:192.168.1.202 - or-vitualhost.local:192.168.1.202

192.168.1.202 를 얻으려면 ifconfig 사용합니다.

이것은 나를 위해 일했습니다. 이 도움을 바랍니다!


Binh Ho

여기 내 솔루션이 있습니다. 내 경우에 작동합니다.

  • /etc/mysql/mysql.conf.d에서 #bind-address = 127.0.0.1 주석으로 로컬 mysql 서버를 공개 액세스로 설정

  • mysql 서버 재시작 sudo /etc/init.d/mysql restart

  • 다음 명령을 실행하여 모든 호스트에 대한 사용자 루트 액세스를 엽니다. mysql -uroot -proot GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES;

  • sh 스크립트 생성 : run_docker.sh

    #!bin/bash

    HOSTIP=`ip -4 addr 표시 범위 전역 개발 eth0 | 그렙 이넷 | awk '{인쇄 \$2}' | 컷 -d / -f 1`


      도커 실행 -it -d --name 웹 앱 \
                  --add-호스트=로컬:${호스트IP} \
                  -p 8080:8080 \
                  -e DATABASE_HOST=${호스트IP} \
                  -e DATABASE_PORT=3306 \
                  -e DATABASE_NAME=데모 \
                  -e DATABASE_USER=루트 \
                  -e DATABASE_PASSWORD=루트 \
                  sopheamak/springboot_docker_mysql

  
  • docker-composer로 실행

    버전: '2.1'

    서비스:
    tomcatwar: extra_hosts: - "local:10.1.2.232" 이미지: sopheamak/springboot_docker_mysql
    포트: - 8080:8080 환경: - DATABASE_HOST=로컬 - DATABASE_USER=루트 - DATABASE_PASSWORD=루트 - DATABASE_NAME=데모 - DATABASE_PORT=3306


Community Wiki

먼저 이 문제를 해결하는 데 필요한 옵션 은 이 답변을 참조하세요. docker-compose 를 사용하는 경우 network_mode: host 를 서비스에 추가 127.0.0.1 을 사용하여 로컬 호스트에 연결할 수 있습니다. 이것은 위의 답변에 설명된 옵션 중 하나일 뿐입니다. 아래에서 https://github.com/geerlingguy/php-apache-container.git docker-compose.yml 을 수정한 방법을 찾을 수 있습니다.

 --- version: "3" services: php-apache: + network_mode: host image: geerlingguy/php-apache:latest container_name: php-apache ...

+ 는 내가 추가한 줄을 나타냅니다.


[추가 정보] 이것은 버전 2.2 에서도 작동했습니다. "호스트" 또는 그냥 '호스트'는 모두 docker-compose 에서 작동합니다.

 --- version: "2.2" services: php-apache: + network_mode: "host" or + network_mode: host ...

Ehsan88

게이트웨이 주소에 연결합니다.

 ❯ docker network inspect bridge | grep Gateway "Gateway": "172.17.0.1"

호스트의 프로세스가 이 인터페이스 또는 모든 인터페이스에서 수신 대기하고 있고 도커 이후에 시작되었는지 확인하십시오. systemd를 사용하는 경우 아래를 추가하여 docker 이후에 시작되었는지 확인할 수 있습니다.

 [Unit] After=docker.service

예시

 ❯ python -m http.server &> /dev/null & [1] 149976 ❯ docker run --rm python python -c "from urllib.request import urlopen;print(b'Directory listing for' in urlopen('http://172.17.0.1:8000').read())" True

balki

알파인 이미지를 사용하여 호스트 IP를 얻을 수 있습니다.

 docker run --rm alpine ip route | awk 'NR==1 {print $3}'

명령을 실행하기 위해 항상 alpine을 사용하기 때문에 이것은 더 일관성이 있습니다.

Mariano의 답변과 유사하게 동일한 명령을 사용하여 환경 변수를 설정할 수 있습니다

 DOCKER_HOST=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') docker-compose up

hasnat

CGroups와 Namespaces는 컨테이너 생태계에서 중요한 역할을 하고 있습니다.

네임스페이스는 격리 계층을 제공합니다. 각 컨테이너는 별도의 네임스페이스에서 실행되며 액세스는 해당 네임스페이스로 제한됩니다. Cgroup은 각 컨테이너의 리소스 사용률을 제어하는 반면 네임스페이스는 프로세스가 각 리소스를 보고 액세스할 수 있는 항목을 제어합니다.

다음은 따를 수 있는 솔루션 접근 방식에 대한 기본 이해입니다.

네트워크 네임스페이스 사용

컨테이너가 이미지에서 생성되면 네트워크 인터페이스가 정의되고 생성됩니다. 이것은 컨테이너에 고유한 IP 주소와 인터페이스를 제공합니다.

 $ docker run -it alpine ifconfig

네임스페이스를 호스트로 변경하면 컨테이너 네트워크가 인터페이스에 격리된 상태로 유지되지 않으며 프로세스는 호스트 시스템 네트워크 인터페이스에 액세스할 수 있습니다.

 $ docker run -it --net=host alpine ifconfig

프로세스가 포트에서 수신 대기하는 경우 호스트 인터페이스에서 수신 대기하고 컨테이너에 매핑됩니다.

PID 네임스페이스 사용 Pid 네임스페이스를 변경하면 컨테이너가 정상적인 범위를 넘어 다른 프로세스와 상호 작용할 수 있습니다.

이 컨테이너는 자체 네임스페이스에서 실행됩니다.

 $ docker run -it alpine ps aux

네임스페이스를 호스트로 변경하면 컨테이너는 시스템에서 실행 중인 다른 모든 프로세스도 볼 수 있습니다.

 $ docker run -it --pid=host alpine ps aux

네임스페이스 공유

이는 취약점에 노출될 수 있고 도청자에게 쉽게 액세스할 수 있는 컨테이너 보안 모델을 벗어나기 때문에 프로덕션 환경에서 이 작업을 수행하는 것은 좋지 않습니다. 이것은 도구를 디버깅하고 컨테이너 보안의 허점을 과소평가하기 위한 것입니다.

첫 번째 컨테이너는 nginx 서버입니다. 이것은 새로운 네트워크와 프로세스 네임스페이스를 생성할 것입니다. 이 컨테이너는 새로 생성된 네트워크 인터페이스의 포트 80에 바인딩됩니다.

 $ docker run -d --name http nginx:alpine

다른 컨테이너는 이제 이 네임스페이스를 재사용할 수 있습니다.

 $ docker run --net=container:http mohan08p/curl curl -s localhost

또한 이 컨테이너는 공유 컨테이너에 있는 프로세스와의 인터페이스를 볼 수 있습니다.

 $ docker run --pid=container:http alpine ps aux

이렇게 하면 애플리케이션을 변경하거나 다시 시작하지 않고도 컨테이너에 더 많은 권한을 부여할 수 있습니다. 비슷한 방식으로 호스트의 mysql에 연결하고 애플리케이션을 실행하고 디버그할 수 있습니다. 그러나 이 방법을 사용하는 것은 권장하지 않습니다. 도움이 되기를 바랍니다.


mohan08p

컨테이너의 IP에 대해 MySQL에서 사용자를 생성하여 해결했습니다.

 $ sudo mysql<br> mysql> create user 'username'@'172.17.0.2' identified by 'password';<br> Query OK, 0 rows affected (0.00 sec) mysql> grant all privileges on database_name.* to 'username'@'172.17.0.2' with grant option;<br> Query OK, 0 rows affected (0.00 sec) $ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf <br>bind-address = 172.17.0.1 $ sudo systemctl restart mysql.service

그런 다음 컨테이너에서: jdbc:mysql://<b>172.17.0.1</b>:3306/database_name


Leandro

ifconfig 를 수행하여 호스트 IP를 확인한 다음 컨테이너 내에서 IP에 연결하면 완벽하게 작동합니다.


Duc Trung Mai

수정 사항 master 분기에 병합되지 않을 때까지 호스트 IP를 얻으려면 컨테이너 내부에서 실행하면 됩니다.

 ip -4 route list match 0/0 | cut -d' ' -f3

(여기 @Mahoney가 제안한 대로).


patryk.beza

모든 것이 작동하도록 하려면 기본 도메인이 "docker.for.mac.localhost"가 될 서버(caddy, nginx)에 대한 구성을 만들어야 합니다. 이를 위해 "http://docker.for.mac.localhost/api"의 baseURL "http://localhost/api"를 교체하십시오.

docker-compose.yml

 backend: restart: always image: backend build: dockerfile: backend.Dockerfile context: . environment: # add django setting.py os.getenv("var") to bd config and ALLOWED_HOSTS CORS_ORIGIN_WHITELIST DJANGO_ALLOWED_PROTOCOL: http DJANGO_ALLOWED_HOSTS: docker.for.mac.localhost POSTGRES_PASSWORD: 123456 POSTGRES_USER: user POSTGRES_DB: bd_name WAITDB: "1" volumes: - backend_static:/app/static - backend_media:/app/media depends_on: - db frontend: restart: always build: dockerfile: frontend.Dockerfile context: . image: frontend environment: # replace baseURL for axios API_URL: http://docker.for.mac.localhost/b/api API_URL_BROWSER: http://docker.for.mac.localhost/b/api NUXT_HOST: 0.0.0.0 depends_on: - backend caddy: image: abiosoft/caddy restart: always volumes: - $HOME/.caddy:/root/.caddy - ./Caddyfile.local:/etc/Caddyfile - backend_static:/static - backend_media:/media ports: - 80:80 depends_on: - frontend - backend - db

캐디파일.local

 http://docker.for.mac.localhost { proxy /b backend:5000 { header_upstream Host {host} header_upstream X-Real-IP {remote} header_upstream X-Forwarded-For {remote} header_upstream X-Forwarded-Port {server_port} header_upstream X-Forwarded-Proto {scheme} } proxy / frontend:3000 { header_upstream Host {host} header_upstream X-Real-IP {remote} header_upstream X-Forwarded-For {remote} header_upstream X-Forwarded-Port {server_port} header_upstream X-Forwarded-Proto {scheme} } root / log stdout errors stdout gzip } http://docker.for.mac.localhost/static { root /static } http://docker.for.mac.localhost/media { root /media }

장고 설정.py

 ALLOWED_HOSTS = [os.getenv("DJANGO_ALLOWED_HOSTS")] CORS_ORIGIN_WHITELIST = [f'{os.getenv("DJANGO_ALLOWED_PROTOCOL")}://{os.getenv("DJANGO_ALLOWED_HOSTS")}'] DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": os.getenv("POSTGRES_DB"), "USER": os.getenv("POSTGRES_USER"), "PASSWORD": os.getenv("POSTGRES_PASSWORD"), "HOST": "db", "PORT": "5432", } }

nuxt.config.js(baseURL 변수는 환경의 API_URL을 재정의함)

 axios: { baseURL: 'http://127.0.0.1:8000/b/api' },

wiseCoder

호스트의 서버가 포트 5000에서 수신 대기 중입니다. response from host 으로 문자열 응답을 다시 보냅니다.

echo "response from host" | nc -l -p 5000

도커는 기본적으로 브리지 모드에서 실행됩니다(즉, 호스트 네트워크 모드에서 실행하는 것보다 안전함). 도커의 프로세스는 127.0.0.1이 아닌 호스트의 첫 번째 네트워크 인터페이스에 대한 ipv4 주소를 가져옵니다. 이 ipv4 주소는 HOSTIP 환경 변수를 통해 도커에 전달됩니다. 도커 내부에는 호스트 IP 및 포트 5000의 서버에 연결하는 nc 명령이 있습니다. 이 명령은 서버의 응답도 읽습니다.

HOST=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -1 | sed -n 's/[^0-9]*\([0-9\.]*\)/\1/p'); docker run -e HOSTIP="${HOST}" --rm -it alpine /bin/sh -c 'echo "greetings from container" | nc $HOSTIP 5000 -v'

첫 번째 나열된 인터페이스의 ipv4 주소를 계산하는 표현식은 osx 및 linux에서 작동합니다.

HOST=$(ifconfig | grep 'inet ' | grep -v 127.0.0.1 | awk '{ print $2 }' | head -1 | sed -n 's/[^0-9]*\([0-9\.]*\)/\1/p')

더 일반적으로 만들려면 다음과 같이 다른 도커 컨테이너 내부에서 서버를 실행할 수 있습니다.

docker run --expose 5000 -p :5000:5000 --rm -it alpine /bin/sh -c 'echo "response from host" | nc -l -p 5000'

--expose 5000 도커 컨테이너는 포트 5000에서 연결을 수락할 수 있습니다.

-p :5000:5000 호스트 측의 도커 엔진은 모든 인터페이스의 포트 5000에서 수신 대기하고 컨테이너 네트워크(nc가 실행 중인)의 포트 5000으로 연결을 전달합니다.


MichaelMoser

출처 : http:www.stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach

반응형