1. 문제 상황
github actions를 이용해서 CI/CD 환경을 만들었고, push 또는 pull_request 할때마다 docker hub에 push하고 받아와서 베포 자동화 환경을 만들었다.
push할때마다 정상적으로 베포가 되고 동작하고, docker ps 명령으로 새로 docker 컨테이너가 의도할때마다 생성되는것을 보고 문제 상황을 인식하기가 쉽지 않았다.
베포한 프로젝트도 정상적으로 동작하지만, 최근 커밋만 적용이 안되는 상황이라 pull이 누락됐을것이라고 생각을 못했고, 프로젝트 코드에 문제가 있다고 생각하여 무의미한 삽질만 이어나갔다.
이용했던 cd workflow
name: CD with Gradle and Docker for Producer and Consumer
on:
push:
branches:
- 'main'
- 'develop' # Push 이벤트에 대한 브랜치 트리거 설정
pull_request:
branches:
- 'main'
- 'develop' # PR 이벤트에 대한 브랜치 트리거 설정
permissions:
contents: read
jobs:
build-and-deploy:
runs-on: ubuntu-latest # 워크플로 실행 환경
steps:
- uses: actions/checkout@v4 # 레포지토리 체크아웃
- name: ☕️ Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for Gradlew
run: chmod +x ./gradlew # Gradle Wrapper 실행 권한 부여
- name: 🐘 Build Producer with Gradle
run: ./gradlew :producer:clean :producer:build -x test --stacktrace
- name: 🐘 Build Consumer with Gradle
run: ./gradlew :consumer:clean :consumer:build -x test --stacktrace
- name: 💣 Build and Push Docker Images
run: |
docker login -u <DOCKER_USERNAME> -p <DOCKER_PASSWORD> # Docker Hub 로그인 (사용자명/비밀번호 환경 변수로 대체)
docker build -f ./producer/Dockerfile -t <DOCKER_USERNAME>/producer:latest ./producer
docker build -f ./consumer/Dockerfile -t <DOCKER_USERNAME>/consumer:latest ./consumer
docker push <DOCKER_USERNAME>/producer:latest
docker push <DOCKER_USERNAME>/consumer:latest
- name: 🚀 Deploy without Docker Compose
uses: appleboy/ssh-action@master
with:
host: <EC2_HOST> # EC2 호스트 정보
username: <EC2_USERNAME> # EC2 사용자명
key: <EC2_PRIVATE_KEY> # EC2 개인 키
port: <EC2_PORT> # EC2 포트
script: |
echo "Uploading environment variables to EC2"
# EC2 내부에서 작업 수행
ssh -o StrictHostKeyChecking=no -i <PRIVATE_KEY_PATH> <EC2_USERNAME>@<EC2_HOST> << 'EOF'
echo "Writing environment variables to .env"
echo "SPRING_DATASOURCE_DRIVER_CLASS_NAME=<DB_DRIVER>" > .env # DB 환경 변수 설정
echo "Stopping and removing existing containers"
sudo docker stop producer || true # 기존 컨테이너 정지
sudo docker rm producer || true # 기존 컨테이너 제거
sudo docker stop consumer || true
sudo docker rm consumer || true
echo "Running Producer container"
sudo docker run -d --name producer -p 8080:8080 \
--env-file .env \
<DOCKER_USERNAME>/producer:latest # Producer 컨테이너 실행
echo "Running Consumer container"
sudo docker run -d --name consumer -p 8081:8081 \
--env-file .env \
<DOCKER_USERNAME>/consumer:latest # Consumer 컨테이너 실행
echo "Cleaning up unused Docker images"
sudo docker image prune -f # 사용하지 않는 Docker 이미지 정리
EOF
2. 원인
CD를 위해 docker hub으로 images를 push는 하고 있었으나, pull하고 docker를 실행시키지 않았다.
아래 명령어로는 기존에 이미지가 없을때는 이미지를 pull 하나, 기존에 이미지가 있을땐 pull을 하지 않는 문제다.
아래 명령어 같은 경우에 image에 존재하지 않으면 pull을 정상적으로 받지만, 이미지가 이미 받아온 상태인 경우 pull하지 않고 이미지를 실행시키기만 한다.
echo "Running Producer container"
sudo docker run -d --name producer -p 8080:8080 \\
--env-file .env \\
${{ secrets.DOCKER_USERNAME }}/roomie-producer:latest
echo "Running Consumer container"
sudo docker run -d --name consumer -p 8081:8081 \\
--env-file .env \\
${{ secrets.DOCKER_USERNAME }}/roomie-consumer:latest
중요!
docker images 명령어를 사용하면 보유 이미지와 마지막으로 pull한 시간이 보인다. (docker ps가 아닌)
만약에 의도한 시간이랑 다를시 docker push한것을 pull 했는지 확인해야된다.
위 같은 경우 12시간 전 받아온 이미지라는것을 확인할 수 있다.
docker ps로 컨테이너 조회했을때 방금 실행 됐다고 해도, docker images로 컨테이너가 아닌 이미지가 최근에 받아온것인지 확인해야한다
3. 해결
workflow 수정
CD workflow에서 run하기 전에 아래 workflow를 중간에 추가해서 pull하도록 작성
echo "Pulling the latest Producer image"
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/roomie-producer:latest
echo "Pulling the latest Consumer image"
sudo docker pull ${{ secrets.DOCKER_USERNAME }}/roomie-consumer:latest
workflow 없이 바로 pull 하고 싶다면 pull 명령어 입력
sudo docker pull <도커hub 사용자 id>/<이미지 레포 이름>
4. 해결이 안된다면?
pull은 했어도 push를 안한것은 아닌지 확인해볼 필요가 있다.
docker hub으로 가서 해당 레포를 조회한다.
last pushed의 시간이 자신이 의도한 시간인지 확인해볼 필요가 있다.
해결
workflow 수정
CD workflow에서 run하기 전에 아래 workflow를 중간에 추가해서 pull하도록 작성
- name: 💣 Build and Push Docker Images
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -f ./producer/Dockerfile -t ${{ secrets.DOCKER_USERNAME }}/roomie-producer:latest ./producer
docker build -f ./consumer/Dockerfile -t ${{ secrets.DOCKER_USERNAME }}/roomie-consumer:latest ./consumer
docker push ${{ secrets.DOCKER_USERNAME }}/roomie-producer:latest
docker push ${{ secrets.DOCKER_USERNAME }}/roomie-consumer:latest
workflow 없이 바로 push하고 싶다면 아래 명령으로 로컬에서 build후 push
레포 이름이 producer, consumer라고 가정하고 작성한 명령어입니다.
docker build -f ./producer/Dockerfile -t <DOCKER_USERNAME>/producer:latest ./producer
docker build -f ./consumer/Dockerfile -t <DOCKER_USERNAME>/consumer:latest ./consumer
docker push <DOCKER_USERNAME>/producer:latest
docker push <DOCKER_USERNAME>/consumer:latest
'Server > 🐳 Docker' 카테고리의 다른 글
[Docker] GitHub Actions와 Docker Hub를 이용해 CI/CD 환경 구축하기 (0) | 2025.01.24 |
---|
댓글