Docker
Docker rollback을 위해 이전 이미지를 남겨두기
배포 후 문제가 생기면 빨리 이전 버전으로 돌아가야 한다. 그럴 때 이미지가 없으면 곤란하다.
배포 후 문제가 발생하면, 가장 빠른 해결책은 이전 버전으로 돌아가는 것이다. 그런데 Docker 이미지를 지워버렸다면? 다시 빌드해야 하고, 그 사이에 서비스는 다운된다.
문제: 이미지 정리 과다
# 배포 후 이미지를 깔끔하게 하려고...
docker image prune -a --force
# → 모든 이미지 삭제!
# 문제 발생
docker run myapp:v1.0 # 이미지 없음!
운영 중에 이런 일이 생기면 서비스 복구가 매우 어렵다.
해결책: 이미지 태그 전략
기본 원칙: 최소 2개의 이미지를 항상 보관
# 현재 배포된 이미지
myapp:latest
# 이전 배포 이미지
myapp:v1.0
myapp:previous
# 개발 이미지
myapp:dev
myapp:staging
1단계: 새 버전으로 빌드
docker build -t myapp:v1.1 .
2단계: 기존 이미지를 previous 태그로 백업
# 현재 latest가 뭔지 확인
docker images myapp | grep latest
# 현재 latest를 previous로 태그
docker tag myapp:latest myapp:previous
3단계: 새 이미지를 latest로 배포
docker tag myapp:v1.1 myapp:latest
docker push myapp:latest
# 또는 Docker Compose
docker compose up -d
4단계: 문제 발생시 빠른 롤백
# previous로 돌아가기
docker tag myapp:previous myapp:latest
# 컨테이너 재시작
docker compose up -d
# 또는 Swarm/Kubernetes
docker service update myapp --image myapp:previous
Docker Compose 예시
version: '3.8'
services:
myapp:
image: myapp:latest
container_name: myapp_prod
ports:
- "3000:3000"
environment:
NODE_ENV: production
restart: always
배포 스크립트
#!/bin/bash
# 1. 현재 이미지를 previous로 백업
echo "Backing up current image..."
current=$(docker images myapp | grep latest | awk '{print $3}')
if [ ! -z "$current" ]; then
docker tag myapp:latest myapp:previous
fi
# 2. 새 이미지 빌드
echo "Building new image..."
docker build -t myapp:latest .
# 3. 컨테이너 시작
echo "Starting container..."
docker compose up -d
# 4. 헬스 체크
echo "Health check..."
sleep 5
curl -f http://localhost:3000/health || {
echo "Health check failed! Rolling back..."
docker tag myapp:previous myapp:latest
docker compose up -d
exit 1
}
echo "Deployment successful!"
Kubernetes 배포
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 3000
targetPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1.1
ports:
- containerPort: 3000
롤백
# 이전 버전 확인
kubectl rollout history deployment/myapp
# 롤백
kubectl rollout undo deployment/myapp
# 또는 특정 버전으로
kubectl rollout undo deployment/myapp --to-revision=2
저장소 관리
로컬 저장소에는 최소 2-3개 버전을 유지하자.
# 이미지 목록
docker images myapp
# 결과:
# REPOSITORY TAG IMAGE ID CREATED
# myapp latest abc123... 5 minutes ago
# myapp v1.1 abc123... 5 minutes ago
# myapp v1.0 def456... 2 days ago
# myapp previous def456... 2 days ago
불필요한 이미지만 정리
# dangling 이미지만 삭제 (안전)
docker image prune -f
# 특정 버전 삭제
docker rmi myapp:v0.9
# 모든 이미지 삭제 (위험!)
docker image prune -a -f # 하지 말 것!
레지스트리에 보관
Docker Hub나 Private Registry에도 여러 버전을 보관하면 더 안전하다.
# 빌드 및 푸시
docker build -t myregistry.azurecr.io/myapp:v1.1 .
docker push myregistry.azurecr.io/myapp:v1.1
# 태그도 푸시
docker tag myregistry.azurecr.io/myapp:v1.1 myregistry.azurecr.io/myapp:latest
docker push myregistry.azurecr.io/myapp:latest
# 롤백할 때 레지스트리에서 가져오기
docker pull myregistry.azurecr.io/myapp:v1.0
docker run myregistry.azurecr.io/myapp:v1.0
모니터링 및 자동 롤백
배포 후 문제를 감지하면 자동 롤백하는 게 가장 좋다.
#!/bin/bash
# 배포
docker compose up -d
# 헬스 체크 (반복)
for i in {1..30}; do
if curl -f http://localhost:3000/health >/dev/null 2>&1; then
echo "✓ Health check passed"
exit 0
fi
echo "Waiting for service... ($i/30)"
sleep 2
done
# 30초 후에도 실패면 롤백
echo "✗ Service failed to start, rolling back..."
docker tag myapp:previous myapp:latest
docker compose up -d
exit 1
정리
Rollback은 배포 전략의 가장 중요한 부분이다. 항상 이전 버전의 이미지를 보관하고, 배포 후 헬스 체크를 실행하고, 문제시 빠르게 롤백할 수 있게 준비하자. 시간이 걸리지 않는 롤백이 최고의 장애 대응이다. "배포 1시간, 정상 확인 1분, 롤백 30초" 이 정도면 충분한 준비다.