배포 스크립트의 절반은 멈추는 조건이다
이 블로그의 배포는 오랫동안 손으로 했다. 서버에 ssh로 들어가서 git pull, 그리고 pm2 restart.
잘 되는 날에는 아무 문제가 없다. 문제는 급한 날이다. 급한 날에는 순서를 하나씩 빼먹는다.
그래서 npm run deploy 한 줄로 끝나는 스크립트를 만들었다. 만들고 나서 보니 스크립트의 절반은 배포가 아니라 "멈추는 조건"이었다. 하나같이 한 번씩 데이고 나서 넣은 것들이다.
파일은 rsync로 보낸다. 바뀐 파일만 보내고, 로컬에서 지운 파일은 서버에서도 지운다.
rsync -az --delete --itemize-changes \ -e "ssh -i $DEPLOY_KEY" \ --exclude-from=deploy/rsync-exclude.txt \ ./ "$REMOTE:$DEPLOY_PATH/"
여기서 --delete가 무섭다. 없으면 지운 파일이 서버에 영원히 남고, 있으면 경로 하나 잘못 적었을 때 서버 폴더가 통째로 비워진다.
.env, uploads/, node_modules/, .git/은 제외 목록에 넣었다. rsync는 제외한 경로를 지울 대상에서도 빼 준다. 이걸 빼먹으면 첫 배포에서 사용자가 올린 파일이 전부 사라진다. 서버에만 있는 파일이기 때문이다.
경로도 검사한다. 배포 경로가 홈 디렉터리나 루트면 스크립트가 거부하고, 대상 폴더가 비어 있거나 package.json이 있을 때만 진행한다. 오타 하나로 엉뚱한 폴더를 가리켰을 때, 그 안의 남의 파일을 지우지 않으려고.
case "$DEPLOY_PATH" in ""|/|/root|/home|"/home/$DEPLOY_USER") echo "위험한 경로"; exit 1 ;; esac
터미널에서는 되던 node가
스크립트에서 ssh로 명령을 보내면 .bashrc가 초반에 return해 버려서 nvm이 안 읽힌다. 터미널에서 멀쩡하던 node가 스크립트에서는 command not found가 된다. 원격 명령 첫 줄에서 nvm.sh를 직접 읽게 했다. 지금 서버는 apt로 깐 Node라 상관없지만, 언젠가 nvm으로 옮길 걸 알아서 미리 넣었다.
DB 마이그레이션도 배포에 넣었다. 댓글 테이블을 만들면서 CREATE TABLE IF NOT EXISTS를 실행하는 스크립트를 만들고, npm install 다음에 매번 돌게 했다. 여러 번 돌아도 안전하니까. "코드는 올라갔는데 테이블이 없어서 500"은 손으로 배포하던 시절에 실제로 겪은 일이다.
재시작은 restart 대신 reload를 쓴다. restart는 프로세스를 죽였다가 띄우는 사이에 502가 난다. reload는 새 프로세스를 띄운 뒤 옛 것을 내려서 끊기는 시간이 훨씬 짧다.
하나 더. 배포할 때마다 npm이 EACCES 경고를 잔뜩 냈다. 예전에 sudo npm install을 한 번 한 탓에 node_modules 안에 root 소유 폴더가 열몇 개 남아 있었다. chown 한 줄이면 끝날 일을 몇 달 동안 몰랐다. 경고는 늘 거기 있었는데 아무도 안 읽었다. 나도 안 읽었다.
혼자 운영하면 배포를 봐 줄 사람이 없다. 이 스크립트가 지금은 그 사람 대신이다. 다음 숙제는 이 녀석이 경고까지 읽게 만드는 일이다.
댓글 0