
Git Hub Action + Docker + AWS (ec2 + RDS)
위 환경에서 서버를 자동배포하며 만난 에러를 해결한 내용을 정리한다.
여기서 도커 로그 확인해볼 생각안하고 ec2 인바운드 규칙만 계속 바꿔준게 ㄹㅇ 실수였다.
환경변수도, 앤드포인트도, 포트 열어주는것도 다 제대로 했는데 왜!!
결국엔 관련해 구글링을 미친듯이 하다가, 어떤 블로그 글을 보고 아!! 왜 도커 실행중인걸 확인할 생각을 안했지? 하면서
1. docker ps # 현재 실행중인 컨테이너를 확인한다.
# 근데 여기서 나는 아무것도 안떴다..
2. docker ps -a #종료된거까지 확인해줬다.
이 명령어들을 실행시켰다.
docker ps -a 입력하니까 종료되었다고 나왔고,
docker logs {컨테이너 이름}
//만약 해당 컨테이너의 로그가 많아서 모두 보기 어려울 경우, -f 옵션을 사용하여 로그를 실시간으로 보거나, --tail 옵션을 사용하여 최근 로그 몇 줄만 보는 것도 가능하다.
이걸로 로그 확인해주니까
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [org.springframework.boot.context.config.ConfigDataProperties]
이런 이유를 뱉어줬다.
찾아보니까 프로퍼티 설정을 안해줘서 생긴거라는데, 나는 server로 확실하게 설정해줬단 말이다...
설정해둔 환경변수 싹 확인하고 (띄어쓰기 같은 문제로 안될까바..) 그래도 안된다.
결국 거의 반나절을 찾아해멘 결과..
도커 이미지가 실행될 때 환경변수가 주입이 안되어서 그렇다..
과정을 다시 생각해보니까 빌드할 때만 알려주고 도커 이미지는 내가 안알려줘서 환경변수로 처리한것들 뭔지 모를텐데.. 내가 그냥 run 시켜서 서버가 꺼졌구만.. 하는 생각이 들었다.
도커 이미지를 실행시키기위해 -e로 환경 변수를 주입해줘야겠다! 하는 생각으로 workflow를 아래와 같이 구성했다.
- name: Deploy to Server
run: |
aws ssm send-command \
--instance-id {Ec2 id} \
--document-name "AWS-RunShellScript" \
--parameters "commands=[
'if sudo docker ps -a --format \\'{{.Names}}\\' | grep -q \'^server$\\'; then',
' sudo docker stop server',
' sudo docker rm server',
'fi',
'sudo docker pull ${{secrets.DOCKER_HUB_USERNAME}}/spring-cicd:${GITHUB_SHA::7}',
'sudo docker run -d --name server -p 8080:8080 \
-e AWS_ACCESS_KEY=${{secrets.AWS_ACCESS_KEY}} \
-e AWS_SECRET_ACCESS_KEY=${{secrets.AWS_SECRET_ACCESS_KEY}} \
-e DOCKER_HUB_PASSWORD=${{secrets.DOCKER_HUB_PASSWORD}} \
-e DOCKER_HUB_USERNAME=${{secrets.DOCKER_HUB_USERNAME}} \
-e JWT_SECRET_KEY=${{secrets.JWT_SECRET_KEY}} \
-e MYSQL_DATABASE_PASSWORD=${{secrets.MYSQL_DATABASE_PASSWORD}} \
-e MYSQL_DATABASE_URL=${{secrets.MYSQL_DATABASE_URL}} \
-e MYSQL_DATABASE_USERNAME=${{secrets.MYSQL_DATABASE_USERNAME}} \
-e KAKAO_CLIENT_ID=${{secrets.KAKAO_CLIENT_ID}} \
-e KAKAO_CLIENT_SECRET=${{secrets.KAKAO_CLIENT_SECRET}} \
spring-cicd'
]"
이렇게 깃헙 레파지토리에 환경변수로 넣어놓고 workflow에서 도커 이미지를 실행시킬 때 넣어줬다.
그러니까 성공!
하지만, 나중에 알게된 것인데 이렇게 넣어주는건 보안에 굉장히 취약해서 현업에서는 사용하지 않는 방식이라고 했다.
나도 이렇게 서버를 운영하다보니 하나하나 환경변수 확인해주고, 변수 이름 하나라도 잘못되면 서버가 배포안되는 문제를 겪으니 아 이거 빨리 고쳐야겠다.. 정석을 찾자! 해서 고치려한다 (이건 다른 게시물에서...)
S3 버킷과 연결하기위해 AWS와 연결하는 코드를 추가했는데, 이걸 추가하고 액션을 실행하니..
ServerApplicationTests > contextLoads() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
FAILURE: Build failed with an exception.
이렇게 에러가 발생했고, 찾아보니 프로퍼티 실행할 때 생기는 오류라고했다.
프로퍼티 관련해서 오류가 생길게 (최근에 변경된거 ㅎ) AWS 액세스 키를 환경변수 처리한거밖에 없었다.
AwsConfig 클래스에서 이 환경변수로 처리한 액세스 키값을 받아와서 처리하도록 로직을 짰는데, 값이 뭔지 받아오질 못하니생긴 문제라고 판단했다.
근데?! 이 키값은 깃헙에 못올린다. .gitignore 처리를 해서 올려도 깃에 없으니까 액션이 못읽는건 똑같을거고 그럼 대체 어떻게 처리하냐..
(이럴때 제일 답답하다. 왜그러는지 이유를 알거같은데 해결방법을 모르겠다는거..)
그래도 이유가 어느정도 명확해지니까 관련해서 구글링을 또 뒤지게해서.. 해결 방법을 찾아냈다!
on:
push:
branches: [main]
paths:
- 'server/**'
jobs:
server:
runs-on: ubuntu-latest
env: #여기!!!
AWS_ACCESS_KEY: ${{secrets.AWS_ACCESS_KEY}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
JWT_SECRET_KEY: ${{secrets.JWT_SECRET_KEY}}
KAKAO_CLIENT_ID: ${{secrets.KAKAO_CLIENT_ID}}
KAKAO_CLIENT_SECRET: ${{secrets.KAKAO_CLIENT_SECRET}}
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'zulu'
- name: Grant execute permission for gradlew
working-directory: ./server
run: chmod +x gradlew
- name: Build with Gradle
working-directory: ./server
run: ./gradlew build
workflow에서 빌드 실행전에 환경변수가 뭔지 알려줬다.
이렇게 돌리고, 도커 이미지에도 추가되는 AWS 액세스 키값을 알려주니까 작동했다!!
(사실 안됐다. 환경변수까지 넣어줬는데 왜 안돼..하면서 울기 직전에 구글링해보니까 어떤 글에서 재부팅해주니까 됐다는 글을보고 나도 EC2 재부팅하고 다시 workflow 실행하니까 됐다...)
환경변수에관해서 너무 에러를 많이 만나고, 내가생각해도 이렇게 관리하면 안될거같아서 멘토님한테 여쭤보니,
사이드 프로젝트에서는 민감한 정보인 application-server.yml 같은 경우 직접 업로드를 통해 관리하여 volume mount 하는 것이 좋을 듯 싶습니다.
라고 답해주셨다. 더 길게 많은 정보를 주셨지만 이글에서 필요한건 이 내용일거같아서 요약했다.
그냥 결론은.. 빌드-배포과정에서 관리해야하는 정보들을 따로 관리하고 각 과정에서 따로 주입해줘야겠다는 생각을 했다.
이것도 다른 게시물에서..