on:
push:
branches:
- main
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: '20.x'
- name: Install yarn
run: npm install -g yarn
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Test and Build with yarn
run: |
yarn install
yarn workspace client build
- name: Build and Push Docker image
run: |
docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-fe:${{ github.sha }} -f ./Dockerfile-web .
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-fe:${{ github.sha }}
docker build -t ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-be:${{ github.sha }} -f ./Dockerfile-was .
docker push ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-be:${{ github.sha }}
- name: make docker-compose file
run: |
sed -i "s/GITHUB_SHA/${{ github.sha }}/g" docker-compose.yml
- name: send docker-compose file with scp
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
source: docker-compose.yml
target: /app
- name: make .env file
run: |
echo ${{ secrets.ENV }} > .env
- name: send .env file with scp
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
source: .env
target: /app
- name: Deploy with SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /app
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-fe:${{ github.sha }}
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-be:${{ github.sha }}
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker-compose up -d
rm -rf .env docker-compose.yml
앞선 GitHub Actions 스크립트 학습과, 각종 AI들의 도움을 받아 스크립트를 작성해봤다. 중간중간에 에러가 나는 부분을 잡아주느라 main PR을 여러번 올리며 고생을 좀 했다 ㅎ
주요 에러 요인들은 다음과 같다.
echo ${{ secrets.ENV }} > .env
명령으로 파일이 정상적으로 입력되지 않음-e "A=...\n" \ "B=...\n" \ ... ""
형태로 넣어서 스크립트 변경 없이 해결. 다음으로 해석됨echo -e "A=...\n" \
"B=...\n" \
...
"" > .env`
secrets 변수들은 프로젝트 설정의 Secrets and variables => Actions
에 직접 넣어준다.
Actions 탭에서 결과 확인 가능
새로운 tag의 web, was 컨테이너가 잘 돌아가고 있는 것을 확인할 수 있다!
다양한 자료를 참고했지만, 결정적으로 다음의 boilerplate를 활용해 Let's Encrypt 인증서를 발급했다.
서버 인스턴스에 위 repository를 클론해 온 뒤
server {
listen 80;
server_name www.xn--bj0b03z.site;
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 www.xn--bj0b03z.site;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/www.xn--bj0b03z.site/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.xn--bj0b03z.site/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://www.xn--bj0b03z.site;
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;
}
}
/data/nginx/app.conf
의 도메인을 구매한 서버 도메인으로 지정한다.
#!/bin/bash
if ! [ -x "$(command -v docker-compose)" ]; then
echo 'Error: docker-compose is not installed.' >&2
exit 1
fi
domains=(www.xn--bj0b03z.site)
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
...
다음으로 init-letsencrypt.sh
의 도메인도 적절히 변경, email 입력, staging=0
으로 설정 후 실행한다.
./init-letsencrypt.sh
알아서 nginx와 certbot docker 이미지를 다운받고 실행시켜 인증서를 받아준다.
인증서가 잘 받아졌는지 확인하고,
version: '3'
services:
was:
container_name: was
image: qkrwogk/web16-b1g1-be:GITHUB_SHA
ports:
- 3000:3000
env_file:
- .env
networks:
- b1g1-network
web:
container_name: web
image: qkrwogk/web16-b1g1-fe:GITHUB_SHA
ports:
- 80:80
- 443:443
volumes:
- ./data/certbot/conf:/etc/letsencrypt
- ./data/certbot/www:/var/www/certbot
networks:
- b1g1-network
networks:
b1g1-network:
driver: bridge
이제 우리 걸 실행한다. nginx가 있는 web 컨테이너에는 인증서 파일이 동일하게 들어가게 volumes 속성을 부여해줘야 한다. (data 폴더를 container 실행환경으로 옮겨준다)
# nginx.conf with https
server {
listen 80;
server_name www.xn--bj0b03z.site;
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 www.xn--bj0b03z.site;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/www.xn--bj0b03z.site/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.xn--bj0b03z.site/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ =404;
}
location /api {
proxy_pass http://was:3000;
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;
rewrite ^/api(/.*)$ $1 break;
}
}
참고로 nginx conf도 https를 받을 수 있도록, ssl 인증서도 등록해주고 80으로 오면 443으로 리다이렉트 해주고 해야 한다! web 컨테이너는 이 파일을 이용해서 다시 빌드했음
이제 안전한 사이트라고 잘 뜬다!
https 적용 성공! (뿌듯)