본문 바로가기
Develop/Docker

[Docker] Certbot컨테이너를 통한 HTTPS 프로토콜 적용

by 루시킴 2021. 10. 14.

현재 웹서버 Nginx는 http 서버로서의 역할을 하고 있기 때문에 HTTP(기본 포트번호 80)로 들어오는 요청을 HTTPS(기본 포트번호 443)로 리다이렉션 하는 작업을 해줘야한다.

즉, Nginx에서 Certbot을 통해 SSL을 발급받아 Https적용해야한다.

 

Let's Encrypt와 Certbot이란?

  • Let's Encrypt는 무료 SSL인증서를 발급해주는 곳이고, Certbot는 Let's Encrypt 인증서를 자동으로 발급 및 갱신을 해주는 프로그램이다.
  • Certbot을 이용해 인증서를 받기위해선 서비스를 운용하는 서버 & 서비스할 도메인 주소 가 필수적으로 필요하다.
  • Certbot으로 받은 인증서(Encrypt)는 3개월 유효기간이 있으므로 주기에 맞추어 갱신이 필요하다.

 

Docker-compose로 flask+gunicorn+react+nginx 모든 서비스를 한번에 올리는 상황이었기 때문에 기존에 구성했던 docker-compose.prod.yml파일과 nginx.conf를 수정해야한다.

 

진행해야할 작업 순서
Cloud network 방화벽 설정 (443포트 열기) => docker-compose 파일 수정 => nginx.conf파일 수정 => ssl 인증서 발급 => 자동 인증서 갱신

 

1. docker-compose파일 수정

  • nginx 서비스에 443 포트 추가
  • certbot 컨테이너 추가
  • certbot 컨테이너에서 인증서를 발급받아 로컬 서버에 마운트 된 디렉토리에 저장하고, nginx 컨테이너는 동일한 디렉토리를 마운트해 동일한 인증서 파일을 공유받을수 있도록 volume설정 추가
nginx:
        build: ./nginx
        container_name: nginx
        ports:
            - "80:80"
            - "443:443"  # nginx에 443 포트 추가
        restart: "on-failure"
        volumes: 
            # - ./nginx/nginx.conf:/etc/nginx/conf.d
            - build_folder:/var/www/Frontend
            - ./certbot/conf:/etc/letsencrypt  #동일한 디렉토리를 마운트
            - ./certbot/www:/var/www/certbot
        command : "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
        depends_on:
            - flask-app
            - react-app
certbot:  #certbot 컨테이너 추가 
        image: certbot/certbot
        restart: unless-stopped
        container_name: certbot
        volumes: 
            - ./certbot/conf:/etc/letsencrypt    #nginx컨테이너에 certbot컨테이너 연결
            - ./certbot/www:/var/www/certbot
        depends_on:
            - nginx
        entrypoint : "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

2. nginx.conf파일 수정

  • https를 위한 서버를 하나더 생성하여 ssl내용으로 수정
  • 기존 nginx.conf에서 80포트를 listen하던 서버 설정을 새로만든 서버 블록으로 옮김 (react와 flask 관련 설정을 443포트 서버에서 처리)
  • 80포트에선 들어오는 모든 요청을 443포트로 리다이렉트 시킴
    upstream api {
        server flask-app:5000;
    }
    #http
    server {
        listen 80;
        server_name weirdmuseum.ml;  #우리 도메인 이름으로 설정
        server_tokens off;
    
        # Allow only for register SSL (Certbot)
        location /.well-known/acme-challenge/ {
            allow all;
            root /var/www/certbot;
        } 
    
        # Http로 들어온 요청을 Https로 Redirect
        location / {
            return 301 https://$host$request_uri;
        }
    }
    #https
    server {
        listen 443 ssl;
        server_name weirdmuseum.ml;
        server_tokens off;
    
        ssl_certificate /etc/letsencrypt/live/weirdmuseum.ml/fullchain.pem;  # ssl 인증서 사용
        ssl_certificate_key /etc/letsencrypt/live/weirdmuseum.ml/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
        location / {
            root /var/www/Frontend;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html?q=$uri&$args;
        }
    
        location /api/ {
            proxy_pass http://api;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            add_header 'Access-Control-Allow-Origin' *;
        }
    }​
     

3. SSL인증서 발급

  • 이상태 에서 docker-compose up을 하면 실행되지 않는다.
  • 문제 : 현재 설정에서 nginx서버를 올리기 위해선 SSL인증서가 필요한데, SSL인증서를 발급받기위해는 nginx서버가 올라가있어야 되는 모순인 상황이다.
  • 해결방법 : 더미증명서를 발급 => nginx서버 시작 => 더미증명서 삭제 및 실제 증명서 요청
  • 이 방법을 자동화시킨 스크립트 파일을 이용하면 된다. 적용시, domain , data_path, email을 우리것으로 바꾸면된다.
  • 해당 스크립트 파일에 실행가능한 권한을 부여후 실행하면 위의 과정을 통해 인증서 발급이 되며 docker-compose의 정의해놓은 서비스들이 컨테이너에 띄워진다.

4. 자동 인증서 갱신

  • 아까 말했듯이, Let's Encrypt에서 발급받은 인증서는 30일후에 만료되기 때문에 자동 인증서 갱신이 필요하다.
  • 아래의 코드를 docker-compose파일에 추가해주면 끝
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" # certbot에서 12시간마다 갱신여부 판별 
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" # nginx에서 6시간마다 설정을 다시 로드

여기까지 하면 Nginx + Certbot를 이용해 HTTPS 프로토콜 적용이 가능하다.

'Develop > Docker' 카테고리의 다른 글

Docker(도커)란 무엇인가?  (0) 2021.08.29

댓글