본문 바로가기
Server/🐳 Docker

[Docker] Docker Hub 이용해서 CD 환경 구축 시 최신 이미지 미적용 문제 해결하기

by 코딩하는 동현😎 2025. 1. 24.

 

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

반응형

댓글