
물론 Route53,ACM 같이 도메인관련 좋은 서비스는 많다. 하지만 나는 과금을 더 이상은 하기가 싫었다.
그래서 Let's encrypt를 사용해서 ssl인증을 진행했다. 그런데 이 과정이 너무나 빡셌다. 도커를 처음했던 내가 얕은지식으로 했던 것이 사고였다.
이 부분은 엄청 쉽다.
나 같은 경우에는 가비아에서 www.jaetteoli.shop으로 도메인을 구입했다.

도메인을 ec2에 적용하는 방법은 간단하다.
1. ec2에 탄력적IP적용
2. ec2의 IP를 내 도메인의 A타입과 매핑해두기
끝이다.
이렇게하면 도메인과 인스턴스의 IP와 연결은 끝났다. 이제 nginx가 이 정보를 알 수 있도록 해야한다.
server {
listen 80;
server_name www.jaetteoli.shop;
access_log off;
location / {
proxy_pass http://server:8081;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server_name에 원래는 퍼블릭DNS가 적용되어 있었지만, www.jaetteoli.shop으로 그 내용을 바꿔주면 된다.
version: '3'
services:
server:
container_name: server
image: kimjiseop/jaetteoli-server
expose:
- 8081
ports:
- 8081:8081
restart: "always"
env_file:
- .env
nginx:
container_name: nginx
image: kimjiseop/jaetteoli-nginx
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- "server"
certbot:
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
여기서 중요하게 봐야할 부분은
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
restart: unless-stopped 이 설정은 컨테이너가 수동으로 중지되지 않는 한 항상 자동으로 재시작되도록 하는 설정이다. 이전에는 always 옵션이였지만, 이번에는 수정을 했다.
volumes: 호스트와 컨테이너 사이에 볼륨을 설정한다. 일전에 말했던 볼륨마운트 설정이다. 볼륨은 데이터를 컨테이너가 아닌 호스트 시스템(여기서는 EC2)에 저장하게 해서, 컨테이너가 삭제되거나 재시작될 때도 데이터가 유지되도록 하는 설정이다.
./nginx/conf.d:/etc/nginx/conf.d라고 설정을 해놨다면, EC2 시스템 내의 .(작업 디렉토리)/nginx/conf.d 디렉토리를 Nginx 컨테이너 내부의 /etc/nginx/conf.d 디렉토리와 연결이 지어진다고 생각하면 된다.로컬에서 nginx.conf를 편집해서 배포를 아무리해도, 배포된 Nginx 컨테이너 내부의 conf.d에는 방금 로컬에서 배포한 nginx.conf가 위치하는 것이 아니라, 무조건 EC2의 ./nginx/conf.d 환경으로 덮어지게 되는 것이다. -> 내가 이것 때문에 고생을 많이 한 것 같다.. 정말 처음에는 이해하기 어려웠다.image: certbot/certbot certbot/certbot 이미지를 사용하는데, 이 이미지는 Let's Encrypt의 Certbot을 포함하고 있다.
volumes: ... Let's Encrypt의 설정 및 인증서 정보를 저장할 볼륨을 설정한다. 이렇게 하면 인증서 정보가 컨테이너 외부에 유지되므로, 컨테이너가 재시작되거나 삭제될 때도 인증서 정보가 보존된다고 보면 된다.
server {
listen 80;
listen [::]:80;
server_name www.jaetteoli.shop;
location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
}
}
그리고나서,
docker-compose -f docker-compose.yaml up -d
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를 적용할 수 있다.EC2내에서 nginx.conf를 수정해야 한다.
vi 혹은 vim을 쓰면되지만, 혹시라도 read-only 경고가 뜨면서 수정이 안될 때를 대비하여 sudo로 nginx.conf를 수정하면 된다.
server {
listen 80;
listen [::]:80;
server_name www.jaetteoli.shop;
access_log off;
location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name www.jaetteoli.shop;
ssl_certificate /etc/letsencrypt/live/www.jaetteoli.shop/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.jaetteoli.shop/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://server:8081;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
location /.well-known/acme-challenge/
/.well-known/acme-challenge/ 경로에 특정한 정보를 배치하게 되는데, 이 설정은 그 요청을 처리하는 부분이라고 보면된다.return 301 https://$host$request_uri; 80포트로 들어오는 HTTP 요청을 HTTPS로 리다이렉트하는 부분이다. 이를 통해 모든 트래픽이 암호화되도록 강제하는 것이다. 301은 HTTP 상태 코드로 "Moved Permanently"를 나타내며, $host는 요청이 도착한 서버의 이름, $request_uri는 요청의 URI를 의미한다.
docker-compose.yaml 파일을 수정해야 한다.version: '3'
services:
server:
container_name: server
image: kimjiseop/jaetteoli-server
expose:
- 8081
ports:
- 8081:8081
restart: "always"
env_file:
- .env
nginx:
container_name: nginx
image: kimjiseop/jaetteoli-nginx
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
depends_on:
- "server"
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;'"
command : "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
이 두개를 잘 봐야한다
command : "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
이 명령은 무한루프를 실행하면서 6시간마다 Nginx를 재시작하는 작업을 수행한다.
sleep 6h & wait $${!} 현재 스크립트를 6시간동안 멈추는 명령.
nginx -s reload Nginx 서버를 재시작.
nginx -g \"daemon off;\" Nginx를 데몬 모드가 아닌 포어그라운드에서 실행한다. 이는 Docker 컨테이너의 특성상 백그라운드에서 실행되는 데몬 프로세스가 컨테이너의 생명주기를 제어하면 안 되기 때문이라고 한다.
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
이 명령은 무한루프를 실행하면서 12시간마다 Certbot를 이용해 SSL 인증서를 갱신하는 작업을 수행한다.
trap exit TERM TERM 시그널을 받으면 스크립트를 종료한다. Docker가 컨테이너를 종료할 때는 보통 TERM 시그널을 보내므로, 이 명령을 사용하면 Docker가 컨테이너를 정상적으로 종료할 수 있다.
certbot renew SSL 인증서를 갱신한다.
sleep 12h & wait $${!} 현재 스크립트를 12시간동안 멈춘다.


잘 읽었습니다. 좋은 정보 감사드립니다.