2024. 9. 25. 21:15ㆍ카테고리 없음
DOCKER + EC2 + CI/CD
프로젝트 서버를 배포할때 cicd를 활용하여서 무중단 배포를 구축하려고 하였습니다.
- ec2는 다양한 인스턴스 유형을 제공해주기에, 트래픽 증가에 따라서 리소스를 확장함에있어 유리합니다.
- docker는 애플리케이션을 컨테이너화 하여서 개발 환경과 동일한 조건에서 배포할 수 있어서 환경 차이에 따른 문제를 방지할 수 있으며, 컨테이너는 경량화가 되어있기에 애플리케이션을 신속하게 배포할 수 있으며, 새로운 버전으로 쉽게 교체가 가능합니다.
- CI/CD 를 통하여 코드변경이 감지될때마다 자동으로 테스트 및 통합이 진행되어서 지속적인 통합을 할 수 있고, 지속적인 자동 배포를 통하여 새로운 기능이나 버그 수정을 빠르게 재배포 할 수 있습니다.
위에 같은 이점들로 인하여 이 방법을 선택하여서 배포를 진행해주었습니다.
EC2
우선 AWS EC2를 생성해줍니다.
다음으로 프리티어가 사용 가능한 t2 micro로 설정을 해주고 키페어도 새로 생성해주었습니다.
( 저는 .pem으로 사용하였지만 만약 PUTTY를 사용하신다면 ppk로 하시면 됩니다. )
다음으로는 보안그룹을 설정해준후 인스턴스를 시작해줍니다.
다음으로는 탄력적 ip주소를 할당해줍니다.
이제 이 탄력적 ip주소에 아까 만들었던 인스턴스를 연결해줍니다.
그럼 인스턴스에서 확인시 퍼블릭 IPv4 주소가 확인이 됩니다.
ssh 접속
그럼 이제 다음으로 ssh 접속 설정을 해줄것입니다.
저는 mac을 사용중이니 터미널로 진행하겠습니다.
아까 만들어줬던 키페어를 ~/.ssh 폴더로 옮겨줍니다.
다음으로 ~/.ssh 폴더에서 config 파일을 만들어줍니다.
Host 원하는 이름
HostName 퍼블릭IP 주소
User ec2-user
IdentityFile ~/.ssh/{키페어}
로 설정해줍니다.
다음으로는 키에 권한을 부여해줍니다.
다음로는 ssh 접속을 실행해줍니다.
그럼 ssh 접속이 잘된걸 확인 할 수 있습니다.
다음으로는 id와 password를 설정해주겠습니다.
이제 id와 password연결을 허용시켜주겠습니다.
sshhd_config 파일로 들어가서
/Password를 통해 비밀번호를 허용해주는 부분을 찾습니다
그 후 no로 되어있던 부분(PasswordAuthentication)은 yes로 수정해주고 저장 후 나와줍니다.
그 후 sshd를 재시작해줍니다.
docker install
도커를 설치해줍니다.
sudo yum install docker
다음으로 서버에 도커를 실행시켜둡니다.
docker token
도커 허브에 들어가 로그인 후 myaccount에서 security 탭에서 new accesstoken을 통해 새로운 토큰을 발급받아줍니다.
이때 생성된 토큰은 생성직후 볼 수 없으므로 다른데에 복사해놔서 저장해둡니다.
AWS RDS 생성
RDS는 aws에서 제공하는 관계형 데이터베이스 서버입니다.
템플릿은 프리티어로 설정해줍니다.
마스터 암호는 기억해주고 있어야 합니다.
만약 EC2에 직접 연결하면, EC2에서만 데이터베이스에 접근할 수 있는 보안으룹으로 설정되므로 EC2 컴퓨팅 리소스에 연결 안함을 선택해줍니다.
또한 외부에서 RDS에 접근이 가능하도록 퍼블릭 엑세스 설정을 예로 해줍니다.
이렇게 설정을해준후 나머지는 그대로 건들지말고 데이터베이스를 생성해줍니다.
생성되면 이렇게 엔드포인트가 나오게되는데 이것으로 DB를 접속해주는 것입니다.
해당 엔드포인트를 application.yml에 적용해줍니다.
username: admin
password는 아까 지정해준 마스터 암호를 입력해줍니다.
다음으로는 rds를 인텔리제이에서 testConnection으로 연결해줍니다.
( 주의!! 이때 저는 보안그룹 설정시 인바운드 규칙에서 IPv4의 모든 트래픽을 허용하는 인바운드 규칙을 설정안해놔서 rds testConnection 당시 에러가 났습니다. )
Github Action Secret
깃허브에서 배포하려는 레포지토리의 설정에 Secret and variables에서 action으로 들어가줍니다.
다음으로는 github repository secret을 설정해줍니다.
여기서 이름과 내용을 적어 secret을 추가해줍니다.
DOCKERHUB_IMAGENAME : 도커 이미지 이름 ( 원하는 이름 입력 )
DOCKERHUB_USERNAME : 도커 허브 닉네임
DOCKERHUB_TOKEN : 좀 전에 도커 허브에서 발급받았던 토큰
EC2_USERNAME : ec2-user
EC2_PASSWORD : 서버에서 설정했던 비밀번호
EC2_HOST : 퍼블릭 IP
EC2_SSH_PORT : 22
APPLICATION_YML : application.yml 파일 내용 ( yml이 바뀔때마다 수동으로 업데이트 시켜줘야합니다. )
Dockerfile
최상단에 도커 파일을 만들어줍니다.
도커 파일에는 해당 내용들을 적어줍니다.
1 - 자바 17 환경
2 - jar file 가져오기
3 - jar file을 app.jar로 복사하기
4 - app.jar을 실행시키기
주의 사항
하지만 원래 gradle build task를 진행하면 builds/libs 폴더에 jar 파일이 두개가 나옵니다.
실행가능한 jar파일은 SNAPSHOT 과 실행이 불가능한 jar파일인 SNAPSHOT-plain이 나옵니다.
하지만 2번째 줄을 보시면 jar파일을 가져오라는데 jar파일이 두개이므로 에러가 날 수 있습니다.
해당 에러를 해결하기위해 build.gradle 파일에 추가시켜줍니다.
( gradle build시 plain을 제외한 jar 파일 하나만 나옵니다. )
github action script
깃허브에서 cicd용으로 추가해준 서비스로, 레포지토리에 어떤 이벤트가 발생되면 특정 작업이 일어나는 script를 작성할 수 있습니다.
.github/workflows 폴더에 yml 파일로 스크립트을 작성합니다.
이 스크립트의 실행은 github action 내에 가상환경 runner가 실행시켜주거나 내가 실행시킬 환경을 지정하고 접속하여 스크립트를 실행할 수 있습니다.
레포지토리의 액션 탭에서 java with gradle을 선택해줍니다.
저는 개인프로젝트를 진행중이라 main에서 작업중이니 브랜치는 main으로 설정해줄것이고, 이름은 cicd.yml로 바꿔주겠습니다.
다음으로는 기존에 있던 yml파일을 다 지우고 원하는 script를 작성해줍니다.
( 저는 main 브랜치에 코드가 push 될때마다 동작이 되게 하였습니다. 협업시에는 따로 develop 브랜치를 만들어서 해당 브랜치에 코드가 머지될때 동작하게끔 해야합니다. )
다 만든후 commit directly해줍니다.
그럼 action에서 스크립트가 실행되는것이 나옵니다.
( 저는 스크립트 실행중 자꾸 밑에 에러가떠서 많은 삽질을 해본 결과 dockerimagename문제였습니다 꼭 소문자로 지정해주세요..ㅠㅠ )
ERROR: invalid tag "***/***": repository name must be lowercase
Error: Process completed with exit code 1.
그렇다면 이제 컨테이너가 잘 실행되고있는지 터미널에서 확인해줍니다.
도커 이미지가 실행되었지만 종료되었다는걸 볼 수 있습니다.
에러를 확인하기위해 도커 로그를 확인해줍니다.
에러 확인
에러를 확인해보니 저는 build폴더의 무존재로 인하여 에러가났고 이 부분은 아까 설정해줬던 gradle파일에서 jar 파일을 생성하지않겠다는 옵션을 주석처리해주고 다시 build하여서 해결하였습니다.
이 부분에서 snapshot 파일을 깃허브에 올리려고 하니 깃허브의 한번의 최대 푸시 용량이 초과된다는 에러를 발견하였고 이 부분에서
git config --global http.postBuffer 524288000
이와같이 깃허브 버퍼를 늘려주어서 해결 하였습니다.
또한 프로젝트 환경변수 설정시 프로젝트 폴더이름을 한번 바꿨습니다. 따라서 해당 환경변수들이 제대로 들어가지않아 해당 에러를 해결해주었고, yml 작성시 기재해두었던 변수들이 Value어노테이션에 제대로 들어가지않아 해결해주었습니다.
다음으로는 현재 http로 배포가 된 상황이므로 ssl 인증서를 받은 후, https로 접근이되게 해주고 도메인을 직접 라우팅 시켜주겠습니다.