Nginx

Docker와 nginx를 이용하여 HTTPS 적용, 무중단 배포까지[1] - HTTPS 적용

PlatinumeOlive 2024. 6. 28. 13:28

 

저는 gcp에서 도커로 Spring, Mysql, Redis를 돌려서 사용중이고, HTTPS 연결을 위해 도메인을 구매하여 gcp자체에 nginx와 certbot을 설치하여 사용중이였습니다.

 

프로젝트에서 날씨 데이터(과거, 현재)를 가져오고, 게시글 추천 알고리즘을 만들기 위해 기존 스프링 서버에 추가로 Flask서버를 만들게 되었습니다. 

 

기존에는 nginx로 443 포트로 들어오는것을 곧바로 8080번 Spring 포트로 포워딩 해주었습니다. 하지만 이제 포트 5000번 Flask 서버에도 연결 해주어야 합니다. 

 

그런 김에 ngnix 또한 도커 컨테이너로 만들어 같이 관리하고, nginx 설정하는 김에 무중단 배포도 함께 구현하도록 하겠습니다.

 

구성 계획

위 그림과 같이 구성하려고 합니다. 선행되어야 하는 준비는 다음과 같습니다.

 

  • docker 설치
  • docker-compose.yml
  • 클라우드 서버 포트 80, 443 열어놓기
  • 도메인 주소 구매 및 연결해두기

도메인을 구매하고, gcp에 dns 설정하는 과정은 생략하도록 하겠습니다. 저는 도메인이 연결되어있다는 가정 하에, 이후 과정을 작성하겠습니다.

 

SSL 인증서 발급받기

HTTPS로 프로젝트를 배포하기 위해서는, Nginx에 SSL 인증서를 적용하면 됩니다.

 

SSL은 웹사이트와 브라우저 사이(또는 두 서버 사이)에 전송되는 데이터를 암호화하여 인터넷 연결을 보호하기 위한 표준 기술입니다 이 기술은 해커가 개인 데이터나 금융 데이터 등의 전송되는 정보를 보거나 훔치는 것을 방지합니다.

 

먼저, SSL 인증서를 발급받아 보겠습니다. 유료로 인증서를 발급받기도 하지만, 저는 실제 운영단계가 아니기 때문에, certBot으로 무료 ssl 인증서를 발급받도록 하겠습니다.

 

SSL 인증서를 관리하고 적용하는데 필요한 ngnix와 certbot을 먼저 도커에 띄워보겠습니다.

 

docker-compose.yml

docker-compose를 할 디렉토리에 docker-compose.yml 파일을 통해 컨테이너를 띄우는 과정을 일일히 하지 않고, 한번에 일괄적으로 할 수 있습니다.

version: "3"
services:
  nginx:
    image: nginx:latest
    container_name: trippy-ngnix -> [원하는 컨테이너 이름]
    networks:
      - trippy-network -> [구성해둔 네트워크가 있다면 작성]
    restart: unless-stopped
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/www/certbot:/var/www/certbot
    ports:
      - 80:80
      - 443:443
    command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''

  certbot:
    image: certbot/certbot
    container_name: trippy-nginx-certbot -> [원하는 컨테이너 이름]
    networks:
      - trippy-network -> [구성해둔 네트워크가 있다면 작성]
    restart: unless-stopped
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/www/certbot:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

networks:
  trippy-network:
    driver: bridge
volumes:
  trippy-nginx-vol:
  trippy-certbot-vol:

 

 

 

저의 경우는 위처럼 작성하였습니다. volumes 내부에 [로컬에 있는 원본 파일]:[도커 내부에 마운트할 위치] 를 통해 미리 생성하고 작성해둔 설정 파일을 마운트 하여, 컨테이너가 중단되거나 종료되는 상황이 발생하여도 데이터가 손실되지 않도록 하였습니다.

 

또한 entryPoint를 설정하여 , 추후 ssl 인증서가 만료되었을 경우 certbot이 자동으로 갱신해서 발급해주는 명령어를  컨테이너 안에서 실행할 수 있게 추가해주었습니다.

 

그럼 이제 필요한 설정 파일을 작성해보겠습니다.

 

nginx.conf

nginx를 사용하기 위해서는, 설정 파일이 필요합니다. docker-compose.yml이 있는 디렉토리 하위 conf 폴더를 만들어 nginx.conf 파일을 작성합니다.

server {
     listen 80;

     server_name [구매한 도메인];

     location /.well-known/acme-challenge/ {
             allow all;
             root /var/www/certbot;
     } 
}

 

이제 docker-compose up -d 명령어를 통해 컨테이너를 실행하면 됩니다. Status가 restart나 종료된 것이 아니라면 정상적으로 동작하고 있는 것 입니다. docker logs [컨테이너 이름] 을 통해 컨테이너 로그를 확인할 수 있습니다. 만약 에러가 발생한다면 로그를 보고 해결하시길 바랍니다. (저의 경우에는 오타, 들여쓰기 이슈로 안되었던 적이 있었습니다)

 

인증서 발급

이제 인증서를 먼저 발급받고 진행하도록 하겠습니다. 아래 명령어를 실행하여 인증서를 발급받을 수 있는 스크립트를 다운로드 받으면 됩니다. 다운로드가 되었다면, vi를 통해 도메인, 이메일, 디렉토리를 직접 수정해주고 실행하면 인증서가 발급되게 됩니다.

curl -L <https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh> > init-letsencrypt.sh
chmod +x init-letsencrypt.sh
vi init-letsencrypt.sh // 도메인, 이메일, 디렉토리 수정
sudo ./init-letsencrypt.sh // script를 실행하여 인증서 발급

 

위의 docker-compose.yml에 적힌 경로대로 작성해주면 됩니다. 예시로 아래와 같이 적어주면 됩니다. 저는 /var/www/certbot에 생성하도록 하였습니다.

domains=(trippy.com www.trippy.com)
rsa_key_size=4096
data_path="/var/www/certbot"
email="trippy@naver.com"

 

이제 위에 적어둔대로 sudo를 통해 실행하여 인증서를 발급받았다면, 발급받은 인증서를 토대로 https를 적용하면 됩니다. 적용하러 가보겠습니다.

 

Https 적용

nginx.conf 수정

이제 80번 포트로 들어오는 Http 요청과 더불어, 443 포트로 들어오는 Https 요청을 처리해주어야 합니다. 

user  nginx;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    upstream trippy-spring {
        server trippy-app:8080;
    }

    upstream trippy-flask {
        server flask-trippy-app:5000;
    }

    server {
        listen 80;
        server_name trippy.com;
        server_tokens off;

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

        location / {
            return 301 https://$host$request_uri;
        }
    }

    server {
        listen 443 ssl;
        server_name trippy.com;

        ssl_certificate /etc/letsencrypt/live/trippy.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/trippy.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
            proxy_pass http://trippy-spring/;
            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;
        }

        location /py {
            proxy_pass http://trippy-flask/;
            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;
        }
    }
}

먼저, Http로 들어온 요청도 Https로 리다이렉트 시켜주도록 구성하였습니다. 이후 Https인 443 포트로 들어오는 요청에 대해 ssl 인증서의 경로를 명시함으로서 정상적으로 Https를 적용하였습니다.

 

upstream으로 각 요청('/', '/py')로 들어오는 요청에 대해  반환하는 경로를 따로 지정해주었습니다.  /은 일반 스프링 서버이므로 trippy-app:8080으로 연결하였습니다. 이때 trippy-app은 스프링 도커 컨테이너의 이름이며 8080은 포트 번호입니다. 마찬가지로 /py 로 들어오는 요청에 대해서는 flask 서버로 연결해주어야 하기 때문에, flask 컨테이너의 이름과 포트번호를 작성해줍니다.

 

이로서 하나의 도메인과 gcp로 두개의 서버에 연결을 완료하였습니다. 마지막으로 아래 명령어들도 다시 도커 컴포즈를 재실행하고, 상태 확인하여서 제대로 나오면 성공입니다.

 

docker-compose down
docker-compose up -d
// 거부 당할경우 앞에 sudo를 붙여서 실행

docker ps // 상태 확인

 

 

다음 포스팅에서는 무중단 배포를 적용해보도록 하겠습니다.

 

참고

https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71

 

Nginx and Let’s Encrypt with Docker in Less Than 5 Minutes

Getting Nginx to run with Let’s Encrypt in a docker-compose environment is more tricky than you’d think …

pentacent.medium.com

 

https://velog.io/@rivkode/Docker-Nginx%EC%97%90%EC%84%9C-HTTPS%EB%A5%BC-%EC%9C%84%ED%95%9C-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%A0%81%EC%9A%A9-Lets-encrypt-Docker-compose#ssl-%EC%9D%B8%EC%A6%9D%EC%84%9C%EB%A5%BC-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

 

Docker Nginx에서 HTTPS를 위한 SSL 인증서 적용 (Let's encrypt, Docker compose)

지난글에 이어 이번시간에는 Docker 환경에서 Nginx를 띄우고 Https를 위해 인증서를 적용하는 과정을 설명드리겠습니다.지난 시간에는 아래의 내용들을 완료하였었습니다.Github Actions, Compose를 활용

velog.io

https://velog.io/@wksmstkfka12/%EB%96%A0%EB%A8%B9%EC%97%AC%EC%A3%BC%EB%8A%94-Nginx-Docker%EC%97%90-%EB%AC%B4%EB%A3%8C-SSL-%EC%A0%81%EC%9A%A9

 

떠먹여주는 Nginx Docker에 무료 SSL 적용, 주기적으로 갱신하면서!

Cert bot으로 SSL 인증서를 적용하고 자동으로 갱신해주어 HTTPS 프로토콜 이용하기

velog.io