Nginx에 SSL 인증서를 적용한 내용을 공유합니다.
컨테이너 상의 Nginx에 인증서를 적용하다 보니 방법이 잘 이해가 가지 않아 생각해보다 헤매었네요 😲
Let’s Encrypt 유효성 검사를 완료하려면 Nginx가 필요하지만 인증서가 없으면 nginx가 시작되지 않습니다.
그래서 임시로 https를 사용하지 않는 척 nginx를 실행한 다음 인증서를 발급받고
https를 사용한 nginx에 인증서를 적용하면 됩니다.
준비물
- docker-compose
- 도메인 주소
💡 SSL이란?
https를 통한 인터넷 접속은 서버와의 암호화를 통신하고 있는 것을 의미합니다.
이때 사용하는 보안 프로토콜이 SSL(Secure Socket Layer)이며 보안이 향상된 통신을 할 수 있게 됩니다.
- http 뒤에 붙는 s가 secure!
- SSL과 TLS는 같은 의미의 단어(TLS가 후속 버전)
- http는 80번 포트, https는 443번 포트 사용
SSL을 위해 필요한 것이 SSL 인증서입니다.
👀 https를 적용하지 않고 SSL 인증서 발급받기
docker-compose.yml
nginx.conf 파일은 사용자 환경에 맞게 경로를 잡아주시면 됩니다.
./data 폴더는 수동으로 생성하지 않아도 됩니다.
version: '3'
services:
  nginx:
    image: nginx:latest
    restart: unless-stopped
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
      - ./data/certbot/conf:/etc/letsencrypt 
      - ./data/certbot/www:/var/www/certbot
    ports:
      - 80:80
      - 443:443
  certbot:
    image: certbot/certbot
    restart: unless-stopped
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt 
      - ./data/certbot/www:/var/www/certbot
conf/nginx.conf
server {
     listen 80;
     listen [::]:80;
     server_name domain; // 등록한 도메인으로 변경
     location /.well-known/acme-challenge/ {
             allow all;
             root /var/www/certbot;
     } 
}
docker-compose를 실행합니다.
docker-compose -f docker-compose.yml up -d
docker ps // nginx와 certbot 컨테이너가 살아있는지 확인
인증서 발급받는 스크립트를 다운로드하고 도메인, 이메일 주소, 디렉터리를 변경합니다.
인증서 발급에 실패한 경우 실패 시 메시지나 docker log를 통해 원인을 찾을 수 있습니다.
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 // 인증서 발급  
👌 HTTPS 적용하기
이제 인증서를 발급받았으니 HTTPS를 적용할 수 있습니다.
nginx.conf 수정
server {
    listen 80;
    server_name example.org; # 도메인으로 변경
    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 example.org; # 도메인으로 변경
    server_tokens off;
    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # example.org를 도메인으로 변경
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem; # example.or를 도메인으로 변경
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    location / {
        proxy_pass  <http://example.org>;
        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;
    }
}
인증서를 자동으로 갱신하도록 설정하지 않으면 만료될 때마다 다시 발급을 해주어야 합니다.
자동으로 인증서가 갱신되도록 docker-compose.yml 파일을 수정합니다.
version: '3'
services:
  nginx:
    image: nginx:1.15-alpine
    restart: unless-stopped
    volumes:
      - ./data/nginx:/etc/nginx/conf.d
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/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
    restart: unless-stopped
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
마무리

이제 HTTPS이 적용되었습니다!
이 글은 Nginx and Let’s Encrypt with Docker in Less Than 5 Minutes를 참고하여 작성되었으며 예제는 아래 깃헙에서 확인하실 수 있습니다. :)
'기타' 카테고리의 다른 글
| [Github] Fork해온 저장소에 잔디 심는 방법(커밋해도 잔디가 안심어질때) (0) | 2022.12.07 | 
|---|---|
| Sentry로 쉽고 안전하게 서비스 운영하기 (0) | 2022.01.23 | 
| [Macbook] 맥북 외장모니터 연결 문제 임시 해결(모니터 깜빡임) (2) | 2022.01.09 | 
| [Docker] Docker, Nginx, Node.js 환경에서 서비스 무중단 배포하기 (0) | 2021.12.19 | 
| [Docker] Docker 호스트에 원격으로 배포하기(docker compose 이용) (1) | 2021.12.18 | 
![[Docker] Docker 환경 Nginx에 SSL 인증서 적용하기(Let’s Encrypt)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdna%2FONcvc%2FbtrqXxdP2ty%2FAAAAAAAAAAAAAAAAAAAAANx_lz3JbQRACDRiHT7FioeZWyk6Av8uYO6OIhWvNckA%2Fimg.png%3Fcredential%3DyqXZFxpELC7KVnFOS48ylbz2pIh7yKj8%26expires%3D1761922799%26allow_ip%3D%26allow_referer%3D%26signature%3DXOsX8FFov%252BMfCdWHYur2YP91HR4%253D)