안녕하세요! 오늘은 Nginx 웹서버를 도커 컴포즈를 이용하여 세팅하고, Certbot 을 이용해서 HTTPS 인증서를 연결하는 과정까지 포스팅해보겠습니다.
해당 과정은 저의 개인 프로젝트에 적용했던 경험을 바탕으로 작성했습니다.
- 해당 프로젝트 레포
https://github.com/wil953742/study-mbti
왜 도커를 사용했나?
크레딧의 한계 때문에 클라우드 서비스를 이리저리 옮겨 다닐 것 같다는 생각이 들어서 (아직은 아닙니다만...) 서버 환경을 image화 할 수 있고, 혹시라도 대박( 기대 0.00001% 정도...? )이나서 트래픽이 몰릴 경우 유동적으로 서버를 추가할 수 있도록 도커를 사용하기로 했습니다.
+ 도커 캐릭터가 너무 귀여워서..?
Docker-compose를 사용한 이유?
docker-compose는 여러가지의 컨테이너들을 실행하기 위해 필요한 설정들이 많은데 (ex. 볼륨 설정, 네트워크 설정 등등) docker-compose.yml 파일에 컨테이너 실행 명령어들을 전부 적어 놓고, docker-compose 파일만 실행시키면 한 번에 컨트롤이 가능하다는 장점이 있습니다.
제가 생각한 Nginx 설정은 이렇습니다.
API 서버를 따로 만들 필요가 없는 프로젝트였기 때문에, 단순히 GET 요청에 대해 정적 파일만 제공해주면 된다고 생각했습니다. 다만, HTTP 접속 시 모든 연결을 HTTPS로 리다이렉트 해야한다고 생각했습니다.
HTTPS 연결은 비대칭키 방식과 인증서를 이용하여 대칭키를 주고 받고, 해당 대칭키로 송수신 데이터를 암호화 하는 연결입니다. 때문에 대칭키를 주고 받기 위해, 공인된 기관의 "개인키(Private Key)"와 "인증서(Certificate)"를 받아야 했습니다. 저는 무료이며 자동화된 인증 기관인 "Let's Encrypt"의 "certbot" 프로그램을 이용하기로 했습니다.
도커 허브에서 certbot 이미지를 제공하고 있기 때문에, 도커 컴포즈 파일에 certbot container 설정을 추가했습니다.
# docker-compose.yml
version: '3.1'
services:
nginx:
image: nginx:latest
# 네트워크 모드를 host로 하면 컨테이너가 독립적인 네트워크를 갖지 않고 host와 네트워크를 함께 사용
# 그렇지 않으면 호스트와 컨테이너 사이의 네트워크를 연결해줘야 함
network_mode: 'host'
ports:
- '80:80'
- '443:443'
restart: unless-stopped
volumes:
# 왼쪽 위치는 빌드된 정적파일이 저장되는 곳, 오른쪽은 nginx root 폴더로 설정한 곳 ( index.html을 참조하는 곳 )
- /root/study-mbti/dist:/usr/share/nginx/html
# 여기서부터는 아래 certbot 컨테이너에 저장되는 "인증서", "개인키" 를 nginx 와 연결하기 위한 설정
- ./nginx/conf.d:/etc/nginx/conf.d
- ./certbot/conf:/etc/letsencrypt
- ./certbot/data:/var/www/certbot
certbot:
image: certbot/certbot:latest
# 한글 부분은 인증 관련, 내 개인정보를 입력하면 된다. ex) 이메일: qwe123@naver.com, 도메인: woongs.shop
command: certonly --webroot --webroot-path=/var/www/certbot --email 이메일 --agree-tos --no-eff-email -d 도메인
volumes:
# 여기도 위 nginx 컨테이너와 연결을 위한 설정
- ./certbot/conf:/etc/letsencrypt
- ./certbot/logs:/var/log/letsencrypt
- ./certbot/data:/var/www/certbot
코드에 대한 상세 설명은 주석에 작성했습니다.
여기서 주의해야할 점은 volume 설정 시 path 값에 대한 설정입니다.
간추려본 저의 폴더 구조는 다음과 같았습니다.
모든 JavaScript, CSS, 이미지 파일들은 "src" 폴더 안에 전부 들어 있고, 웹팩으로 build 할 경우, bundling 된 파일이 dist 폴더에 업데이트 되는 구조였습니다.
그리고 docker-compose.yml 파일에서 volume 설정에 대한 path 를 작성할 때, 위와 같은 nginx 설정 파일과 정적파일 위치를 고려해서 작성했습니다. 시간을 들여 위 폴더 구조와 volume 설정 경로를 비교하신다면, 어떤 식으로 경로를 설정했는지 이해가 가실 거라고 생각합니다.
위와 같이 docker-compose.yml 파일을 작성하고 해당 파일이 존재하는 폴더에서 다음 명령어를 통해 docker-compose를 실행시켜줍니다.
$ docker-compose up -d
( -d 옵션은 백그라운드 실행 )
해당 명령어를 실행하면 certbot 이미지가 자동으로 다운되고, 만약 도메인이 연결되어 있는 상태라면 인증서와 개인키를 받을 수 있습니다.
혹시 에러가 날 경우에는 다음 명령어를 통해 각 컨테이너의 로그를 확인할 수 있습니다!
$ docker-compose logs -f
( 저는 해당 과정에서 도메인의 A 또는 AAA 레코드를 찾을 수 없다는 에러가 발생했었는데, 도메인 호스팅 설정에서 @ 와 www 호스트에 대한 A 레코드를 추가해서 해결했습니다. )
도메인에 대한 인증서와 개인키가 성공적으로 받아졌다면, 다음과 같이 인증서와 개인키의 위치가 표시됩니다.
두 경로를 잘 저장해놨다가 nginx 설정에 입력해야합니다.
이제 nginx 설정 파일을 작성해 줍니다. nginx 설정파일은 위 디렉토리 구조에서 conf.d 폴더 안에 "default.conf" 라는 파일 내부에 작성해주면 됩니다.
server {
listen 80;
server_name 도메인 www.도메인;
access_log /var/log/nginx/host.access.log main;
if ($host = studymbti.shop) {
return 301 https://$host$request_uri;
}
if ($host = www.studymbti.shop) {
return 301 https://$host$request_uri;
}
location ~ /.well-known/acme-challenge {
allow all;
root /var/www/certbot;
}
}
server {
listen 443 ssl http2;
server_name 도메인 www.도메인;
access_log /var/log/nginx/host.access.log main;
root /usr/share/nginx/html;
ssl_certificate /etc/letsencrypt/live/도메인/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/도메인/privkey.pem;
location / {
try_files $uri /index.html;
}
}
그리고 나서 docker compose 파일을 재실행 하면 변경된 설정이 적용되고, https 프로토콜을 적용할 수 있습니다.
- 재실행 코드
$ docker-compose down
$ docker-compose up -d
nginx 설정에 대한 세부 내용은 라우팅관련 글에서 더 자세하게 작성해보도록 하겠습니다.
'프론트엔드' 카테고리의 다른 글
Sentry 를 알아보자 - (1) Trace, Transaction, Span 이란? (0) | 2024.02.04 |
---|---|
모노레포의 개념, 장단점, 종류 (1) | 2024.02.01 |
자바스크립트로 브라우저 라우팅 구현하기 (0) | 2022.01.02 |
TypeScript를 활용한, FLUX 패턴 적용하기 (0) | 2022.01.02 |
[TS] 이것만 알아도 기초탄탄? TypeScript 기초 정리! (1) | 2021.12.16 |