이 글의 목차

Nginx Proxy Manager에서 502 Bad Gateway가 보이면 프록시가 실제 앱에 연결할 수 있는지 먼저 확인하세요. 브라우저에서 접속한 HTTPS와 프록시가 앱으로 보내는 HTTP는 다른 구간입니다. 인증서를 다시 발급하기 전에 앱 주소·포트·프로토콜과 Docker 네트워크를 대조하는 것이 효율적입니다.

설치 과정은 Nginx Proxy Manager 사용법에 정리되어 있습니다. 여기서는 같은 Docker 호스트에서 NPM과 앱을 운영하는 경우를 중심으로 502 원인을 좁힙니다. 앱 자체나 다른 프록시가 502를 반환하는 경우도 있으므로 응답과 로그를 함께 보세요.

localhost가 자주 원인이 되는 이유

컨테이너 안의 127.0.0.1은 일반적인 bridge 네트워크에서 그 컨테이너 자신입니다. NPM의 Forward Hostname에 localhost를 입력하면 다른 컨테이너의 앱이 아니라 NPM 내부로 연결합니다.

Docker의 사용자 정의 bridge 네트워크에서는 같은 네트워크에 연결된 컨테이너가 이름으로 통신할 수 있습니다. 호스트에 앱 포트를 공개하지 않아도 컨테이너 내부 포트로 접근할 수 있다는 점이 중요합니다. Docker bridge 네트워크 문서

NPM 공식 문서도 공유 Docker 네트워크와 서비스 이름을 사용하는 구성을 소개합니다. NPM 공유 네트워크 안내

최소 구성으로 먼저 연결 확인

다음은 연결을 확인하기 위한 예시입니다. NPM 이미지 버전은 2026년 10월 8일 공식 설치 문서의 예시 태그이며, 앞으로도 최신 버전이라는 뜻은 아닙니다. 운영 서비스 적용 전에는 현재 지원 버전과 업데이트 안내를 확인하세요.

services:
npm:
image: jc21/nginx-proxy-manager:2.16.0
ports:
- "80:80"
- "443:443"
- "127.0.0.1:81:81"
volumes:
- ./npm-data:/data
- ./npm-certificates:/etc/letsencrypt
networks:
- proxy
web:
image: nginx:stable-alpine
networks:
- proxy
networks:
proxy:

web는 내부 80번 포트로 응답하는 예시 앱입니다. NPM 관리 UI는 호스트의 loopback에만 연결했습니다. 원격 관리가 필요하면 해당 호스트에 안전하게 접속한 뒤 SSH 터널 등을 사용하세요. 공식 기본 설치의 포트·데이터 디렉터리 구성은 NPM 설치 문서에서 확인할 수 있습니다.

NPM의 Proxy Host는 다음처럼 입력합니다.

입력란예시 값의미
Domain Names본인이 관리하는 도메인브라우저가 접속할 이름
SchemehttpNPM에서 web으로 보내는 프로토콜
Forward Hostname / IPweb같은 네트워크의 서비스 이름
Forward Port80web 컨테이너 내부 포트

브라우저에 HTTPS를 제공하더라도 내부 앱이 HTTP로 동작하면 Scheme은 HTTP입니다. 반대로 앱이 TLS 포트에서만 응답하면 앱이 사용하는 HTTPS·포트·인증서 조건을 확인해야 합니다.

기존 Compose가 둘로 나뉘어 있으면

각 Compose 프로젝트의 기본 네트워크는 보통 서로 다릅니다. NPM과 앱에 같은 이름의 networks 블록을 썼다는 사실만으로 실제 동일 네트워크가 만들어졌다고 볼 수는 없습니다. 별도 프로젝트라면 공용 외부 네트워크를 만들고 양쪽에서 같은 네트워크를 참조할 수 있습니다.

Terminal window
docker network create home-proxy
# 두 Compose의 실제 연결할 서비스에 networks: [proxy]도 지정
networks:
proxy:
external: true
name: home-proxy

이미 있는 네트워크인지 먼저 확인하세요. 네트워크를 바꾸는 작업은 서비스 재생성 등 연결 중단을 유발할 수 있으므로, 아래 읽기 명령으로 현재 연결부터 확인하는 편이 좋습니다. 서비스 이름 충돌도 피해야 합니다.

502 진단 명령과 결과 해석

Terminal window
docker compose ps
docker compose logs --tail 100 npm
docker compose exec npm curl -v --connect-timeout 5 http://web:80/

핵심은 NPM 컨테이너 안에서 앱을 호출하는 것입니다. 호스트에서 접속이 되더라도 NPM의 네트워크에서는 실패할 수 있습니다. 설치 이미지에 curl이 없으면 진단 도구가 포함된 임시 컨테이너를 같은 네트워크에 연결해 테스트하는 방법을 사용하세요. 운영 이미지를 급히 바꿀 필요는 없습니다.

결과가능한 원인다음 확인
이름 해석 실패네트워크 분리, 이름 오타양쪽 네트워크와 서비스 이름
Connection refused앱 미실행, 다른 포트, loopback 바인딩앱 로그와 실제 리스닝 주소
Timeout경로·방화벽·앱 지연네트워크 상태와 앱 처리 시간
TLS 관련 오류Scheme·포트·인증서 불일치내부 앱의 실제 HTTPS 설정
200·401·403 응답네트워크는 도달NPM 설정과 앱의 인증·호스트 제한

NPM이 기록하는 사이트별 로그는 배포 구성의 /data/logs 등도 확인해야 할 수 있습니다. 로그 파일명은 사이트 ID와 버전에 따라 달라질 수 있으니 실제 디렉터리를 확인하세요. 공개 글에 로그를 공유할 때는 토큰·쿠키·개인 주소를 제거하세요.

호스트 포트와 내부 포트 혼동

앱에 8080:3000이 설정되어 있으면 호스트의 8080이 컨테이너의 3000으로 전달됩니다. 같은 Docker 네트워크에서 서비스 이름으로 연결할 때는 app:3000을 사용합니다. app:8080은 앱이 내부 8080에서도 따로 리스닝하지 않는 한 실패합니다.

웹 앱이 컨테이너 내부 127.0.0.1:3000에만 바인딩한 경우도 다른 컨테이너가 접근할 수 없습니다. 의도한 컨테이너 네트워크에서 응답하도록 바인딩을 설정해야 합니다. 이와 별개로 호스트 포트를 인터넷에 공개할 필요가 있는지는 따로 판단하세요.

자주 묻는 질문

SSL 인증서를 다시 받으면 502가 고쳐지나요?

프록시에서 앱으로 연결하는 구간의 주소·포트 문제라면 인증서 재발급으로 해결되지 않습니다. NPM 내부에서 upstream 호출이 되는지 먼저 확인하세요.

호스트에서는 curl이 성공하는데 왜 NPM은 실패하나요?

호스트와 NPM 컨테이너는 네트워크 관점이 다릅니다. 컨테이너 안에서의 DNS 이름, 공유 네트워크, 내부 포트와 앱 바인딩을 확인하세요.

WebSocket Support를 켜면 모든 502가 해결되나요?

아닙니다. WebSocket이 필요한 앱의 연결 설정과 기본 HTTP 연결 실패는 구별해야 합니다. 일반 HTTP 응답부터 확인한 뒤 앱의 공식 프록시 요구사항을 적용하세요.

참고 자료

2026년 10월 8일 문서 확인. 예시는 단일 호스트 bridge 환경이며 host networking 등 다른 환경에는 그대로 적용되지 않을 수 있습니다.

← 전체 글로 돌아가기