머리말

머리말

머리말

/etc/hosts컨테이너 내부에 Docker 호스트의 올바른 IP 주소를 추가하는 일반 셸 스크립트를 작성하고 싶습니다 .

내가 액세스하려는 서비스를 다른 도커 컨테이너에도 넣으라고 제안할 수도 있지만 가장 빠른 CI 테스트를 위해 컨테이너의 IP를 통해 도커 호스트에 액세스하고 싶기 때문에 그것이 필요합니다.

하나 있다github 문제에는 댓글이 많습니다사람들은 호스트 IP에 액세스하는 통합된 방법을 요구하고 있습니다. 모든 플랫폼 ATM에 적용할 수 있는 단일 솔루션은 없습니다.

사람들은 다음과 같은 스크립트를 만듭니다.

grep dockerhost /etc/hosts || echo $(ip r | grep ^default | cut -d" " -f3) dockerhost >> /etc/hosts

Docker 호스트에 액세스하기 위해 동일한 방법을 사용하고 싶지만 Mac atm에서는 작동하지 않습니다. 반환된 결과는 다음과 같습니다.

ip r | grep ^default | cut -d" " -f3

Docker 호스트가 Mac인 경우 잘못된 대답이 제공됩니다 172.17.0.1(실제로 컨테이너를 사용하여 컨테이너에서 Mac에 액세스할 수 없음 172.17.0.1).

Mac용 Docker에는 다음과 같은 기능이 있습니다.특수 호스트 이름 docker.for.mac.localhost이를 사용하여 컨테이너에서 호스트 Mac에 액세스할 수 있습니다.

질문

먼저 확인 된 주소를 구문 sh분석 하고 .docker.for.mac.localhost/etc/hostsip r | grep ^default | cut -d" " -f3/etc/hosts

docker.for.mac.localhost질문은: 어떤 컨테이너에서든 어떻게 구문 분석을 시도합니까 ? ( nslookup예를 들어 일부 배포판은 그렇지 않습니다). 아니면 문제를 해결하려고 하지 말고 docker.for.mac.localhost어딘가에서 값을 읽으려고 노력할 수 있을까요?

내 현재 생각은 시도해 보고 getent ahosts docker.for.mac.localhost명령이 존재하지 않으면 이를 사용해 보는 것입니다 (즉, Busybox 이미지에 명령이 nslookup없습니다 ). getent어쩌면 내가 잘못 해결하려고 시도하는 것일 수도 docker.for.mac.localhost있고 더 쉬운 방법으로 검색할 수 있습니다. 당신의 생각을 공유해주세요.

감사해요.

답변1

docker.for.mac.localhost를 해결하려는 아이디어는 확실합니다. 거의 모든 컨테이너에서 이를 해결할 수 있는 것을 찾으면 됩니다. 이렇게 하면 됩니다(내 테스트에 따르면).

grep dockerhost /etc/hosts || echo $( (ping -c1 docker.for.mac.localhost || (ip r | grep ^default)) | grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts

진입점( )의 일부로 수행하거나 sh -c일종의 초기화 스크립트에서 수행할 수 있습니다.

자세한 내용, 보다 완전한 버전의 리뷰 및 주의 사항을 보려면 계속 읽어보세요.

우리가 하는 일은 Linux가 이름을 확인하도록 하는 것뿐입니다. nc와 Traceroute는 거의 어디에나 존재하지만 Ping은 가장 간단한 옵션일 뿐입니다. 다른 모든 방법이 실패하면 실제로 최신(BusyBox는 아님) bash 또는 syslog를 사용하여 이 작업을 수행할 수 있습니다. 기본적으로 Docker는 동일한 네트워크에 있는 다른 컨테이너(또는 이전 버전에서는 연결된 컨테이너)의 이름에 응답하는 작은 DNS 서버를 설정합니다. 그런 다음 docker.for.mac.localhost추가하십시오.

해결이 되지 않는다면 DNS 서버가 해결하지 못한 것이므로 정상적으로 호스트를 얻을 수 있다는 의미입니다. 대신 /proc/net 메소드를 사용할 수도 있지만 내 테스트 컨테이너에서는 동일한 것으로 보입니다.

이제 몇 가지 주의 사항이 있습니다. 첫째, 큰 문제입니다. 네트워크에 연결되어 있지 않으면 최대 30초까지 시간이 영원히 초과됩니다. 아래의 더 큰 스크립트에는 몇 가지 수정 사항이 있습니다. 또한 컨테이너의 빌드 프로세스 중에는 이를 실행할 수 없습니다(기본적으로 이를 재정의하는 방법이 있음). 대신 아무 작업도 수행하지 않을 수 있습니다. Docker는 컨테이너를 시작할 때 새 /etc/hosts를 마운트합니다.

더 나은 버전이 작동 timeout하지만 문제가 있습니다. 호환되지 않는 버전이 (적어도) 2개 있고, 존재하지 않을 수도 있다고 가정하려는 경우 세 번째 경우가 있습니다.

grep dockerhost /etc/hosts || echo $( (
(if timeout -t1 env >/dev/null; then \
     timeout -t1 ping -c1 docker.for.mac.localhost; \
   elif timeout 1s env >/dev/null; then
      timeout 1s ping -c1 docker.for.mac.localhost; \
   else \
      ping -c1 docker.for.mac.localhost; \
fi) \
|| (ip r | grep ^default)) \
| grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts

env를 사용하는 이유는 내장되지 않은 쉘 버전( /usr/bin/env대부분의 경우)이 거의 확실하고, 잘 알려진 인터페이스(즉, 입력 없이 실행됨)가 있으며, 다음의 영향을 받을 가능성이 거의 없기 때문입니다. 환경 ls파일 시스템에 의존하는 불쾌한 명령과 다른 이유로 실패하는 문제.

마지막으로, 내가 사용하고 있는 것과 유사한 완전히 주석이 달린 버전입니다(내 뒤에 있는 사람들이 무슨 일이 일어나고 있는지 이해할 수 있도록):

add_dockerhost_address() {
  # The name we're checking for - in case this technique is useful on Windows 
  # if we get a Windows version instead of a cross-platform one
  local MACHOST="docker.for.mac.localhost"
  # The name we want to insert into /etc/hosts
  local DOCKERHOSTNAME="dockerhost"

  # Don't insert the name twice
  if grep "$DOCKERHOSTNAME" /etc/hosts >/dev/null 2>&1; then
    return 0
  fi

  # A command string we'll be building
  local COMMAND=""

  # Check for the ability to limit the timeout
  if command -v timeout >/dev/null 2>&1; then
    # We still have a problem - there are two widely used incompatible
    # variants of timeout. Let's see which one we have.

    # env should not be a builtin, doesn't require a pipe,
    # has a consistent command line test, and is unlikely to fail
    if timeout -t1 env >/dev/null 2>&1; then
      COMMAND="timeout -t1 "
    else
      COMMAND="timeout 1s "
    fi
  fi

  local IS_NOT_MAC=1
  local IP=""

  if command -v ping >/dev/null 2>&1; then
    COMMAND="$COMMAND ping -c1 $MACHOST"
    # Otherwise, BusyBox shows terminated.
    IP=$(sh -c "$COMMAND" 2>&1)
    # Exit codes: 0 - found the host, 1/2 failed to find, 124/143 terminated
    IS_NOT_MAC="$?"
  fi

  if [ "$IS_NOT_MAC" -eq 0 ]; then
    IP=$(echo "$IP" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')    
  else
    IP=$(ip r | grep ^default | cut -d" " -f3)
  fi

  echo "$IP $DOCKERHOSTNAME" >> /etc/hosts
}

add_dockerhost_address

exec "/usr/sbin/apachectl" "-DFOREGROUND"

답변2

나는 그것이 언급되었다고 믿는다여기사용할 수 있습니다 docker.for.mac.host.internal. 언급되지 않았지만 docker.for.mac.localhost나에게도 효과가 있습니다.

그런 다음 다음 줄을 사용하여 Mac용 Docker에서 실행 중인지 확인합니다.

$ getent hosts docker.for.mac.host.internal

$?docker.for.mac.host.internal찾으면 말해주세요 .

실제 IP를 얻으려면 awk아래와 같이 를 사용할 수도 있습니다.

$ getent hosts docker.for.mac.host.internal | awk '{ print $1 }'

관련 정보