다른 컨테이너에서 도커 컨테이너에 액세스


93

두 개의 서로 다른 이미지를 기반으로 두 개의 도커 컨테이너를 만들었습니다. db 중 하나와 웹 서버용. 두 컨테이너 모두 내 Mac OSX에서 실행되고 있습니다.

나는 호스트 머신에서 db 컨테이너에 액세스 할 수 있으며 동일한 방법으로 호스트 머신에서 웹 서버에 액세스 할 수 있습니다.

그러나 웹 서버에서 db 연결에 어떻게 액세스합니까?

내가 db 컨테이너를 시작한 방법은

docker run --name oracle-db -p 1521:1521 -p 5501:5500 oracle/database:12.1.0.2-ee

wls 컨테이너를 다음과 같이 시작했습니다.

docker run --name oracle-wls -p 7001:7001 wls-image:latest

다음에 연결하여 호스트의 db에 액세스 할 수 있습니다.

sqlplus scott/welcome1@//localhost:1521/ORCLCDB

호스트의 wls에 다음과 같이 액세스 할 수 있습니다.

http://localhost:7001/console

그렇다면 웹 컨테이너와 db 컨테이너가 모두 호스트 머신에 있습니까? 그렇다면 어떤 버전의 도커를 사용하고 있습니까? 이전 버전의 docker에는 한 가지 방법이 있었지만 새 버전에는 다른 방법이 있습니다. docker-compose도 사용할 수 있습니까? 더 쉽게 만들 수 있지만 사용할 수없는 방법을 사용하여 대답하고 싶지 않습니다.
Caperneoignis

이 대답은 맥 OS의 컨테이너에서 액세스 로컬 호스트에 어떻게 도움이 될 수 있습니다
Chaojun 종에게

외부 네트워킹의 경우이 솔루션이 저에게
효과적

답변:


51

가장 쉬운 방법은 --link를 사용하는 것이지만 최신 버전의 docker는 그로부터 멀어지고 있으며 실제로 스위치가 곧 제거 될 것입니다.

아래 링크는 두 개의 컨테이너를 연결하는 방법을 제공합니다. 이미지에 항목을 추가하는 데 유용한 방법이므로 첨부 부분을 건너 뛸 수 있습니다.

https://deis.com/blog/2016/connecting-docker-containers-1/

관심있는 부분은 두 컨테이너 간의 통신입니다. 가장 쉬운 방법은 웹 서버 컨테이너에서 이름으로 DB 컨테이너를 참조하는 것입니다.

예:

db 컨테이너 db1와 웹 서버 컨테이너의 이름을 지정했습니다 web0. 컨테이너는 둘 다 브리지 네트워크에 있어야합니다. 즉, 웹 컨테이너가 이름을 참조하여 DB 컨테이너에 연결할 수 있어야합니다.

따라서 앱에 대한 웹 구성 파일이있는 경우 DB 호스트에 대해 이름을 사용합니다 db1.

이전 버전의 docker를 사용하는 경우 --link를 사용해야합니다.

예:

1 단계: docker run --name db1 oracle/database:12.1.0.2-ee

그런 다음 웹 앱을 시작할 때. 사용하다:

2 단계: docker run --name web0 --link db1 webapp/webapp:3.0

웹앱이 DB에 연결됩니다. 그러나 내가 말했듯이 --link 스위치는 곧 제거됩니다.

대신 docker compose를 사용하여 네트워크를 구축합니다. 하나; 시스템 용 docker compose를 다운로드해야합니다. https://docs.docker.com/compose/install/#prerequisites

예제 설정은 다음과 같습니다.

파일 이름은 base.yml

version: "2"
services:
  webserver:
    image: "moodlehq/moodle-php-apache:7.1
    depends_on:
      - db
    volumes:
      - "/var/www/html:/var/www/html"
      - "/home/some_user/web/apache2_faildumps.conf:/etc/apache2/conf-enabled/apache2_faildumps.conf"
    environment:
      MOODLE_DOCKER_DBTYPE: pgsql
      MOODLE_DOCKER_DBNAME: moodle
      MOODLE_DOCKER_DBUSER: moodle
      MOODLE_DOCKER_DBPASS: "m@0dl3ing"
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"
  db:
    image: postgres:9
    environment:
      POSTGRES_USER: moodle
      POSTGRES_PASSWORD: "m@0dl3ing"
      POSTGRES_DB: moodle
      HTTP_PROXY: "${HTTP_PROXY}"
      HTTPS_PROXY: "${HTTPS_PROXY}"
      NO_PROXY: "${NO_PROXY}"

이것은 네트워크의 이름을 일반 이름으로 지정합니다. --name 스위치를 사용하지 않는 한 그 이름이 무엇인지 기억할 수 없습니다.

IE docker-compose --name setup1 up base.yml

참고 : --name 스위치를 사용하는 경우 docker compose를 호출 할 때이 스위치를 사용해야합니다. docker-compose --name setup1 down 하나 이상의 웹 서버 및 db 인스턴스를 가질 수 있으며이 경우 docker compose가 어떤 인스턴스를 알고 있는지 확인합니다. 명령을 실행하려고합니다. 또한 한 번에 여러 개를 실행할 수 있습니다. 동일한 서버에서 병렬로 테스트를 실행하는 경우 CI / CD에 적합합니다.

Docker compose에는 docker와 동일한 명령이 있으므로 docker-compose --name setup1 exec webserver do_some_command

가장 중요한 부분은 단위 테스트를 위해 db 또는 이와 유사한 것을 변경하려는 경우 up 명령에 추가 .yml 파일을 포함 할 수 있으며 유사한 이름을 가진 항목을 덮어 쓸 수 있다는 것입니다. .

예:

db.yml

version: "2"
services:
  webserver:
    environment:
      MOODLE_DOCKER_DBTYPE: oci
      MOODLE_DOCKER_DBNAME: XE
  db:
    image: moodlehq/moodle-db-oracle

그런 다음 전화 docker-compose --name setup1 up base.yml db.yml

이것은 db를 덮어 씁니다. 다른 설정으로. 각 컨테이너에서 이러한 서비스에 연결해야하는 경우 service 아래에 설정된 이름 (이 경우 webserver 및 db)을 사용합니다.

나는 이것이 실제로 귀하의 경우에 더 유용한 설정이라고 생각합니다. yml 파일에서 필요한 모든 변수를 설정할 수 있으므로 필요할 때 docker compose 명령을 실행하면됩니다. 그래서 더 시작하고 설정을 잊어 버리십시오.

참고 : 나는 --port컨테이너-> 컨테이너 통신을 위해 포트를 노출 할 필요가 없기 때문입니다. 호스트가 컨테이너 또는 호스트 외부에서 애플리케이션에 연결하도록하려는 경우에만 필요합니다. 포트를 노출하면 호스트가 허용하는 모든 통신에 포트가 열려 있습니다. 따라서 포트 80에서 웹을 노출하는 것은 물리적 호스트에서 웹 서버를 시작하는 것과 동일하며 호스트가 허용하는 경우 외부 연결을 허용합니다. 또한 어떤 이유로 든 한 번에 하나 이상의 웹앱을 실행하려는 경우 포트 80을 노출하면 해당 포트에서도 노출을 시도 할 경우 추가 웹앱을 실행할 수 없습니다. 따라서 CI / CD의 경우 포트를 전혀 노출하지 않는 것이 가장 좋으며 docker compose를 --name 스위치와 함께 사용하면 모든 컨테이너가 자체 네트워크에 있으므로 충돌하지 않습니다. 그래서 당신은 컨테이너 컨테이너를 거의 가질 것입니다.

업데이트 : 기능을 더 사용하고 다른 사람들이 Jenkins와 같은 CICD 프로그램에 대해 어떻게 수행했는지 확인한 후. 네트워크도 실행 가능한 솔루션입니다.

예:

docker network create test_network

위의 명령은 다른 컨테이너도 연결할 수있는 "test_network"를 생성합니다. --network스위치 오퍼레이터 로 쉽게 만들 수 있습니다.

예:

docker run \
    --detach \
    --name db1 \
    --network test_network \
    -e MYSQL_ROOT_PASSWORD="${DBPASS}" \
    -e MYSQL_DATABASE="${DBNAME}" \
    -e MYSQL_USER="${DBUSER}" \
    -e MYSQL_PASSWORD="${DBPASS}" \
    --tmpfs /var/lib/mysql:rw \
    mysql:5

물론 프록시 네트워크 설정이있는 경우 "-e"또는 "--env-file"스위치 문을 사용하여 해당 설정을 컨테이너에 전달해야합니다. 따라서 컨테이너는 인터넷과 통신 할 수 있습니다. Docker는 프록시 설정이 최신 버전의 docker에서 컨테이너에 흡수되어야한다고 말합니다. 그러나 나는 여전히 그것들을 습관으로 전달합니다. 이것은 사라질 "--link"스위치를 대체합니다. 컨테이너가 생성 한 네트워크에 연결되면 컨테이너의 '이름'을 사용하여 다른 컨테이너에서 해당 컨테이너를 계속 참조 할 수 있습니다. 위의 예에 따라 db1. 모든 컨테이너가 동일한 네트워크에 연결되어 있는지 확인하기 만하면됩니다.

cicd 파이프 라인에서 네트워크를 사용하는 자세한 예는 다음 링크를 참조하십시오. https://git.in.moodle.com/integration/nightlyscripts/blob/master/runner/master/run.sh

Moodle에 대한 대규모 통합 테스트를 위해 Jenkins에서 실행되는 스크립트이지만 아이디어 / 예제는 어디에서나 사용할 수 있습니다. 이것이 다른 사람들에게 도움이되기를 바랍니다.


1
첫 번째 링크가 작동하지 않으면이 링크를 사용할 수 있습니다. linode.com/docs/applications/containers/…
Caperneoignis

1
Docker가 네트워크를 구성하거나 수행하는 경우 웹 서버가 DB를 어떻게 참조합니까? 컨테이너 이름을 사용합니까? 두 번째 링크는 다음과 같습니다. 따라서 DB와 APP를 정의하면 앱이이 경우를 참조해야합니다. psql -U {USER} -h database -p 5432 {DATABASE}내가
쉘링

1
@Fallenreaper 컨테이너에 있고 docker가 구성한 경우 명시 적으로 이름을 지정하지 않은 경우 "services :"에서 사용되는 이름을 사용합니다. 따라서 예제에서 쉘의 "db"컨테이너에서 연결을 시도하는 경우 "webserver"를 사용합니다. db.yml의 예를 보면 webserver 및 db라는 이름을 사용합니다. 지연되어 죄송합니다. 알림을 잊어 버렸습니다.
Caperneoignis

52

그것은 간단합니다. 두 개 이상의 실행중인 컨테이너가있는 경우 다음 단계를 완료하십시오.

docker network create myNetwork
docker network connect myNetwork web1
docker network connect myNetwork web2

이제 web1에서 web2 컨테이너로 또는 그 반대로 연결합니다.

다음을 실행하여 찾을 수있는 내부 네트워크 IP 주소를 사용하십시오.

docker network inspect myNetwork

내부 IP 주소와 포트만 네트워크 브리지로 연결된 컨테이너에 액세스 할 수 있습니다.

예를 들어 web1 컨테이너가 다음으로 시작되었다고 가정하고 docker run -p 80:8888 web1(서버가 내부적으로 포트 8888에서 실행 중임을 의미 함), 검사 myNetwork결과 web1의 IP가 172.0.0.2 인 것으로 표시되며을 사용하여 web2에서 web1로 연결할 수 있습니다 curl 172.0.0.2:8888.


1
안녕하세요, web1에서 web2로 어떻게 연결합니까? IP로, 호스트 이름? 이 정보는 어디에서 얻을 수 있습니까?
Henry Ávila

docker-compose.yml 파일에서 네트워크 생성 : myNetwork.
MxWild

14
@ HenryÁvila 컨테이너의 이름 (예 :)을 web1호스트 이름으로 사용합니다.
Pascal

19

호스트 컴퓨터의 IP를 통해 db에 액세스해야합니다. 또는 localhost : 1521을 통해 액세스하려면 다음과 같이 웹 서버를 실행해야합니다.

docker run --net=host --name oracle-wls wls-image:latest

여길 봐


1
호스트의 IP가 실행중인 머신 컨테이너에 따라 변경되므로 실제 생활에서 어떻게 작동할까요?
Vik

1
머신에 고정 IP 또는 DNS가있는 경우에만 유효하며 그렇지 않으면 두 번째 방법을 사용합니다.
xitter

나는 이것에 문제가있는 것 같다. 내 정확한 실행 명령은 다음과 같습니다. docker run --name ora-tools-wls -it -p 7001 : 7001 orawls 작동하며이 컨테이너에서 실행중인 내 서버에 localhost : 7001 / console로 액세스 할 수 있습니다. 그러나 서버에서 db 액세스가 필요합니다. DB를 실행하는 다른 컨테이너에 도달하기위한 정확한 IP. docker run --name ora-tools-wls -it -p 7001 : 7001 --network = "host"orawls를 사용하면 서버가 언급 한대로 localhost를 ip로 사용하여 db에 액세스 할 수 있지만 호스트 컴퓨터 브라우저에서 서버에 액세스 할 수 있습니다. 실패합니다.
Vik

3
-p 7001:7001모든 컨테이너가 호스트의 네트워크 스택 자체를 사용 하므로을 정의 할 필요가 없습니다 .
xitter

@Vik, 같은 문제가 있었고 Mac에서 지원되지 않는다는 것을 알았습니다. 그게 당신이하는 일이기도합니다. > 호스트 네트워킹 드라이버는 Linux 호스트에서만 작동하며 Mac 용 Docker Desktop, Windows 용 Docker Desktop 또는 Windows Server 용 Docker EE에서는 지원되지 않습니다. docs.docker.com/network/host
Brent Fisher

9

를 사용하면 docker-compose기본적으로 서비스가 이름별로 서로 노출됩니다. 문서 .
다음과 같은 별칭을 지정할 수도 있습니다.

version: '2.1'
services:
  mongo:
    image: mongo:3.2.11
  redis:
    image: redis:3.2.10
  api:
    image: some-image
    depends_on:
      - mongo
      - solr
    links:
      - "mongo:mongo.openconceptlab.org"
      - "solr:solr.openconceptlab.org"
      - "some-service:some-alias"

그리고 예를 들어 호스트 이름으로 지정된 별칭을 사용하여 서비스에 액세스 mongo.openconceptlab.org하기위한 mongo이 경우.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.