에러메세지 / 문제상황
- docker ps 명령어 결과에서 spring-container가 8080-8081/tcp 식으로 포트 범위를 열고 있는 것이 확인됨.
- nginx를 통한 API 요청 시 502 Bad Gateway 오류 발생.
원인
- Dockerfile과 docker-compose.yml의 포트 설정 불일치.
- Dockerfile에서는 EXPOSE 8081로 되어 있었고,
- docker-compose.yml에서는 expose: 8080, environment: SPRING_CONTAINER_PORT=8080으로 설정되어 있었음.
- Spring Boot 서버는 8080 포트에서 동작했지만, Docker 메타데이터(EXPOSE)에는 8081이 등록되어 있었기 때문에 docker ps 출력에서 8080-8081 포트 범위가 표시되었음.
- nginx는 spring-container의 8080 포트를 proxy_pass 해야 했는데, 포트 정보가 꼬여 502 오류 발생.
시도
시도 1: docker-compose.yml 포트 설정 정비
- docker-compose.yml에서 expose: 8080으로 수정하여 컨테이너 내부 포트를 8080으로 설정함.
- Spring Boot 서버가 8080 포트에서 실행되도록 environment: SPRING_CONTAINER_PORT=8080 설정을 추가함.
- 그러나 docker ps 결과에서 여전히 8080-8081/tcp 식으로 두 포트가 동시에 열려 있는 것으로 표시되는 문제가 발생함.
시도 2: 이미지 캐시 문제를 고려한 강제 리빌드
- Dockerfile 변경사항이 적용되지 않은 캐시 이미지 문제를 의심하여 -no-cache 옵션으로 이미지를 강제 리빌드함.
- Jenkins Execute Shell 스크립트에서 다음 명령어를 사용함.
docker compose build --no-cache spring-container
- 강제 리빌드 후에도 docker ps 출력에서 포트 문제는 여전히 해결되지 않음.
시도 3: docker image inspect를 통한 이미지 메타데이터 확인
- 문제의 정확한 원인을 찾기 위해 docker image inspect spring-project:latest 명령어를 통해 이미지를 분석함.
- 분석 결과, 이미지의 ExposedPorts 항목에 8081/tcp가 남아 있는 것을 확인함.
"ExposedPorts": {
"8081/tcp": {}
}
- 이를 통해 문제는 docker-compose.yml 설정이나 캐시 문제가 아니라 Dockerfile 자체의 EXPOSE 설정 오류임을 파악함.
시도 4: Dockerfile 수정 및 최종 배포
- Dockerfile의 EXPOSE 8081을 EXPOSE 8080으로 수정함.
- docker-compose.yml의 expose: 8080 설정은 그대로 유지함.
- nginx 설정 파일의 proxy_pass 대상 포트도 8080으로 통일함.
- 이후 수정된 Dockerfile을 기반으로 docker compose build --no-cache를 수행하여 이미지를 강제 리빌드함.
- 컨테이너를 재배포 (docker compose up -d)하고, nginx도 reload하여 변경사항을 적용함.
- 최종적으로 docker ps 결과는 8080/tcp로 정상화되었고, API 통신 시 발생했던 502 오류도 모두 해결됨.
해결책
- Dockerfile의 EXPOSE 포트를 실제 서버가 구동하는 포트(8080)와 일치시킴.
- docker-compose.yml에서도 expose: 8080으로 설정하여 내부 네트워크 통신용 포트를 정확히 열어줌.
- nginx 설정 파일에서도 proxy_pass 대상을 spring-container:8080으로 정확히 매칭함.
- ⭐ Spring Boot 애플리케이션이 실제로 8080 포트에서 구동되도록 하기 위해, application.yml에 server.port=${SPRING_CONTAINER_PORT}를 설정함.
- 이는 docker-compose.yml 파일의 environment: 부분(SPRING_CONTAINER_PORT=8080)과 연결되어, 컨테이너 구동 시 Spring 서버 포트를 제어할 수 있도록 구성함.
- 결과적으로 docker-compose와 nginx는 Spring 서버의 실제 구동 포트를 기준으로 포트 매칭만 담당하는 역할을 하게 됨.
회고 및 정리
- Dockerfile의 EXPOSE는 네트워크 자체를 여는 설정은 아니지만, docker inspect와 docker ps 결과에는 표시되기 때문에 주의 필요
- docker-compose.yml의 expose는 Docker 네트워크 내부 통신에만 영향을 주고, ports는 외부(호스트) 노출에만 영향을 준다.
- 실제 포트가 열리려면 Spring Boot 서버의 server.port 설정이 정확해야 하며, 이 설정이 최우선.
- Dockerfile과 docker-compose.yml의 포트 설정이 일치하지 않으면 운영 및 디버깅 과정에서 혼란을 초래할 수 있다
- 향후에는 Dockerfile, docker-compose.yml, nginx 설정의 포트 번호를 반드시 함께 통일해서 관리해야 한다.