이번 프로젝트는 MSA 아키텍처로 구성되어 있으며, 각 서비스는 도커 이미지로 빌드되어 쿠버네티스 클러스터에 배포됩니다. 기존에는 DockerHub를 통해 이미지를 관리했지만, 보안 강화를 위해 Kakao Cloud Container Registry로 전환했습니다.
😚 이번 글에서는 DockerHub에서 KakaoCloud Container Registry로 마이그레이션한 과정을 공유합니다.

먼저 카카오클라우드 콘솔에 접속해 Container Registry를 생성합니다.
1) 카카오클라우드 콘솔 접속
2) Container Pack → Container Registry 메뉴 이동
3) 리포지토리 생성
주요 설정
태그 덮어쓰기
이미지 스캔 설정
Kakao Cloud Container Registry는 Private Registry이기 때문에, 이미지를 Push하거나 Pull하려면 인증이 필요합니다. 이를 위해 IAM 액세스 키를 발급해야 합니다.
1) 카카오클라우드 콘솔에서 자격 증명 → 액세스 키 메뉴로 이동

2) IAM 액세스 키 생성

Container Registry는 Docker CLI를 통해 인증한 사용자만 접근할 수 있습니다. 발급받은 IAM 액세스 키를 사용해 도커에 로그인합니다.
⚠️ 도커가 로컬에 설치되어 있어야 합니다. 설치가 필요한 경우 도커 공식 문서를 참고하세요.
로그인 명령어
docker login <레지스트리 URL> \
--username <IAM 액세스 키 ID> \
--password <보안 액세스 키>

참고로 사용 가능한 명령어와 옵션은 Container Registry 커맨드 보기에서 확인할 수 있습니다.

기존 DockurHub 워크플로우
- name: Log in to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build Docker image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/playus-match-service:${{ env.BASE_TAG }} \
-t ${{ secrets.DOCKER_USERNAME }}/playus-match-service:${{ env.BUILD_VERSION }} .
- name: Push Docker images
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/playus-match-service:${{ env.BASE_TAG }}
docker push ${{ secrets.DOCKER_USERNAME }}/playus-match-service:${{ env.BUILD_VERSION }}
카카오클라우드 Container Registry로 수정
# 카카오 클라우드 Container Registry 로그인
- name: Log in to Kakao Cloud Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.KCR_REGISTRY_URL }}
username: ${{ secrets.KCR_ACCESS_KEY_ID }}
password: ${{ secrets.KCR_SECRET_ACCESS_KEY }}
- name: Build Docker image
run: |
docker build -t ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BASE_TAG }} \
-t ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BUILD_VERSION }} .
- name: Push Docker images
run: |
docker push ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BASE_TAG }}
docker push ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BUILD_VERSION }}
GitHub Secrets 변경
KCR_REGISTRY_URL = <레지스트리 URL>
KCR_ACCESS_KEY_ID = <IAM 액세스 키 ID>
KCR_SECRET_ACCESS_KEY = <보안 액세스 키>
✅ 빌드 및 푸시 성공


카카오클라우드 Container Registry는 Private Registry이기 때문에, 쿠버네티스에서도 인증 정보를 통해 이미지를 Pull해야 합니다.
1) ImagePullSecret 생성
아래 명령어를 통해 K8s 네임스페이스에 도커 인증 정보를 등록합니다.
kubectl create secret docker-registry kcr-secret \
--docker-server=<레지스트리 URI> \
--docker-username=<IAM 액세스 키 ID> \
--docker-password=<보안 액세스 키> \
-n <네임스페이스>
‼️ 이 시크릿은 이후 Deployment에 명시적으로 연결해야 이미지 Pull이 가능합니다.
2) Deployment 설정 수정
기존 이미지 설정
spec:
template:
spec:
containers:
- name: match-service
image: yukyung0/playus-match-service:latest
카카오클라우드 Registry로 변경
spec:
template:
spec:
imagePullSecrets:
- name: kcr-secret
containers:
- name: match-service
image: chunsam.kr-central-2.kcr.dev/playus-match-service/match-service:latest
이미지를 Pull하지 못하고 ImagePullBackOff 오류가 발생하였습니다.

처음에는 시크릿을 생성했지만, Deployment에 imagePullSecrets 설정을 누락해 이미지 Pull에 실패했습니다. Private Registry를 사용할 때는 시크릿 생성 + Deployment에 연결 이 두 단계를 모두 꼭 확인해야 합니다!
# 현재 Deployment 설정 확인
kubectl describe deployment match-service -n dev-match-service
# imagePullSecrets 누락 시 패치 적용
kubectl patch deployment match-service -n dev-match-service \
-p '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"kcr-secret"}]}}}}'
🥳 성공

name: Build and Push Docker Image
on:
push:
branches:
- main
- develop
workflow_dispatch: # 수동 실행 허용
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build with Gradle
uses: gradle/gradle-build-action@v2
with:
arguments: clean bootJar
# 카카오 클라우드 Container Registry 로그인
- name: Log in to Kakao Cloud Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.KCR_REGISTRY_URL }}
username: ${{ secrets.KCR_ACCESS_KEY_ID }}
password: ${{ secrets.KCR_SECRET_ACCESS_KEY }}
- name: Set Docker image tags
run: |
BRANCH_NAME=${GITHUB_REF##*/}
SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-7)
BUILD_VERSION=${{ github.run_number }}-${SHORT_SHA}
if [[ "$BRANCH_NAME" == "main" ]]; then
echo "BASE_TAG=latest" >> $GITHUB_ENV
elif [[ "$BRANCH_NAME" == "develop" ]]; then
echo "BASE_TAG=dev" >> $GITHUB_ENV
fi
echo "BUILD_VERSION=$BUILD_VERSION" >> $GITHUB_ENV
- name: Build Docker image
run: |
docker build -t ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BASE_TAG }} \
-t ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BUILD_VERSION }} .
- name: Push Docker images
run: |
docker push ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BASE_TAG }}
docker push ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BUILD_VERSION }}
- name: Update patch-image.yaml
if: success()
run: |
BRANCH_NAME=${GITHUB_REF##*/}
if [[ "$BRANCH_NAME" == "main" ]]; then
K8S_BRANCH="main"
elif [[ "$BRANCH_NAME" == "develop" ]]; then
K8S_BRANCH="develop"
fi
git clone --single-branch --branch "$K8S_BRANCH" https://x-access-token:${{ secrets.K8S_REPO_TOKEN }}@github.com/KEA-ChunSam/PlayUs-k8s.git
if [[ "$BRANCH_NAME" == "main" ]]; then
echo "Skipping main branch update (prod) for now"
elif [[ "$BRANCH_NAME" == "develop" ]]; then
sed -i "/name: match-service/{n;s|image: .*|image: ${{ secrets.KCR_REGISTRY_URL }}/playus-match-service/match-service:${{ env.BUILD_VERSION }}|}" PlayUs-k8s/overlays/develop/match-service/patch-image.yaml
fi
cd PlayUs-k8s
git config user.name "github-actions"
git config user.email "github-actions@github.com"
# 변경사항 있으면 커밋, 없으면 빈 커밋 생성
if [[ -n "$(git status --porcelain)" ]]; then
git add .
git commit -m "Update match-service image to ${{ env.BUILD_VERSION }} on $BRANCH_NAME"
else
echo "No changes detected, creating empty commit to trigger deploy"
git commit --allow-empty -m "Update match-service image to ${{ env.BUILD_VERSION }} on $BRANCH_NAME"
fi
git push https://x-access-token:${{ secrets.K8S_REPO_TOKEN }}@github.com/KEA-ChunSam/PlayUs-k8s.git