Docker-compose 시 virtual host 업데이트가 되지 않는 문제
이전 글에서는 nginx-proxy 를 사용하여 하나의 서버에서 다양한 서브도메인을 처리하는 방법을 살펴보았다 (참고: Docker 를 사용한 가상 호스트(Virtual Host) 구축 및 서브 도메인 연결). nginx-proxy 이미지에 포함된 docker-gen 이 새로운 컨테이너가 실행 될 때마다 실행되는 컨테이너의 VIRTUAL_HOST
환경변수를 읽어들이는 방식이다. 이 때 내가 겪었던 문제는 docker-compose 를 통하여 컨테이너를 실행할 경우 서브 도메인 연결이 실패한다는 점이었다. nginx-proxy 의 로그를 살펴보면 다음과 같이 nginx -s reload
가 실패하는 것을 볼 수 있다.
dockergen.1 | 2017/07/11 07:48:43 Received event start for container d4e6b438872d
dockergen.1 | 2017/07/11 07:48:43 Generated '/etc/nginx/conf.d/default.conf' from 8 containers
dockergen.1 | 2017/07/11 07:48:43 Running 'nginx -s reload'
dockergen.1 | 2017/07/11 07:48:43 Error running notify command: nginx -s reload, exit status 1
문제 발생 원인
이 문제는 nginx-proxy 컨테이너와 새로 실행되는 컨테이너가 (로그에서는 container d4e6b438872d
) 같은 네트워크에 속해 있지 않기 때문에 발생하는 것으로 보인다. docker-compose 를 수행하면 compose 내에 있는 service 들 끼리 자동적으로 네트워크를 설정하는데, 이 네트워크는 nginx-proxy 에서 접근할 수 없으므로 문제가 발생하는 것이다. 예를 들어 wordpress 디렉토리에서 docker-compose 를 수행할 경우 wordpress-default 라는 네트워크가 만들어진다(존재하는 네트워크의 목록은 docker network ls
명령으로 확인이 가능하다). Docker 의 네트워크에 대해서는 문서를 참고하면 좋다.
nginx-proxy 의 네트워크 확인
따라서 문제를 해결하기 위해서는 nginx-proxy 가 서브 도메인을 담당하는 컨테이너들과 같은 네트워크에 속하도록 설정해야 한다. 그러므로 nginx-proxy 의 네트워크나 docker-compose 로 생긴 컨테이너가 속한 네트워크를 찾아야 하는데, docker inspect <container>
명령을 이용하여 실행 중인 컨테이너의 네트워크를 확인할 수 있다. NetworkSettings 아래에 Networks 가 존재하며, 여기에서 해당 컨테이너가 속해 있는 네트워크를 확인할 수 있다. 나의 경우 해당하는 부분은 다음과 같다.
Networks: {
bridge: {
IPAMConfig: null,
Links: null,
Aliases: null,
NetworkID: 1c856e0515caf284713b1bef2369df6c7a1beb2c3e91d6ae4361c9d2f4f11764,
EndpointID: 78378336490f770ac39ff11fdecb843b674c357e66cbdff9ec82c63cb0a53610,
Gateway: 172.17.0.1,
IPAddress: 172.17.0.2,
IPPrefixLen: 16,
IPv6Gateway: ,
GlobalIPv6Address: ,
GlobalIPv6PrefixLen: 0,
MacAddress: 02:42:ac:11:00:02
}
}
즉 나의 nginx-proxy 가 속해 있는 네트워크의 이름은 기본 네트워크인 bridge 인 것을 확인할 수 있다.
Option 1. nginx-proxy 와 같은 네트워크를 사용하도록 docker-compose 수정
첫 번째 방법은 docker-compose 를 수정하여 nginx-proxy 의 네트워크로 포함되도록 하는 것이다. 이를 위해서는 아래와 같이 networks 를 정의하고, 각각의 service 내에서는 network_mode: bridge
를 설정해 주면 된다.
version: '2'
services:
myapp:
network_mode: bridge
...
networks:
default:
external:
name: bridge
여기서 external 은 외부에 이미 존재하는 네트워크를 의미한다.
Option 2. nginx-proxy 에 네트워크 추가
둘째로는 nginx-proxy 가 여러 네트워크에 속하게 하는 방법이다. 여기서는 docker-compose 로 생성된 (또는 docker-compose 에 기술된) 네트워크에 nginx-proxy 를 추가하면 되겠다. 컨테이너에 네트워크를 추가하기 위해서는 docker network connect [OPTIONS] <network> <container>
명령을 사용하면 된다(참고: docker network connect). 명령 사용 후 docker inspect
를 통하여 네트워크가 추가된 것을 볼 수 있다. 다만 docker-gen 은 컨테이너 로드 및 삭제 시 작동하므로 네트워크 설정 후 해당하는 컨테이너를 삭제 후 다시 수행해 주어야 할 것이다.
기타
- 네트워크를 하나 만들고 nginx-proxy 와 서브 도메인을 처리하는 컨테이너만을 여기에 넣어 두는 것이 가장 효율적인 방법이 될 것이다. 다시 nginx-proxy 를 설정해야 할 경우 시도해 볼 예정.
참고
docker network - https://docs.docker.com/engine/reference/commandline/network/