가비아에서 구입한 도메인 주소를 도메인 이름 입력칸에 적어주고 '호스팅 영역 생성' 버튼 클릭
빨간 네모 칸 4개의 라우팅을 가비아에 설정해주기
설정버튼 누르고 위에 Route 53에서 받은값들을 차례대로 4개 적어주면 된다
그리고 다시 Route 53으로 돌아와
레코드 생성을 누르고
레코드 이름은 비워두고!
값에 탄력적ip (연결할 인스턴스) 을 적고 레코드 생성버튼을 눌러주면 모든 라우터 설정은 끝이 난다!
docker pull certbot/certbot
하지만 이렇게 코드를 치게 되면 ㅠㅠㅠ 오류가 발생했다!!
docker run -it --rm --name certbot -p 80:80 -p 443:443 -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly --standalone -d your_domain -d www.your_domain
your_domain : 가비아에서 산 도메인
그런데 이 명령어를 실행했을 때 오류가 발생했다
Error response from daemon: driver failed programming external connectivity on endpoint certbot (ad071f4a6e476500b157196a59a493c03417a407c242051b08a510130a420c87): Bind for 0.0.0.0:80 failed: port is already allocated.
ERRO[0000] error waiting for container: context canceled
즉 80 포트가 사용중이기 때문에 certbot으로 도메인 연결에 실패했다는 의미였다
지금 현재 nginx 서버가 80 포트에 탄력적ip로 연결되어 열려있는 상태였다 그래서 일단 nginx 80 포트를 중지 시켜준 뒤 cerbot 을 설치해서 ssl 인증을 받아야했다
docker stop 'nginx 서버이름'
내가 설정해놓은 nginx 서버이름이 nginxserver 였기에 나는
docker stop nginxserver
이렇게 입력해주었다
그리고 다시 Certbot을 실행하여 SSL 인증서를 생성을 시도했다
sudo docker run -it --rm --name certbot -p 80:80 -p 443:443 -v "/etc/letsencrypt:/etc/letsencrypt" -v "/var/lib/letsencrypt:/var/lib/letsencrypt" certbot/certbot certonly --standalone -d your domain
your_domain : 가비아에서 산 도메인
그럼 이메일 입력칸이 나온다
본인의 이메일 입력해주고 enter
그리고 계속 yes 해주기!
그럼 이렇게 성공했다고 나온다
docker start nginx서버이름
sudo docker start nginxserver 으로 다시 서버를 재시작 해주었다
그리고 Nginx 설정 파일을 수정하기 위해 Docker 컨테이너에 접속하였다
docker exec -it nginx서버이름 bash
cd /etc/nginx/conf.d/default.conf
// upstream은 웹 서버로 요청을 전달할 업스트림 서버를 지정
upstream blue {
server 11.111.11.111:8080; // 인스턴스 탄력적 ip :8080
}
upstream green {
server 11.111.11.111:8081; // 인스턴스 탄력적 ip :8081
}
// HTTP 프로토콜을 사용하는 80 포트에서 들어오는 요청을 처리하는 서버 블록
server {
listen 80;
server_name sandboxproject.shop; // domain 주소
return 301 https://$host$request_uri; // sandboxproject.shop 도메인으로 들어오는 요청은 모두 HTTPS로 리다이렉션
}
// HTTPS 프로토콜을 사용하는 443 포트에서 들어오는 요청을 처리하는 서버 블록
// sandboxproject.shop 도메인으로 들어오는 요청은 SSL 인증서를 사용하여 암호화된 연결로 처리
server {
listen 443 ssl;
server_name sandboxproject.shop;
// SSL 인증서 파일의 경로는 ssl_certificate와 ssl_certificate_key로 지정
ssl_certificate /etc/letsencrypt/live/sandboxproject.shop/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sandboxproject.shop/privkey.pem;
#access_log /var/log/nginx/host.access.log main;
include /etc/nginx/conf.d/service-env.inc;
location / {
proxy_pass http://$service_url;
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;
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
Nginx 설정도 끝났으니 바로 github Action 으로 cicd 를 실행시켰더니 오류가 났다
이 오류에 빠져서 몇시간을 허비했는지 모른다ㅠㅠㅠㅠㅠ
이 오류가 난다면 꼭 이 방법을 적용해보길 바란다
err: nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/sandboxproject.shop/fullchain.pem":
BIO_new_file() failed (SSL: error:80000002:system library::No such file or directory:calling fopen(/etc/letsencrypt/live/sandboxproject.shop/fullchain.pem, r) error:10000080:BIO routines::no such file)
nginx에 분명 ssl 인증서를 참조할 수 있게 넣어주었는 데도 인증서를 찾지못한느 오류에 빠져버렸다
// SSL 인증서 파일의 경로는 ssl_certificate와 ssl_certificate_key로 지정
ssl_certificate /etc/letsencrypt/live/sandboxproject.shop/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sandboxproject.shop/privkey.pem;
우분투 서버에 가서
sudo ls -l /etc/letsencrypt/live/sandboxproject.shop/
본인 도메인 주소에 해당하는 pem 키가 있는 지 확인한다
total 4
-rw-r--r-- 1 root root 692 Feb 21 11:00 README
lrwxrwxrwx 1 root root 43 Feb 21 11:00 cert.pem -> ../../archive/sandboxproject.shop/cert1.pem
lrwxrwxrwx 1 root root 44 Feb 21 11:00 chain.pem -> ../../archive/sandboxproject.shop/chain1.pem
lrwxrwxrwx 1 root root 48 Feb 21 11:00 fullchain.pem -> ../../archive/sandboxproject.shop/fullchain1.pem
lrwxrwxrwx 1 root root 46 Feb 21 11:00 privkey.pem -> ../../archive/sandboxproject.shop/privkey1.pem
이렇게 출력이 되면 pem 키가 존재한다는 것은 확인 된거다
pem 키에 대한 권한이 없기에 참조하기 어렵다고 판단을 했다 그래서 두가지 방법을 사용했다
docker-compose.yml 파일에 인증서 파일이 위치한 디렉토리를 컨테이너에 마운트 하면 심볼릭 링크가 가리키는 실제 위치한 파일에 위치한 디렉토리를 마운트하는 방법을 사용하였다
docker-compose-blue.yml
version: '3.8'
services:
blue:
image: younssue/live_server:latest
container_name: blue
ports:
- "8080:8080"
environment:
- PROFILES=blue
- ENV=blue
volumes:
- /etc/letsencrypt:/etc/letsencrypt
- /etc/letsencrypt/archive:/etc/letsencrypt/archive
🐫 그런데 문제가 있었다.. 위에 코드 처럼 나는 blue/ green 서버에 대한 docker-compose-{env}.yml 밖에 없었다
본질적인 nginxserver docker-compose.yml 이 없던 것이다
그래서 blue/green 서버에만 docker 마운트 방법만 적용하고
nginxserver는 다른 방법을 써야했다
여기서는 나처럼 blue/green 무중단 배포 하는 방법에서 쓰이는 방법이니
위에 처리까지 해줬는데도 안된다면 이 방법도 고려해보길 바란다
sudo docker stop nginxserver
sudo docker rm nginxserver
sudo docker run -d -p 80:80 -p 443:443 -v /etc/letsencrypt:/etc/letsencrypt -v /etc/letsencrypt/archive:/etc/letsencrypt/archive --name nginxserver nginx
/etc/letsencrypt와 /etc/letsencrypt/archive 디렉토리를 nginxserver 컨테이너에 마운트 한다
그런데 이렇게 되면 기존에 설정해둔 Nginx설정이 다 날라간다 🥲
나는 그걸 모르고 바로 해버려서....다시 nginx 설정을 해주었다
볼륨마운트 추가하기전에 미리 코드를 백업해두자!
cd /etc/nginx/conf.d/default.conf
// upstream은 웹 서버로 요청을 전달할 업스트림 서버를 지정
upstream blue {
server 11.111.11.111:8080; // 탄력적 ip:8080
}
upstream green {
server 11.111.11.111:8081; // 탄력적 ip:8081
}
// HTTP 프로토콜을 사용하는 80 포트에서 들어오는 요청을 처리하는 서버 블록
server {
listen 80;
server_name sandboxproject.shop; // domain 주소
return 301 https://$host$request_uri; // sandboxproject.shop 도메인으로 들어오는 요청은 모두 HTTPS로 리다이렉션
}
// HTTPS 프로토콜을 사용하는 443 포트에서 들어오는 요청을 처리하는 서버 블록
// sandboxproject.shop 도메인으로 들어오는 요청은 SSL 인증서를 사용하여 암호화된 연결로 처리
server {
listen 443 ssl;
server_name sandboxproject.shop;
// SSL 인증서 파일의 경로는 ssl_certificate와 ssl_certificate_key로 지정
ssl_certificate /etc/letsencrypt/live/sandboxproject.shop/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sandboxproject.shop/privkey.pem;
#access_log /var/log/nginx/host.access.log main;
include /etc/nginx/conf.d/service-env.inc;
location / {
proxy_pass http://$service_url;
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;
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
service-env.inc
set $service_url green;
이렇게 하고 돌려주면 된다 생각했는데 ... 또 오류를 만나버렸다
그것은 blue/green 서버가 꼬여버린것이다 🤮
우분투 서버로 다시 가서 아래 명령어를 실행해준다
sudo docker ps -a
이 명령어를 실행해준다면 현재 blue/ green / nginxserver 이렇게 3개가 올라와있었다 (계속 cicd 테스트를 해주다 오류가 나다보니 하나의 서버를 닫아야하는데 그러지 못하고 둘다 살아있는 상태가 되어버렸다)
명령어 예시
sudo docker stop green // green 서버 종료
sudo docker rm green // green 서버 삭제
sudo docker run -d -p 8081:8081 -e "PROFILES=green" -e "ENV=green" --name green {dockerHub UserName}/{docker imageName}:latest
// green 서버 run
그래서 나는 아예 blue / green 서버를 삭제하고
service-env.inc 도 초기설정이 green으로 바꿔주고
set $service_url green;
githubAction으로 cicd를 작동시켜주었더니 성공한 줄 알았다...
이렇게 작동이 되어서 되는 줄 알았다....
하지만 문제는 green 서버가 죽어있는 게 문제가 아니였다
설정의 문제가 있었다
계속 됐다 안됐다의... 굴레 속에 빠져버렸다...
cd /etc/nginx/conf.d/default.conf
// upstream은 웹 서버로 요청을 전달할 업스트림 서버를 지정
upstream blue {
server {domain 주소}:8080; // domain 주소
}
upstream green {
server {domain 주소}:8081; // domain 주소
}
name: CICD
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew clean build -x test
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build Docker
run: docker build --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/live_server .
- name: Push Docker
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/live_server:latest
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Set target IP
run: |
STATUS=$(curl -o /dev/null -w "%{http_code}" "https://${{ secrets.LIVE_SERVER_IP }}/env") // 여기서 https로 설정 , LIVE_SERVER_IP -> domain 으로 변경
echo $STATUS
if [ $STATUS = 200 ]; then
CURRENT_UPSTREAM=$(curl -s "https://${{ secrets.LIVE_SERVER_IP }}/env") // 여기서 https로 설정 , LIVE_SERVER_IP -> domain 으로 변경
else
CURRENT_UPSTREAM=green
fi
echo CURRENT_UPSTREAM=$CURRENT_UPSTREAM >> $GITHUB_ENV
if [ $CURRENT_UPSTREAM = blue ]; then
echo "CURRENT_PORT=8080" >> $GITHUB_ENV
echo "STOPPED_PORT=8081" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=green" >> $GITHUB_ENV
else
echo "CURRENT_PORT=8081" >> $GITHUB_ENV
echo "STOPPED_PORT=8080" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=blue" >> $GITHUB_ENV
fi
- name: Docker compose
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.LIVE_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/live_server:latest
sudo docker-compose -f docker-compose-${{env.TARGET_UPSTREAM}}.yml up -d
- name: Check deploy server URL
uses: jtalk/url-health-check-action@v3
with:
url: https://${{ secrets.LIVE_SERVER_IP }}/env // 여기서 https로 설정 , LIVE_SERVER_IP -> domain 으로 변경, :${{env.STOPPED_PORT}} 삭제
max-attempts: 5
retry-delay: 10s
- name: Change nginx upstream
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.LIVE_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker exec -i nginxserver bash -c 'echo "set \$service_url ${{ env.TARGET_UPSTREAM }};" > /etc/nginx/conf.d/service-env.inc && nginx -s reload'
- name: Stop current server
uses: appleboy/ssh-action@master
with:
username: ubuntu
host: ${{ secrets.LIVE_SERVER_IP }}
key: ${{ secrets.EC2_SSH_KEY }}
script_stop: true
script: |
sudo docker stop ${{env.CURRENT_UPSTREAM}}
sudo docker rm ${{env.CURRENT_UPSTREAM}}
-> 주석으로 처리된 부분을 바꿔주었다
- name: Check deploy server URL
uses: jtalk/url-health-check-action@v3
with:
url: https://${{ secrets.LIVE_SERVER_IP }}/env // 여기서 https로 설정 , LIVE_SERVER_IP -> domain 으로 변경, :${{env.STOPPED_PORT}} 삭제
max-attempts: 5
retry-delay: 10s
http://${{ secrets.LIVE_SERVER_IP }}:${{env.STOPPED_PORT}}/env -> https://${{ secrets.LIVE_SERVER_IP }}/env 으로 변경!
이렇게 실행해주면 실행이 잘 되게 되어진다!
그렇다면 왜 안됐을까 추정을 해보자면 https 로 수정을 해준 뒤 githubAction 에서 CICD.yml 에 바꿔야할 부분들이 있었는데 수정해주지 않은 채 배포를 시도하니 http쪽 방화벽이 막힌 상태에서 계속 서버를 바꾸려고 했어서 거기서 생긴 오류 같았다
그래서 CICD.yml 파일 https로 설정하고 탄력적ip도 도메인으로 수정을 해주니 막혔던 문제가 해결이 되었다