본문 바로가기
개발 및 기타 등등/Linux

Postgresql, geoserver Docker 컨테이너로 설치 및 외부IP설정

by 클수저 2026. 10. 16.
728x90
반응형

Windows Server에서 Docker로 GeoServer 2.27.x + PostgreSQL 14 설치 및 외부 접속 문제 해결 기록

이 글은 Windows Server 환경에서 Docker 컨테이너로 GeoServer 2.27.x와 PostgreSQL 14를 설치하고,
localhost에서는 접속되지만 서버 IP를 통한 외부 접속이 되지 않는 문제를 하나씩 확인하면서 해결한 과정을 정리한 기록이다.

단순히 “명령어 몇 개 실행해서 해결했다”가 아니라, Docker 이미지와 컨테이너의 차이, 포트 매핑, GeoServer HTTP 접속, PostgreSQL의 listen_addresses / pg_hba.conf / SCRAM 인증, 컨테이너 내부 설정 파일 수정 방식까지 함께 정리한다.


1. 목표

서버 안에 다음 두 서비스를 구축하는 것이 목표였다.

  • GeoServer 2.27.x
  • PostgreSQL 14

두 서비스 모두 Windows Server OS에 직접 설치하는 방식이 아니라 Docker 컨테이너 방식으로 구성했다.

최종적으로 원하는 구조는 다음과 같다.

[외부 PC]
   │
   ├── HTTP :8080 ───────────────┐
   │                             ▼
   │                    [Windows Server]
   │                       192.168.0.XX
   │                             │
   │                             ▼
   │                         [Docker]
   │                             │
   │                   8080 ─────┴─────> GeoServer Container
   │
   └── PostgreSQL :5432 ─────────┐
                                 ▼
                         [Windows Server]
                            192.168.0.XX
                                 │
                                 ▼
                             [Docker]
                                 │
                       5432 ─────┴─────> PostgreSQL 14 Container

핵심은 외부 PC가 Windows Server의 IP와 포트를 통해 Docker 컨테이너 안의 서비스에 접근할 수 있어야 한다는 점이다.


2. GeoServer 설치 시작

GeoServer 공식 Docker 이미지를 pull했다.

docker pull docker.osgeo.org/geoserver:2.27.x

실제 출력은 다음과 같았다.

2.27.x: Pulling from geoserver
...
Digest: sha256:d69df5a7091ef21e944943accd090b1661265cb525f8f0df91d3ba797f3db12d
Status: Downloaded newer image for docker.osgeo.org/geoserver:2.27.x
docker.osgeo.org/geoserver:2.27.x

그리고 이미지가 정상적으로 내려왔는지 확인했다.

docker images

결과:

IMAGE                               ID             DISK USAGE   CONTENT SIZE
docker.osgeo.org/geoserver:2.27.x   d69df5a7091e   1.48GB       588MB
doctorkirk/oracle-19c:latest        5816fe124f2a   16.8GB       5.19GB

여기서 처음에 헷갈렸던 부분이 있다.

docker pull은 설치 완료가 아니다

docker pull은 Docker Image를 내려받는 작업이다.

Docker에서는 대략 다음 관계로 이해하면 된다.

docker pull
   ↓
Image 다운로드
   ↓
docker run
   ↓
Container 생성 + 실행
   ↓
docker exec
   ↓
실행 중인 Container 내부에서 명령 실행

즉,

docker pull docker.osgeo.org/geoserver:2.27.x

까지만 실행한 상태에서 바로:

docker exec geoserver java -version

을 실행하면 컨테이너가 없기 때문에 실패한다.

실제로 처음에는 다음 오류가 발생했다.

Error response from daemon: No such container: geoserver

원인은 단순했다.

geoserver라는 Docker Image는 존재하지만, geoserver라는 이름의 Container는 아직 존재하지 않았기 때문이다.


3. GeoServer 컨테이너 실행

GeoServer 컨테이너를 실행할 때는 다음과 같은 형태를 사용한다.

docker run -d --name geoserver -p 8080:8080 docker.osgeo.org/geoserver:2.27.x

각 옵션은 다음 뜻이다.

docker run
→ Image로부터 새로운 Container를 생성하고 실행

-d
→ 백그라운드 실행

--name geoserver
→ 컨테이너 이름을 geoserver로 지정

-p 8080:8080
→ Windows Server의 8080 포트와
   Container 내부의 8080 포트를 연결

docker.osgeo.org/geoserver:2.27.x
→ 사용할 Docker Image

이후:

docker ps

를 실행했더니 다음과 같이 확인되었다.

CONTAINER ID   IMAGE                               COMMAND
50eb63081810   docker.osgeo.org/geoserver:2.27.x   "bash /opt/startup.sh"

STATUS
Up 6 seconds (health: starting)

PORTS
0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp

여기서 중요한 부분은:

0.0.0.0:8080->8080/tcp

이다.

이것은 Windows Server의 모든 IPv4 인터페이스에서 들어오는 TCP 8080 요청을 Docker 컨테이너의 8080 포트로 전달하도록 publish했다는 의미다.


4. 같은 이름으로 다시 docker run 해서 발생한 오류

컨테이너가 이미 생성된 상태에서 다시:

docker run -d --name geoserver -p 8080:8080 docker.osgeo.org/geoserver:2.27.x

를 실행했더니 다음 오류가 발생했다.

docker: Error response from daemon:
Conflict. The container name "/geoserver" is already in use by container
"50eb63081810307bc9f5baa366b88125ab01b1add4e0321fd03f194d60XX6208".
You have to remove (or rename) that container to be able to reuse that name.

이 오류는 GeoServer 자체 오류가 아니다.

이미 다음 컨테이너가 존재했기 때문이다.

컨테이너 이름: geoserver
Container ID: 50eb63081810...

Docker 컨테이너 이름은 같은 Docker 환경에서 중복될 수 없다.

즉, 이미 실행 중이라면 다시 docker run 할 필요가 없다.

상태 확인은:

docker ps

로그 확인은:

docker logs geoserver

로 하면 된다.


5. GeoServer 로그 확인

다음 명령으로 GeoServer 기동 로그를 확인했다.

docker logs geoserver

중요한 로그는 다음과 같았다.

Welcome to GeoServer 2.27-SNAPSHOT

OS Name:               Linux
OS Version:            6.6.87.2-microsoft-standard-WSL2
Architecture:          amd64

Java Home:             /opt/java/openjdk
JVM Version:           17.0.20.1+1
JVM Vendor:            Eclipse Adoptium

CATALINA_BASE:         /usr/local/tomcat
CATALINA_HOME:         /usr/local/tomcat

그리고:

Initializing ProtocolHandler ["http-nio-8080"]
Starting service [Catalina]

가 확인되었다.

이 로그를 통해 알 수 있는 것은 다음과 같다.

Windows Server
   ↓
Docker / WSL2
   ↓
Linux Container
   ↓
Java 17
   ↓
Tomcat
   ↓
GeoServer

즉 GeoServer는 Windows OS에 직접 설치된 것이 아니라, Linux 기반 Docker 컨테이너 내부에서 Java + Tomcat 위에 실행되고 있었다.


6. 컨테이너 내부 Java 버전 확인

GeoServer 컨테이너가 정상 실행된 후에는 다음 명령이 정상적으로 동작했다.

docker exec geoserver java -version

결과:

openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment Temurin-17.0.20.1+1
OpenJDK 64-Bit Server VM Temurin-17.0.20.1+1

여기에서 docker exec의 역할도 명확해졌다.

docker exec <컨테이너 이름> <실행할 명령>

예:

docker exec geoserver java -version

는 다음 의미다.

실행 중인 geoserver 컨테이너 내부에서
java -version 명령을 실행한다.

7. GeoServer는 localhost로 되는데 서버 IP로 안 되는 것처럼 보였던 문제

처음에는 브라우저에서:

http://localhost:8080/geoserver

는 접속되는데 서버 IP를 통한 접속이 안 되는 것처럼 보였다.

그래서 포트 상태를 확인했다.

netstat -ano | findstr :8080

결과:

TCP    0.0.0.0:8080           0.0.0.0:0              LISTENING       1960
TCP    127.0.0.1:57375        127.0.0.1:8080         TIME_WAIT       0
TCP    192.168.0.XX:57376     192.168.0.100:8080     TIME_WAIT       0
TCP    [::]:8080              [::]:0                 LISTENING       1960
...

여기서 핵심은:

0.0.0.0:8080 LISTENING

이었다.

이는 8080이 단순히 localhost에만 바인딩된 것이 아니라 Windows 서버의 IPv4 인터페이스 전체에서 LISTEN 중이라는 의미다.

따라서 Docker의 -p 8080:8080 설정 자체는 정상이었다.


8. 서버 IP 확인 과정

처음에는 192.168.0.100을 대상으로 테스트했는데, netstat에서:

192.168.0.XX:57376 → 192.168.0.100:8080

라는 연결 흔적이 보였다.

즉 명령을 실행 중인 서버의 실제 주소가 192.168.0.XX일 가능성이 높았다.

이후 실제 접속 테스트를:

curl -v http://192.168.0.XX:8080/geoserver

로 진행했다.


9. curl -v로 GeoServer HTTP 응답 확인

localhost부터 확인했다.

curl -v http://localhost:8080/geoserver

결과:

* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)

> GET /geoserver HTTP/1.1
> Host: localhost:8080

< HTTP/1.1 302
< Location: /geoserver/index.html
< Content-Length: 0

서버 IP로도 테스트했다.

curl -v http://192.168.0.XX:8080/geoserver

결과:

* Trying 192.168.0.XX:8080...
* Connected to 192.168.0.XX (192.168.0.XX) port 8080 (#0)

> GET /geoserver HTTP/1.1
> Host: 192.168.0.XX:8080

< HTTP/1.1 302
< Location: /geoserver/index.html
< Content-Length: 0

여기서 처음에는 302라서 오류인가 생각할 수 있지만, HTTP 302는 실패가 아니다.

HTTP 302
Location: /geoserver/index.html

은 다음 의미다.

/geoserver
    ↓
GeoServer가 브라우저에게
/geoserver/index.html 로 이동하라고 응답

즉 정상적인 Redirect이다.

실제 접속 주소는 다음과 같이 사용할 수 있다.

http://192.168.0.XX:8080/geoserver

또는:

http://192.168.0.XX:8080/geoserver/index.html

10. GeoServer 외부 접속 문제에서 배운 점

GeoServer 쪽에서는 내부 conf 파일에 Windows 서버 IP를 직접 넣을 필요가 없었다.

이미:

0.0.0.0:8080->8080/tcp

로 Docker Port Publish가 되어 있었고,

curl -v http://192.168.0.XX:8080/geoserver

에서 실제 HTTP 응답까지 확인되었기 때문이다.

즉 구조는 다음과 같다.

192.168.0.XX:8080
       │
       ▼
Windows Server
       │
       ▼
Docker Port Publish
8080 → 8080
       │
       ▼
GeoServer Container
       │
       ▼
Tomcat / GeoServer

11. PostgreSQL 14 컨테이너 확인

PostgreSQL 14 역시 Docker 컨테이너로 설치했다.

docker ps 결과:

CONTAINER ID   IMAGE         COMMAND                  STATUS
7c1fbe85fXXc   postgres:14   "docker-entrypoint.s…"  Up 13 minutes

PORTS
0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp

NAMES
postgres14

중요한 부분은 두 가지다.

IMAGE: postgres:14
NAME : postgres14

여기서 Image 이름과 Container 이름은 서로 다른 개념이다.

postgres:14
→ Docker Image 이름 + 태그

postgres14
→ 현재 실행 중인 Container 이름

12. 잘못된 컨테이너 이름으로 docker exec 실행

처음에는 다음과 같이 실행했다.

docker exec -it postgres psql -U postgres:14

그러자:

Error response from daemon: No such container: postgres

오류가 발생했다.

원인은 실제 컨테이너 이름이:

postgres14

였기 때문이다.

docker ps의 가장 오른쪽 NAMES 컬럼을 확인하는 것이 중요하다.


13. 또 다른 실수: psql을 빼고 -U부터 사용

다음에는:

docker exec -it postgres14 -U postgres

를 실행했다.

오류:

OCI runtime exec failed:
exec failed:
unable to start container process:
exec: "-U": executable file not found in $PATH

왜 이런 오류가 발생했을까?

docker exec 기본 문법은:

docker exec [옵션] 컨테이너명 실행파일 [인자]

이다.

그런데:

docker exec -it postgres14 -U postgres

라고 입력하면 Docker는:

postgres14 컨테이너 안에서
"-U"라는 프로그램을 실행하라

라고 해석한다.

당연히 -U라는 실행파일은 없기 때문에 오류가 난다.

정확한 명령은:

docker exec -it postgres14 psql -U postgres

이다.

구조는:

docker exec -it
→ 컨테이너에서 대화형 명령 실행

postgres14
→ 컨테이너 이름

psql
→ PostgreSQL CLI 프로그램

-U postgres
→ postgres 사용자로 접속

14. PostgreSQL 네트워크 설정 확인

psql에 접속한 뒤 다음 항목을 확인했다.

SHOW listen_addresses;
SHOW port;
SHOW config_file;
SHOW hba_file;

실제 결과:

postgres=# SHOW listen_addresses;

 listen_addresses
------------------
 *
(1 row)
postgres=# SHOW port;

 port
------
 5432
(1 row)
postgres=# SHOW config_file;

               config_file
------------------------------------------
 /var/lib/postgresql/data/postgresql.conf
(1 row)
postgres=# SHOW hba_file;

               hba_file
--------------------------------------
 /var/lib/postgresql/data/pg_hba.conf
(1 row)

15. listen_addresses = '*'의 의미

가장 중요한 것은:

listen_addresses = *

였다.

이 값은 PostgreSQL이 특정 localhost 주소에만 묶여 있는 것이 아니라 사용 가능한 모든 네트워크 인터페이스에서 연결을 받을 수 있도록 listen한다는 뜻이다.

즉 postgresql.conf에서 별도로:

listen_addresses = '192.168.0.XX'

같은 서버 IP를 넣을 필요가 없었다.

현재 상태:

Docker
0.0.0.0:5432 -> 5432
         ✅

PostgreSQL
listen_addresses = '*'
         ✅

PostgreSQL
port = 5432
         ✅

따라서 다음 확인 대상은 pg_hba.conf였다.


16. pg_hba.conf란?

postgresql.conf가 PostgreSQL 자체의 서버 동작 방식을 설정한다면, pg_hba.conf는 클라이언트 인증 규칙을 관리한다.

쉽게 말하면:

postgresql.conf
→ "PostgreSQL이 어느 주소/포트에서 기다릴 것인가?"

pg_hba.conf
→ "어느 IP의 사용자가 어떤 방식으로 접속해도 되는가?"

관계를 그림으로 보면 다음과 같다.

외부 PC
   │
   ▼
192.168.0.XX:5432
   │
   ▼
Docker -p 5432:5432
   │
   ▼
PostgreSQL
   │
   ├── postgresql.conf
   │      └── listen_addresses = '*'
   │
   └── pg_hba.conf
          └── 어떤 IP를 어떤 인증 방식으로 허용할지 결정

17. pg_hba.conf 경로 오타

설정 파일을 확인하기 위해 처음 다음 명령을 실행했다.

docker exec postgres14 cat /var/lib/postrgresql/data/pg_hba.conf

결과:

cat: /var/lib/postrgresql/data/pg_hba.conf: No such file or directory

원인은 단순 오타였다.

잘못된 경로:

/var/lib/postrgresql/

정확한 경로:

/var/lib/postgresql/

따라서 정확한 명령은:

docker exec postgres14 cat /var/lib/postgresql/data/pg_hba.conf

이다.


18. 실제 pg_hba.conf 내용 확인

확인 결과 주요 규칙은 다음과 같았다.

# TYPE  DATABASE        USER            ADDRESS                 METHOD

local   all             all                                     trust

host    all             all             127.0.0.1/32            trust

host    all             all             ::1/128                 trust

local   replication     all                                     trust

host    replication     all             127.0.0.1/32            trust

host    replication     all             ::1/128                 trust

즉 명시적으로 보이는 TCP 허용 주소는:

127.0.0.1/32
::1/128

뿐이었다.

이는 각각:

127.0.0.1
→ IPv4 localhost

::1
→ IPv6 localhost

이다.

따라서 사설망 192.168.0.x에서 들어오는 외부 접속에 맞는 host 규칙을 추가할 필요가 있었다.


19. 외부 접속 허용 규칙 추가

사설망이 192.168.0.0/24인 환경을 대상으로 다음과 같은 규칙을 추가했다.

host    all    all    192.168.0.0/24    scram-sha-256

각 필드의 의미:

host
→ TCP/IP 연결

all
→ 모든 데이터베이스

all
→ 모든 PostgreSQL 사용자

192.168.0.0/24
→ 192.168.0.x 대역

scram-sha-256
→ 비밀번호 기반 SCRAM-SHA-256 인증

/24는 일반적으로 다음 주소 범위를 의미한다.

192.168.0.0 ~ 192.168.0.255

실제로 특정 PC 한 대만 허용하고 싶다면 예를 들어:

host    all    all    192.168.0.50/32    scram-sha-256

처럼 /32를 사용하는 편이 더 제한적이다.


20. 왜 0.0.0.0/0 trust를 사용하지 않았나?

인터넷 예제 중에는 다음과 같은 설정도 많이 보인다.

host    all    all    0.0.0.0/0    trust

하지만 이 설정은 매우 넓은 범위의 접속을 허용하고, trust 방식은 비밀번호 인증 없이 접속을 허용할 수 있어 보안상 부적절할 수 있다.

따라서 사설망 기준으로:

192.168.0.0/24

로 범위를 제한하고,

scram-sha-256

으로 인증하도록 설정했다.


21. Docker 컨테이너 내부 설정 파일을 Windows로 복사

Docker 컨테이너 내부 파일을 직접 수정하는 대신, 파일을 Windows 서버로 꺼냈다.

docker cp postgres14:/var/lib/postgresql/data/pg_hba.conf C:\Users\Administrator\pg_hba.conf

결과:

Successfully copied 6.66kB to C:\Users\Administrator\pg_hba.conf

이제 Windows에서:

C:\Users\Administrator\pg_hba.conf

파일을 편집할 수 있다.

수정 후 다시 컨테이너로 복사했다.

docker cp C:\Users\Administrator\pg_hba.conf postgres14:/var/lib/postgresql/data/pg_hba.conf

결과:

Successfully copied 6.66kB to postgres14:/var/lib/postgresql/data/pg_hba.conf

22. PostgreSQL 설정 Reload

pg_hba.conf는 수정했다고 바로 끝나는 것이 아니다.

PostgreSQL이 변경된 설정을 다시 읽도록 해야 한다.

다음 명령을 실행했다.

docker exec postgres14 psql -U postgres -c "SELECT pg_reload_conf();"

결과:

 pg_reload_conf
----------------
 t
(1 row)

t는 true라는 의미다.

즉 PostgreSQL이 configuration reload 요청을 정상적으로 처리했다.


23. 외부 DB 클라이언트 접속 시 SCRAM 오류 발생

여기까지 설정한 뒤 외부 DB 클라이언트에서 PostgreSQL에 접속을 시도했다.

그러자 다음 오류가 발생했다.

서버가 SCRAM 기반 인증을 요청했지만,
비밀번호가 제공되지 않았습니다.

처음 보면 연결 실패처럼 보이지만 사실 이 메시지는 매우 중요한 힌트였다.

이 시점에는 이미:

외부 PC
   ↓
192.168.0.XX:5432
   ↓
Windows Server
   ↓
Docker Port Mapping
   ↓
PostgreSQL

까지 연결이 도달했다는 뜻이다.

즉 네트워크나 Docker port mapping 문제가 아니라 인증 단계까지 진입한 것이다.


24. 왜 SCRAM 비밀번호가 필요해졌나?

pg_hba.conf에 다음 규칙을 넣었다.

host    all    all    192.168.0.0/24    scram-sha-256

따라서 외부 PC에서 접속하면 PostgreSQL이:

이 사용자는 SCRAM-SHA-256 방식으로 비밀번호를 제공해야 한다.

라고 요구한다.

그런데 postgres 사용자에 사용할 비밀번호가 클라이언트에 입력되지 않았거나 적절히 설정되지 않은 상태였다.


25. postgres 사용자 비밀번호 설정

이미 만들어진 PostgreSQL 컨테이너이므로 컨테이너를 다시 만들 필요 없이 SQL로 비밀번호를 설정했다.

먼저:

docker exec -it postgres14 psql -U postgres

접속 후:

ALTER USER postgres WITH PASSWORD '사용할비밀번호';

예:

ALTER USER postgres WITH PASSWORD 'ExampleStrongPassword!';

실제 운영 환경에서는 예제 비밀번호를 그대로 사용하지 말고 충분히 강한 비밀번호를 사용해야 한다.

성공하면:

ALTER ROLE

이 출력된다.

이후 DB 클라이언트에 다음 정보를 입력했다.

Host     : 192.168.0.XX
Port     : 5432
Database : postgres
User     : postgres
Password : 설정한 비밀번호

그리고 최종적으로 PostgreSQL 외부 접속에 성공했다.


26. 최종 결과

최종적으로 두 서비스 모두 정상 접속되었다.

GeoServer

http://192.168.0.XX:8080/geoserver

정상 접속 성공.

PostgreSQL 14

Host : 192.168.0.XX
Port : 5432

DB 클라이언트에서 정상 접속 성공.

최종 구조는 다음과 같다.

                         ┌──────────────────────────────┐
                         │        외부 Client PC        │
                         └──────────────┬───────────────┘
                                        │
                    ┌───────────────────┴───────────────────┐
                    │                                       │
                    │ HTTP                                  │ PostgreSQL Protocol
                    │ TCP 8080                              │ TCP 5432
                    ▼                                       ▼
          ┌─────────────────────┐                 ┌─────────────────────┐
          │  192.168.0.XX:8080  │                 │  192.168.0.XX:5432  │
          └──────────┬──────────┘                 └──────────┬──────────┘
                     │                                       │
                     └──────────────────┬────────────────────┘
                                        ▼
                              ┌──────────────────┐
                              │  Windows Server  │
                              │  Docker Runtime  │
                              └────────┬─────────┘
                                       │
                   ┌───────────────────┴───────────────────┐
                   │                                       │
                   ▼                                       ▼
       ┌────────────────────────┐              ┌────────────────────────┐
       │   GeoServer Container  │              │ PostgreSQL 14 Container│
       │                        │              │                        │
       │ Java 17                │              │ listen_addresses = '*' │
       │ Tomcat                 │              │ port = 5432             │
       │ GeoServer 2.27.x       │              │ pg_hba.conf             │
       │ Container Port 8080    │              │ SCRAM-SHA-256           │
       └────────────────────────┘              └────────────────────────┘

27. 전체 트러블슈팅 흐름

이번 문제를 해결한 흐름을 다시 정리하면 다음과 같다.

[GeoServer Image Pull]
        │
        ▼
docker exec 실패
"No such container"
        │
        ▼
Image와 Container가 다른 개념임을 확인
        │
        ▼
Container 생성/실행
        │
        ▼
docker ps에서 0.0.0.0:8080->8080 확인
        │
        ▼
docker logs 확인
        │
        ▼
Java / Tomcat / GeoServer 정상 기동 확인
        │
        ▼
localhost는 되지만 IP 접속 의심
        │
        ▼
netstat 확인
0.0.0.0:8080 LISTENING
        │
        ▼
curl -v 테스트
        │
        ▼
localhost 302 정상
192.168.0.XX 302 정상
        │
        ▼
GeoServer 정상

PostgreSQL 쪽:

[PostgreSQL 14 Container 실행]
        │
        ▼
docker exec에 잘못된 Container 이름 사용
        │
        ▼
docker ps 확인
실제 이름 = postgres14
        │
        ▼
docker exec -it postgres14 -U postgres
        │
        ▼
"-U executable not found" 오류
        │
        ▼
psql 명령이 빠졌음을 확인
        │
        ▼
docker exec -it postgres14 psql -U postgres
        │
        ▼
SHOW listen_addresses;
        │
        ▼
'*' 확인
        │
        ▼
SHOW port;
5432 확인
        │
        ▼
SHOW hba_file;
        │
        ▼
pg_hba.conf 확인
        │
        ▼
localhost 규칙만 존재
        │
        ▼
192.168.0.0/24 + scram-sha-256 추가
        │
        ▼
docker cp로 파일 반영
        │
        ▼
SELECT pg_reload_conf();
        │
        ▼
t 반환
        │
        ▼
외부 클라이언트 연결
        │
        ▼
SCRAM password 오류
        │
        ▼
ALTER USER postgres WITH PASSWORD ...
        │
        ▼
DB Client에 비밀번호 입력
        │
        ▼
접속 성공

28. 이번 작업에서 가장 많이 헷갈렸던 개념

28.1 Docker Image와 Container

Image
→ 프로그램 실행 환경을 담은 템플릿

Container
→ Image를 실제 실행한 인스턴스

비유하면:

Image     = 설치용 원본 / 설계도
Container = 실제 실행 중인 프로그램

따라서:

docker pull

만 했다고 서비스가 실행된 것이 아니다.


28.2 docker run과 docker exec

docker run

은 새로운 컨테이너를 만든다.

docker exec

은 이미 실행 중인 컨테이너 내부에서 명령을 실행한다.

즉:

docker run
→ Container 생성

docker exec
→ Container 내부 작업

28.3 0.0.0.0:PORT->PORT

예:

0.0.0.0:5432->5432/tcp

는 Docker가 Windows Server의 모든 IPv4 인터페이스에서 들어오는 5432 요청을 컨테이너의 5432로 전달하도록 publish했다는 뜻이다.

GeoServer:

0.0.0.0:8080 -> Container:8080

PostgreSQL:

0.0.0.0:5432 -> Container:5432

28.4 PostgreSQL 5432는 웹 포트가 아니다

GeoServer 8080은 HTTP 서비스이므로:

http://192.168.0.XX:8080/geoserver

처럼 브라우저에서 접속할 수 있다.

하지만 PostgreSQL 5432는 HTTP가 아니다.

따라서:

http://192.168.0.XX:5432

처럼 브라우저로 접속 여부를 확인하면 안 된다.

PostgreSQL은 다음과 같은 도구를 사용해야 한다.

  • psql
  • DBeaver
  • pgAdmin
  • JDBC
  • 기타 PostgreSQL 클라이언트

단순히 TCP 포트 오픈 여부만 보고 싶다면 Windows PowerShell에서:

Test-NetConnection 192.168.0.XX -Port 5432

를 사용할 수 있다.


29. PostgreSQL 설정 파일 역할 정리

이번에 특히 중요했던 두 파일이다.

postgresql.conf

PostgreSQL 서버 자체 동작 설정.

예:

listen_addresses = '*'
port = 5432

쉽게 말하면:

PostgreSQL이 어디에서 어떤 포트로 요청을 받을 것인가?

를 결정한다.


pg_hba.conf

클라이언트 인증/접근 제어 설정.

예:

host    all    all    192.168.0.0/24    scram-sha-256

쉽게 말하면:

어떤 IP의 사용자가 어떤 인증 방식으로 들어올 수 있는가?

를 결정한다.


30. Windows 직접 설치와 Docker 설치의 차이

인터넷 자료를 보면 Windows PostgreSQL 설치 경로가 다음처럼 나오는 경우가 있다.

C:\Program Files\PostgreSQL\14\data\postgresql.conf
C:\Program Files\PostgreSQL\14\data\pg_hba.conf

이것은 PostgreSQL을 Windows OS에 직접 설치한 경우이다.

이번 환경은 PostgreSQL을 Docker로 실행했기 때문에 실제 파일은 컨테이너 내부에 있었다.

/var/lib/postgresql/data/postgresql.conf
/var/lib/postgresql/data/pg_hba.conf

즉:

Windows Native 설치
→ Windows 파일 시스템의 conf 수정

Docker 설치
→ Container 내부의 PostgreSQL 설정을 수정

이라는 차이가 있다.


31. 컨테이너 내부 파일 직접 수정 시 주의점

이번에는 docker cp로 설정 파일을 수정하여 문제를 해결했다.

하지만 운영 환경에서는 한 가지 주의해야 한다.

Docker 컨테이너는 삭제하고 다시 만들 수 있는 존재이기 때문에, 컨테이너 내부에서만 변경한 파일은 컨테이너 재생성 시 사라질 수 있다.

따라서 장기 운영 시에는 보통 PostgreSQL의 데이터와 설정을 Docker Volume 또는 Bind Mount로 영속화한다.

개념적인 구조:

Windows Server
│
├── PostgreSQL 영속 데이터/설정
│
│      ├── postgresql.conf
│      ├── pg_hba.conf
│      └── DB Data
│
└── Docker Container
        │
        └── Volume / Bind Mount

그러면 컨테이너가 교체되어도 데이터와 설정은 호스트나 Docker Volume에 유지할 수 있다.


32. 최종 확인용 명령어 정리

Docker 전체 상태

docker ps

Docker Image 확인

docker images

GeoServer 로그

docker logs geoserver

GeoServer Java 확인

docker exec geoserver java -version

GeoServer HTTP 확인

curl -v http://localhost:8080/geoserver
curl -v http://192.168.0.XX:8080/geoserver

Windows 포트 상태 확인

netstat -ano | findstr :8080
netstat -ano | findstr :5432

PostgreSQL 접속

docker exec -it postgres14 psql -U postgres

PostgreSQL Listen 주소 확인

SHOW listen_addresses;

PostgreSQL Port 확인

SHOW port;

postgresql.conf 위치 확인

SHOW config_file;

pg_hba.conf 위치 확인

SHOW hba_file;

pg_hba.conf 내용 확인

docker exec postgres14 cat /var/lib/postgresql/data/pg_hba.conf

파일을 컨테이너에서 Windows로 복사

docker cp postgres14:/var/lib/postgresql/data/pg_hba.conf C:\Users\Administrator\pg_hba.conf

수정한 파일을 다시 컨테이너로 복사

docker cp C:\Users\Administrator\pg_hba.conf postgres14:/var/lib/postgresql/data/pg_hba.conf

PostgreSQL 설정 Reload

docker exec postgres14 psql -U postgres -c "SELECT pg_reload_conf();"

PostgreSQL 사용자 비밀번호 변경

ALTER USER postgres WITH PASSWORD '사용할비밀번호';

외부 PC에서 TCP 연결 테스트

Test-NetConnection 192.168.0.XX -Port 8080
Test-NetConnection 192.168.0.XX -Port 5432

33. 장애를 볼 때 어떤 순서로 확인하면 좋은가?

이번 경험을 바탕으로 Docker 서비스 외부 접속 장애는 다음 순서로 확인하는 것이 효율적이다.

1. Container가 실행 중인가?
        ↓
   docker ps

2. Host Port가 publish되어 있는가?
        ↓
   0.0.0.0:PORT->PORT 확인

3. 서비스 자체가 Container 내부에서 실행 중인가?
        ↓
   docker logs
   docker exec

4. Windows Server 자체에서 접속 가능한가?
        ↓
   curl / psql / Test-NetConnection

5. 서비스 자체의 Listen 설정은 정상인가?
        ↓
   PostgreSQL: listen_addresses
   GeoServer: Tomcat/HTTP listener

6. 애플리케이션 레벨 접근 제어가 있는가?
        ↓
   PostgreSQL: pg_hba.conf

7. 인증 정보가 정상인가?
        ↓
   PostgreSQL User / Password / SCRAM

8. 다른 PC에서 TCP 연결이 가능한가?
        ↓
   Test-NetConnection

9. 안 된다면 Windows Firewall / 상위 Network ACL 확인

이 순서대로 보면 “일단 conf부터 고쳐보자”와 같은 방식으로 불필요한 변경을 줄일 수 있다.


34. 이번 문제의 핵심 원인 요약

GeoServer와 PostgreSQL에서 문제가 각각 달랐다.

GeoServer

GeoServer는 실제로 서버 IP를 통한 연결 자체가 정상 동작하고 있었다.

curl -v를 통해:

HTTP/1.1 302
Location: /geoserver/index.html

을 확인하면서 정상 Redirect임을 알 수 있었다.

즉 GeoServer 내부 conf 파일에 서버 IP를 따로 넣는 문제가 아니었다.


PostgreSQL

PostgreSQL은:

Docker Port Mapping
→ 정상

listen_addresses
→ *

port
→ 5432

까지 정상 상태였다.

실질적으로 추가 확인/설정이 필요했던 부분은:

pg_hba.conf
→ 외부 사설망 허용

SCRAM Authentication
→ postgres 사용자 비밀번호 설정

이었다.

최종적으로:

외부 IP 허용
+
SCRAM-SHA-256
+
postgres 사용자 Password

구성이 맞춰지면서 외부 DB 접속에 성공했다.


35. 최종적으로 배운 점

이번 작업에서 가장 크게 배운 것은 외부 접속이 안 된다고 바로 애플리케이션 설정 파일부터 수정하면 안 된다는 것이다.

Docker 환경에서는 여러 계층을 거친다.

Client
  ↓
Network
  ↓
Windows Firewall
  ↓
Host Port
  ↓
Docker Port Mapping
  ↓
Container
  ↓
Application Listen 설정
  ↓
Application 접근 제어
  ↓
Authentication

따라서 어느 단계에서 막혔는지를 하나씩 확인해야 한다.

특히 PostgreSQL의 경우:

5432가 열려 있다

와:

PostgreSQL에 로그인할 수 있다

는 전혀 다른 이야기다.

TCP 연결은 성공했어도:

pg_hba.conf
SCRAM
ID/Password

에서 다시 차단될 수 있다.

반대로 SCRAM 인증 오류가 보인다는 것은 네트워크 단계는 이미 통과하고 PostgreSQL 인증 단계까지 도달했다는 단서가 될 수 있다.

이번 작업은 단순히 PostgreSQL과 GeoServer를 설치한 것보다, Docker 환경에서 서비스가 외부에 노출되는 전체 흐름을 이해하는 데 도움이 되었다.


36. 최종 구성 요약

Windows Server
IP: 192.168.0.XX

Docker
├── GeoServer Container
│     Image : docker.osgeo.org/geoserver:2.27.x
│     Port  : 8080:8080
│     Java  : OpenJDK 17
│     접속  : http://192.168.0.XX:8080/geoserver
│
└── PostgreSQL Container
      Image     : postgres:14
      Name      : postgres14
      Port      : 5432:5432
      Listen    : *
      Auth      : SCRAM-SHA-256
      DB Client : 192.168.0.XX:5432

최종적으로 GeoServer와 PostgreSQL 14 모두 Docker 컨테이너 형태로 정상 실행되고, 서버 IP를 통한 외부 접속까지 성공했다.


부록: 이번 과정에서 실제 발생한 오류만 빠르게 보기

1. GeoServer Container 없음

Error response from daemon: No such container: geoserver

원인:

Image만 pull했고 Container가 아직 없거나,
지정한 이름의 Container가 존재하지 않음

2. GeoServer Container 이름 중복

Conflict. The container name "/geoserver" is already in use

원인:

이미 geoserver라는 Container가 실행 중

3. PostgreSQL Container 이름 오류

Error response from daemon: No such container: postgres

원인:

실제 Container 이름은 postgres14

4. psql 명령 누락

exec: "-U": executable file not found in $PATH

잘못된 명령:

docker exec -it postgres14 -U postgres

정상 명령:

docker exec -it postgres14 psql -U postgres

5. pg_hba.conf 경로 오타

cat: /var/lib/postrgresql/data/pg_hba.conf:
No such file or directory

잘못된 경로:

postrgresql

정상 경로:

postgresql

6. SCRAM 비밀번호 오류

서버가 SCRAM 기반 인증을 요청했지만,
비밀번호가 제공되지 않았습니다.

원인:

네트워크 연결은 PostgreSQL까지 도달했지만
SCRAM 인증에 필요한 비밀번호가 없음

해결:

ALTER USER postgres WITH PASSWORD '사용할비밀번호';

이후 DB Client에서 해당 비밀번호를 입력하여 정상 접속했다.

728x90
반응형