Contents

[Docker] 도커의 컨테이너 간 네트워킹에 대해서 알아보자

Docker 자체는 가상화 엔진이다.

하지만 도커가 한번에 하나의 프로그램만 실행시킬 수 있었다면 이렇게까지 인기를 얻진 못했으리라. 여러개의 컨테이너를 올리고, 하나의 컴퓨터 내에서 각각 독립된 환경에서 실행과 네트워킹이 가능하기 때문에 유용하다고 생각했다. 하지만 구체적으로 어떻게 네트워킹하는지에 대해서 생각해보진 못했는데, 이번 기회에 알아보자.

일단, 개개의 컨테이너는 여러가지 환경에 처할 수 있다. 컨테이너가 생성되고 실행되는 환경은 대략적으로 크게 두가지로 정리될 수 있을 것이다.

  • 하나의 Compose 내에서 실행될 때
  • 독립적인 컨테이너로써 실행될 때

개개의 경우의 수에서 각각의 hostname 과 도커 엔진이 제공하는 예약어가 어떻게 작동하는지 기술해보았다.

localhost

로컬 호스트는 명백하다. 어떤 상황이던간에 컨테이너 자신 자체를 가리킨다.

따라서 localhost 만으로는 다른 컨테이너 혹은 호스트와 제대로 소통할 수 없다.

host.docker.internal

host.docker.internal 은 도커에서의 환경에서 해당 도커를 실행하는 호스트를 향할 수 있게 해준다.

예를 들어, 도커에서 호스트에서 실행하는 다른 서버에 접근하고 싶다고 하자.

/2025-10-30-docker-container-networking/BaseChest%20%EA%B0%9C%EB%B0%9C%EA%B8%B0%201%20-%20host.docker.internal-1761828168099.webp

이럴때 어떻게 할까? 앞서 언급된 localhost 라면 컨테이너 그 자체를 가리키기 때문에 실패할 것이다.

이때, host.docker.internal 내부 도메인을 사용하면 된다. 이는 도커 엔진에서 제공 된다.

다른 컨테이너를 향할 수 있는가?

두가지의 이슈로 나뉠 수 있다.

  • 같은 Docker compose 에 속하는 컨테이너일때
  • 아예 무관한 그저 하나의 호스트가 돌리는 연관성 없는 서로 다른 컨테이너일 때

1. 같은 Compose 에 속하는 컨테이너를 찾고싶은 경우

도커 컴포즈는 이를 위해 서비스 명에 대해 호스트 도메인을 할당해준다. 이게 무슨 뜻이냐면

services:
  spring-app: # <-- (1) 이 서비스 이름
    build: .
    # ...
  nginx-proxy:
    image: nginx
    # ...

위와 같이 service 명들이 할당이 되어있다면, 아래와 같이 접근할 수 있다.

location / {
    # (2) 'spring-app' 서비스 이름을 주소처럼 사용
    proxy_pass http://spring-app:8080; 
}

2. 다른 compose 혹은 관계성이 없는 컨테이너에게 요청을 보내고 싶은 경우

이런 경우 방법이 달라진다. 일반적으로 하나의 Compose 로 묶여있지 않으므로 같은 네트워크로 묶여있지 않다. 방식은 두가지 방법이 있다.

호스트 경유 방식

/2025-10-30-docker-container-networking/%EB%8F%84%EC%BB%A4%20%EC%BB%B4%ED%8F%AC%EC%A6%88%20%EB%B0%8F%20%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%20%EA%B0%84%20%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9%EC%97%90%20%EB%8C%80%ED%95%B4%EC%84%9C%20%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-1761830157364.webp

이전에 언급된 host.docker.internal 을 이용하는 방법이다.

  • 조건 : 요청을 받을 컨테이너의 포트가 호스트로 열려있어야 가능하다.
  • 호스트 머신에게 해당 포트로 요청을 하게된다면, 호스트를 경유해서 해당 컨테이너로 요청이 들어가게 된다.

공용 네트워크 방식

/2025-10-30-docker-container-networking/%EB%8F%84%EC%BB%A4%20%EC%BB%B4%ED%8F%AC%EC%A6%88%20%EB%B0%8F%20%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%20%EA%B0%84%20%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%82%B9%EC%97%90%20%EB%8C%80%ED%95%B4%EC%84%9C%20%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-1761830033430.webp

도커에서 제공되는 기능인 공용 네트워크를 이용하는 방법이다.

보다 도커의 기능들을 활용하므로 권장되는 방법일 것이다.

  • 먼저, 두 컨테이너가 함께 사용할 공용 네트워크를 하나 만들 수 있다.
docker network create my-shared-network
  • compose 의 경우, 내가 외부 네트워크에 연결하고자 하는 컴포즈 설정에서 아래와 같이 설정해주면 된다.
services:
  spring-app:
    # ...
    networks:
      - default
      - my-shared-network # <-- 공용 네트워크 추가

networks:
  default:
  my-shared-network:
    external: true # <-- 외부에서 만든 네트워크라고 알려줌
  • compose 가 아닌 단일 컨테이너의 경우 명령어를 통해 수동으로 공용 네트워크를 생성하고 두 컨테이너를 해당 네트워크에 연결해주면 된다.
  • 이때, --name service-a 라는 부분이 있는데, 이 이름을 통해 통신할 수 있다.
docker run -d --name service-a --network my-shared-network [이미지 1 이름]
docker run -d --name service-b --network my-shared-network [이미지 2 이름]

전자의 경우 가장 간단하며, 후자의 경우 네트워크가 깔끔하게 관리될 수 있다는 점에서 일장일단인듯.

질문 : 컨테이너들은 아예 외부를 향해 네트워크를 요청할 수 있는가?

프로젝트가 커지면 데이터 안정성을 위해 DB 등을 별도의 서버로 분리할 수도 있을 것이다.

당연히 가능하며, 이때 호스트는 라우터로써 작동된다.

  1. 컨테이너가 외부를 향하는 네트워크 요청을 호스트 머신으로 전달한다.
  2. 호스트 머신은 이 요청을 받아 자신의 IP를 사용해 연결된 외부 인터넷으로 요청을 보낸다. (이 과정을 NAT라고 부른다.)
  3. 응답을 받고, 호스트 머신은 컨테이너로 결과를 반환해준다.