Docker를 활용하여 여러 개의 컨테이너를 실행하는 경우, 컨테이너 간의 통신이 중요한 문제입니다. 특히, localhost를 사용한 통신이 제대로 동작하지 않는 문제를 해결하려면 몇 가지 중요한 개념을 이해해야 합니다. 본 포스트에서는 Docker Compose 환경에서 컨테이너 간의 통신 방식과 그 이유를 살펴보겠습니다.
1. localhost를 통해서 소통하지 못하는 이유
Docker에서 각 컨테이너는 독립적인 환경을 갖고 있으며, 자체적인 네트워크를 사용합니다. 이 때문에, localhost는 각 컨테이너 내에서 자기 자신만을 참조합니다. 즉, 하나의 컨테이너가 localhost:3001로 접근한다고 하더라도, 그 컨테이너 내에서만 동작하고 다른 컨테이너와는 소통할 수 없습니다.
이 문제는 여러 컨테이너가 서로 통신해야 할 때 발생할 수 있습니다. 예를 들어, auth 컨테이너가 alarm 컨테이너에 요청을 보내려고 할 때, localhost를 사용하면 auth 컨테이너 자체에 요청을 보내게 되어 alarm 컨테이너와의 연결이 이루어지지 않게 됩니다. 이 문제를 해결하려면 컨테이너 간의 네트워크 통신을 위한 적절한 주소를 사용해야 합니다.
2. localhost 대신에 사용할 수 있는 URL 그리고 동작이 가능한 이유
Docker Compose에서는 컨테이너 간 통신을 위해 서비스 이름을 사용하는 방식이 일반적입니다. 예를 들어, docker-compose.yml 파일에서 alarm 서비스가 정의되었다면, 다른 컨테이너는 alarm:3001과 같은 서비스 이름을 사용하여 해당 서비스에 접근할 수 있습니다.
Docker Compose는 각 서비스에 대해 자동으로 DNS 이름을 할당합니다. 이렇게 할당된 이름은 Docker 네트워크 내에서 다른 컨테이너가 해당 서비스에 접근할 수 있도록 해줍니다. 따라서 auth 컨테이너는 alarm:3001으로 요청을 보낼 수 있게 되는 것입니다.
동작 가능한 이유는 Docker Compose가 내부 DNS 시스템을 사용하여 서비스 이름을 컨테이너의 네트워크 주소로 자동으로 해석해 주기 때문입니다. 이 시스템 덕분에, 각 컨테이너는 localhost 대신 서비스 이름을 사용하여 다른 컨테이너와 소통할 수 있습니다.
docker-compose.yml
services:
auth-service:
build: ./services/auth
ports:
- "3000:3000"
env_file:
- ./services/auth/.env
alarm-service:
build: ./services/alarm
ports:
- "3001:3001"
env_file:
- ./services/alarm/.env
API가 정상인 경우 localhost 대신에 아래와 같이 docker-compose에 작성한 서비스명 기준으로 요청을 보낼 수 있다
const alarmResponse = await axios.post(
"http://alarm-service:3001/api/alarms/login",
{
userId: "test",
type: "signup",
message: "Welcome! Your account has been created successfully.",
email: "test-email", // 이메일 주소
}
);
3. Docker Compose에 my_network 설정이 필요 없는 이유
Docker Compose에서 여러 서비스가 통신하기 위해 별도로 네트워크를 설정할 필요는 없습니다. 기본적으로 Docker Compose는 모든 서비스가 같은 네트워크를 공유하도록 설정합니다. 이 기본 네트워크는 bridge 네트워크 모드로 자동 설정되며, 이 네트워크 내에서 서비스 간의 통신이 가능합니다.
따라서 my_network와 같은 사용자 정의 네트워크를 명시적으로 정의하지 않아도, Docker Compose 내에서 서비스 이름으로 다른 컨테이너와 통신이 가능합니다. 이는 Docker의 자동 네트워크 설정 덕분에 별도의 네트워크 설정 없이도 서비스 간에 원활한 통신이 이루어지도록 해줍니다.
결론
Docker Compose 환경에서는 여러 컨테이너가 서로 통신할 때, localhost를 사용하지 않고 서비스 이름을 사용해야 합니다. localhost는 각 컨테이너 내에서 자기 자신을 참조하기 때문에, 컨테이너 간의 통신을 위해서는 서비스 이름을 이용한 URL을 사용해야 합니다. 또한, Docker Compose는 기본적으로 모든 서비스가 동일 네트워크를 공유하게 설정되므로, 별도의 네트워크 설정 없이도 서비스 간 통신이 가능합니다.
이와 같은 기본적인 원리를 이해하고 설정을 적절히 적용하면, Docker Compose 환경에서 다양한 서비스가 문제 없이 상호작용하며 동작할 수 있습니다.