오류해결

Docker 컨테이너를 사용하면서 만난 네트워크 불일치 문제(nginx)

indeep 2025. 1. 5. 19:23

오랜만에 사이드 프로젝트를 진행하면서 Docker를 다시 사용했는데 웹서버로 Nginx를 사용하면서 다른 컨테이너로 리버스 프록시를 못하는 문제를 마주하게 되었다.

 

 

 

프로젝트의 통신 흐름은 위 그림처럼 진행이 된다.

 

1. 사용자가 HTTP 요청을 보냄

2. Nginx는 HTTP 요청을 잡아서 스프링부트로 요청을 전달

 

 

 

그러나 위 과정을 진행하면서 생각도 못했던 문제를 마주하게 되었다.

 

 

그 문제는 도커 네트워크 불일치 문제로 인해 Nginx가 받은 HTTP 요청을 스프링부트로 못넘기는 문제였다.

 

 

도커 컨테이너끼리의 통신은 도커 네트워크를 통해 이루어지게 되는데 통신하려는 두 컨테이너가 같은 네트워크를 사용하고 있지 않아서 발생한 문제이다.

 

 

 

나는 컨테이너를 구축할 때 아래의 방법으로 컨테이너를 구축했다.

 

1. Nginx, MySQL은 Docker-compose로 생성

2. SpringBoot는 깃허브액션을 통해 컨테이너 생성

 

 

 

즉 컨테이너를 만들 때 다른 네트워크를 사용하도록 만들었던 것이다.

 

 

 

그러면 저 구성이 무슨 문제가 있길래 요청을 넘기지 못하는 걸까?

 

 

네트워크가 어떻게 묶여있는지 그림으로 표현하면 아래와 같다.

 

 

Docker-compose로 만든 Nginx, MySQL이 하나의 네트워크로 묶여있고, 깃허브 액션으로 배포했던 SpringBoot가 별개의 네트워크로 묶여있다.

 

 

 

이걸 확인해보려면 아래 명령어를 이용해서 도커 네트워크를 확인할 수 있다.

docker network ls

 

 

 

그리고 아래 명령어를 통해서 해당 네트워크에서 사용 중인 컨테이너의 목록을 볼 수 있다

docker network inspect <네트워크 이름>

 

 

(현재는 설정이 완료된 상태라 4개의 컨테이너가 전부 같은 네트워크를 사용하고 있습니다.)

 

 

 

docker-compose에서 아무 설정을 하지 않고 컨테이너를 생성하면 ec2-user_default라는 네트워크를 기본으로 사용하도록 설정되어 있었다.(기본 네트워크는 확인해봐야 합니다. EC2의 OS나 사용자 환경에 따라 달라질 수 있습니다.)

 

 

그러니 내가 할 일은 깃허브액션에서 컨테이너를 생성할 때 네트워크를 지정해 주면 되는 것이다.

# EC2에 배포 진행 
    - name: Deploy to EC2
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ${{ secrets.EC2_USERNAME }}
        key: ${{ secrets.EC2_KEY }}
        script: |
          echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin
          docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/our-password:latest
          docker stop our-password || true
          docker rm our-password || true
          docker run -d \
            --network ec2-user_default \
            -p ${{ secrets.BACKEND_DOCKER_OUT_PORT }}:${{ secrets.BACKEND_DOCKER_IN_PORT }} \
            --name our-password \
            ${{ secrets.DOCKER_HUB_USERNAME }}/our-password:latest

가장 마지막에 docker run을 진행할 때 --network ec2-user_default를 해당 네트워크를 사용하도록 지정해 두었다.

 

 

그리고 다시 배포를 진행하면 해당 컨테이너는 ec2-user_default 네트워크를 사용하게 되는 것이다.

 

 

location /api {
            proxy_pass http://our-password:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

위 코드는  nginx.conf의 설정 부분이다.

 

 

이제 nginx랑 springBoot의 컨테이너 이름인 our-password는 같은 네트워크를 사용하고 있기 때문에 컨테이너 이름이 호스트명으로 사용이 가능하다. 그렇기에 리버스 프록시가 가능하게 된다.

 

반응형