베어_
TechBear
베어_
전체 방문자
오늘
어제
  • 분류 전체보기 (336)
    • Spring (33)
      • 개념 (13)
      • Security (5)
      • 실습 (1)
      • 토비 스프링 (11)
    • JPA (6)
    • 프로젝트 기록 (24)
    • DB (13)
    • JAVA (18)
    • 알고리즘 (50)
      • 유형정리 (8)
      • Baekjoon (21)
      • LeetCode (18)
    • 디자인패턴 (0)
    • 개발서적 (79)
      • Effective Java (78)
      • 객체지향의 사실과 오해 (1)
    • 독후감 (4)
    • 보안 (2)
    • 운영체제(OS) (53)
      • 공룡책 (53)
    • 컴퓨터 네트워크 (28)
      • 컴퓨터 네트워크 하향식 접근 (23)
    • 자료구조 (1)
    • DevOps (2)
    • 앱 개발 (20)
      • 안드로이드 스튜디오 (20)

블로그 메뉴

    공지사항

    인기 글

    태그

    • 스프링시큐리티
    • 자바8
    • BFS
    • 스프링
    • 백준
    • jpa
    • 데이터베이스
    • 알고리즘
    • 자바
    • 함수형인터페이스
    • leetcode
    • 스레드
    • dfs
    • 코드업
    • Spring
    • C++
    • 운영체제
    • 이펙티브자바
    • java
    • 토비스프링

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    베어_

    TechBear

    Docker Compose를 이용한 Vue 프로젝트 실행
    프로젝트 기록

    Docker Compose를 이용한 Vue 프로젝트 실행

    2023. 7. 25. 04:43

    이전에는 voca 프로젝트의 backend 스프링 프로젝트와 DB를 컨테이너로 올리는 작업을 진행하였다. 현재 운영 서버는 Nginx를 이용하고 있어 이를 맞추고자 한다.

    🔍 vue 빌드하기

    웹브라우저는 HTML, CSS, JS 이 세개의 언어만 해석할 수 있기 때문에 모든 사람이 이용하게 하려면 App.vue파일을 그대로 올리는 것이 아닌 build를 해야 한다.
    Vue 프로젝트는 npm run build 명령어를 통해 간단하게 빌드할 수 있다. 빌드가 성공하면 dist라는 폴더가 생기는데 이 폴더를 그대로 서버에 올리면 된다.

    이를 도커 파일로 작성해보자.

    1. dockerfile을 프론트 프로젝트 루트에 생성한다.
    FROM node:latest as build-stage
    # 디렉토리 전환 명령어로 이후의 명령어는 모두 /app 경로를 기준으로 동작한다.
    WORKDIR /app
    # package.json이름을 가진 파일을 모두 workdir폴더로 복사한다.
    COPY package*.json ./
    
    RUN npm install
    
    # 현재 폴더를 workdir폴더에 복사한다.
    COPY ./ .     
    # 빌드하기 !
    
    RUN npm run build
    1. 웹 서버에 배포하기
      • Nginx를 이용하여 웹 서버에 배포하였다. 프론트 dockerfile에 같이 작성하였다.
    FROM nginx as production-stage
    RUN mkdir /app
    
    # build-stage에서 생성한 /app/dist의 모든 파일을 /app으로 이동시킨다.
    COPY --from=build-stage /app/dist /app
    
    # nginx.conf파일을 도커의 nginx 설정파일로 복사한다. 
    COPY /nginx/nginx.conf /etc/nginx/nginx.conf
    1. nginx.conf파일 작성하기
      필요한 부분만 발췌하였다. 일단 '/' 경로로 들어오면 웹 서버에 있는 정적 index.html파일을 사용할 수 있도록 하였다. 만약 '/api'로 들어오면 백엔드 서버가 사용될 수 있도록 리버스 프록시를 적용하였다.
    ...
    ...
    http {
      server {
        listen       80;
        server_name  localhost;
        location / {
          root   /app;
          index  index.html;
          try_files $uri $uri/ /index.html;
        }
    
        location /api {
            # 리버스 프록시
            # 도커 컴포즈의 같은 네트워크 상에 있다면 컨테이너 이름으로 컨테이너간 통신이 가능하다. 
            proxy_pass http://voca-backend:8088;
    
            # cors 에러 방지용
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
        }
      }
    }

     

    🔍 도커 컴포즈 작성

    voca-front의 경로를 지정해서 Dockerfile을 찾을 수 있게 지정해주었으며, 포트는 80번 포트로 지정하였다. 백엔드 서버가 동작해야 유의미한 작업이 가능하므로 백엔드 서버 실행 이후 웹 서버 컨테이너가 동작하도록 지정해주었다.

    
    voca-front:  
    container_name: voca-front  
    
    # 빌드 할 경로와 Dockerfile 이름을 지정하였다.  
    build:  
       context: ../voca-front  
       dockerfile: Dockerfile  
    ports:  
       - 80:80  
    restart: always  
    
    # voca-backend 컨테이너 생성 이후에 이 컨테이너가 올라간다.  
    depends_on:  
       - voca-backend  
    networks:  
       - voca

     

    🔍 트러블 슈팅

    프론트 서버에서 백엔드 서버로 API 요청을 할 때마다 다음과 같은 로그가 발생하였다.

    에러 로그

    기본적으로 스프링에서 cors를 해결하는 가장 쉬운 방법은 허용할 url을 맵핑해주는 것이다.

    백엔드 코드

    cors는 프로토콜, 호스트, 포트번호까지 일치해야 같은 출처로 본다. 이를 맞춰서 스프링에 추가를 해줬음에도 불구하고 에러가 해결되지 않았다.

     

    ✏️ 시도 

    1. 에러의 원인을 파악하기 위해 모든 cors를 모두 오픈한 뒤에 테스트 해보았지만 해결할 수 없었다.
    2. 도커 컨테이너간의 다른 ip주소를 사용하기 때문에 같은 localhost를 못 받는건가해서 docker container의 IP주소를 그대로 넣어보았지만 해결할 수 없었다.
    3. 헤더에 클라이언트의 ip정보를 추가함으로써 해결하였다.
      Nginx는 기본적으로 요청을 전송할 때 두 가지 헤더 정보 (Host, Connection)을 재정의한다. 기본 셋팅은 Host=$proxy_host, Connection=close이다.
    4. 즉, 프록시 서버가 요청을 백엔드 서버로 전송하려면 헤더를 추가해주어야 한다.

    좀 더 자세히 설명하면, 프록시 서버는 전용 프로토콜로 요청을 보낸후에 받은 결과를 가공하여 클라이언트에 재전송하게 된다. 이로 인해 처리한 웹 서버에서 request.getRemoteAddr()등으로 로그를 찍어보면 proxy ip를 얻게된다.

     

    ✏️ 해결

    1. X-Real-IP를 설정한다.
    2. proxy_set_header X-Real-IP $remote_addr;
    3. X-Forwarded-For를 설정한다.
      • X-Forwarded-For: 이전 프록시 서버가 또 있다면 그 IP 정보를 가지고 있다.
      • proxy_add_x_forwarded_for: 요청 헤더와 그 뒤에 따라오는 클라이언트의 원격 주스를 포함한 호스트명을 의미한다.
      • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    4. http요청의 호스트 이름 지정
      • $http_host : HTTP Request의 호스트 헤더값
      • proxy_set_header Host $http_host
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

     

    저작자표시 비영리 변경금지 (새창열림)
      '프로젝트 기록' 카테고리의 다른 글
      • 서로 다른 타임존에서 데이터 핸들링 하기
      • TimeZone으로 인한 데이터 조회 실패
      • Docker Compose를 이용한 프로젝트 실행
      • 트랜잭션 전파 레벨 정하기
      베어_
      베어_
      Today I learned | 문제를 해결하는 개발자

      티스토리툴바