본래 PostgreSQL을 Docker 컨테이너로 돌리다가 굳이 Docker로 돌릴 필요가 있나 싶어 로컬 서비스로 옮기기로 했다.
다만 그냥 옮겨서 바로 포트에 연결해 사용할 수는 없고 추가적인 설정이 필요하다.
PostgreSQL 설정 #
연결 설정 #
Docker 컨테이너는 docker0
인터페이스를 통해 외부와 통신한다.
이는 컨테이너 내에서 포트에 연결을 요청하면 로컬에서는 docker0
로부터의 요청으로 해석된다는 것이다.
PostgreSQL이 기본적으로 localhost
만 LISTEN 하기 때문에 이를 docker0
도 LISTEN 하도록 수정해 줄 필요가 있다.
postgresql.conf
를 열어 listen_addresses
항목을 수정한다.
1# ip route show dev docker0
2172.17.0.0/16 proto kernel scope link src 172.17.0.1 linkdown
1#------------------------------------------------------------------------------
2# CONNECTIONS AND AUTHENTICATION
3#------------------------------------------------------------------------------
4
5# - Connection Settings -
6
7listen_addresses = 'localhost,172.17.0.1'
8 # what IP address(es) to listen on;
9 # comma-separated list of addresses;
10 # defaults to 'localhost'; use '*' for all
11 # (change requires restart)
12#port = 5432 # (change requires restart)
13max_connections = 100 # (change requires restart)
14#reserved_connections = 0 # (change requires restart)
IP 필터링을 사용할 이유가 없다면 *
로 설정해 모든 IP를 허용해도 상관없다.
인증 설정 #
PostgreSQL은 pg_hba.conf
파일에 선언된 IP가 아니면 연결을 거부한다.
필요에 따라 IP 범위와 인증 방식을 지정해주면 된다.
아래 예시에서는 마지막 줄이 Docker를 위한 설정이다.
1# TYPE DATABASE USER ADDRESS METHOD
2
3# "local" is for Unix domain socket connections only
4local all all scram-sha-256
5# IPv4 local connections:
6host all all 127.0.0.1/32 scram-sha-256
7# IPv6 local connections:
8host all all ::1/128 scram-sha-256
9# Allow replication connections from localhost, by a user with scram-sha-256
10# replication privilege.
11local replication all scram-sha-256
12host replication all 127.0.0.1/32 scram-sha-256
13host replication all ::1/128 scram-sha-256
14
15host all all 192.168.0.0/24 scram-sha-256
16host all all 172.0.0.0/8 scram-sha-256
서비스 시작 순서 변경 #
위에서 PostgreSQL이 docker0
의 IP를 LISTEN 하도록 설정했다.
문제는 PostgreSQL 서비스가 Docker 서비스보다 먼저 시작될 수 있다는 것이다. 이 경우 IP가 사용 상태가 아니므로 해당 IP에 bind할 수 없다.
1LOG: could not bind IPv4 address "172.17.0.1": Cannot assign requested address
2WARNING: could not create listen socket for "172.17.0.1"
해결책은 서비스의 drop-in 디렉터리를 만들어 순서에 대한 설정을 추가하는 것이다.
아래 설정은 docker 서비스 시작 이후에 postgresql 서비스가 시작되도록 한다.
1[Unit]
2Wants=docker.service
3After=docker.service
서비스 재시작 #
모든 수정이 끝났다면 systemctl daemon-reload
명령으로 서비스를 다시 불러오고, PostgreSQL 서비스를 재시작해 변경사항을 적용한다.
Docker 컨테이너 설정 #
두 번째 문제는 어느 IP를 통해 컨테이너 내부에서 로컬에 연결할 수 있느냐이다.
localhost
는 컨테이너 내부의 localhost
이므로 사용할 수 없다.
외부로 연결하려면 위에서 언급한 것처럼 docker0
의 IP를 사용해야 한다.
Host 매핑 #
docker run
명령의 경우 --add-host "(host):host-gateway"
파라미터를 사용해 docker0
의 IP를 원하는 host에 매핑해줄 수 있다.
Docker Compose의 경우 아래처럼 설정해 같은 결과를 얻을 수 있다.
1extra_hosts:
2 - "(host):host-gateway"
이후 설정한 host를 통해 포트에 접근할 수 있다. 아래는 host를 host.docker.internal
로 설정해 사용하는 예시이다.
1DATABASE_URL: postgresql://host.docker.internal/service