Duck DNS라는 무료 도메인 사이트를 이용하였습니다.
{원하는 주소}.duckdns.org 형태로 주소를 사용할 수 있습니다.
아래 사이트로 들어가서 회원가입 후 로그인합니다.
https://www.duckdns.org/
add domain을 클릭 후 값을 입력을 입력합니다.
sub domain : 원하는 주소 값
current ip : public ip
Let's Encrypt라는 무료 SSL인증서 발급 기관을 사용하였고, 90일의 유효기간이 있어서 리눅스 명령어를 통해서 자동으로 인증서가 갱신되도록 구성하였습니다.
크게 아래와 같은 순서로 진행이 됩니다.
- docker-compose.yml, app.conf 작성
- docker-compose 실행
- init-letsencrypt.sh download
- init-letsencrypt.sh 수정 및 실행하여 인증서 발급
- docker-compose.yml, app.conf 작성
리눅스 서버에 연결하여 docker-compose.yml 파일을 작성해줍니다.
저는 ~/docker 경로 하위에 파일들을 생성하였습니다.
// i클릭(INSERT모드) -> 내용작성 -> ESC클릭 -> :wq입력 -> enter클릭
vi ~/docker/docker-compose.yml
version: '3'
services:
nginx:
container_name: nginx
image: nginx:1.22-alpine
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
certbot:
container_name: certbot
image: certbot/certbot
restart: unless-stopped
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
vi ~/docker/data/nginx/app.conf
server {
listen 80;
server_name {도메인 값};
server_tokens off;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
docker-compose -f docker-compose.yml 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
파일을 들어가면 여러 내용이 있는데 domains, email만 수정해주시면 됩니다.
도메인 값은 duckdns로 발급받은 주소를 입력해주시면됩니다.
// ...
domains=({도메인 값} www.{도메인 값})
rsa_key_size=4096
data_path="./data/certbot"
email="{이메일 입력}" # Adding a valid address is strongly recommended
staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits
// ...
sudo ./init-letsencrypt.sh
yes/no 질문이 나오면 yes를 입력해주시면 인증서 발급이 완료됩니다.
https로 접속할 수 있도록 80, 443 포트 설정을 해주고 http로 접속했을 경우 https로 리다이랙트 하도록 구성하였습니다.
app.conf 파일과 docker-compose.yml 파일을 수정해줍니다.
upstream my-app {
server {cloud instance public ip}:8080;
}
server {
listen 80;
server_name {도메인 값};
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 {도메인 값};
server_tokens off;
ssl_certificate /etc/letsencrypt/live/{도메인 값}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{도메인 값}/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://my-app;
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;
}
}
{cloud instance public ip} : oracle cloud instance public ip 값
도메인 값 : duckdns로 발급 받은 주소
version: '3'
services:
spring_boot:
container_name: spring_boot
image: {이미지명}
ports:
- "8080:8080"
networks:
- my_network
nginx:
container_name: nginx
image: nginx:1.22-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx:/etc/nginx/conf.d
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
depends_on:
- spring_boot
networks:
- my_network
certbot:
container_name: 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;'"
networks:
- my_network
networks:
my_network:
driver: bridge
이미지명 : spring boot 이미지 명
docker-compose -f docker-compose.yml down
docker stop {name 또는 ID}
docker rm {name 또는 ID}
docker-compose -f docker-compose.yml up -d
여기까지 에러 없이 왔으면 성공적으로 무료로 평생 DNS, SSL를 사용하실 수 있습니다.
docker-compose.yml에 볼륨 경로가 적절하지 않아서 발생한 문제로 nginx이미지나 버전에 따라 경로가 다르므로 볼륨경로를 설정할 때 이미지명과 버전에 맞는 경로로 수정하여 해결
도메인명, 컨테이너명 오타로 인해 발생한 문제
아직 미해결한 문제로 원하던 것은 nginx로 들어온 경로를 8080포트로 포트포워딩 하는 과정에서 컨테이너 명으로 연결시키고 싶었지만 되지 않아서 임시로 ip값을 넣어서 연결.
하지만 0,443포트만 열고 나머지 포트는 접속할 수 없도록 하는 것이 안전하기 때문에 다른 방법을 찾아서 수정이 필요
SSL 인증서를 도입해보면서 암호화(대칭키/비대칭키), SA(인증기관), DNS, 프록시서버 등의 많은 CS지식을 알 수 있게 되었습니다. 나중에 위 개념에 대해 공부했던 것들을 정리하여 포스팅하도록 하겠습니다.
그리고 Oracle Cloud 시리즈에서는 자동 배포까지는 구현되어있지 않은데 jenkins, github action 등등의 다양한 환경에서 CI/CD하는 방법도 포스팅 하도록 하겠습니다.