1일차: 클라우드 및 Docker 개념 학습
클라우드 컴퓨팅이 필요한 이유
- 비용절감
- 하드웨어 및 소프트웨어를 구입하고 데이터 센터 설치 및 운영 비용을 줄일 수 있습니다.
- 서버 랙, 전원 및 냉각에 사용되는 전기료, 인프라 관리를 위한 IT 전문가 인건비 등도 절약됩니다.
- 속도향상
- 주문형 셀프서비스로 제공되기 때문에 다양한 컴퓨팅 리소스를 몇번의 마우스 클릭으로 설정할 수 있습니다.
- 확장성
- 필요할 때 적절하게 스토리지, 네트워크 대역폭 등 IT 자원을 확장할 수 있습니다.
- 생산성
- 일반적인 온사이트 데이터센터에서는 하드웨어 설치, 소프트웨어 패치 및 시간이 오래걸리는 IT 운영 작업이 필요하지만, 클라우드 컴퓨팅을 사용하면 이 모든게 불필요해지므로 IT 팀은 인프라 외에 비즈니스에 집중할 수 있습니다.
Docker Compose vs Kubernetes

2일차: Docker 이미지 생성 실습
Docker 이미지 주요 명령어
# 현재 시스템에서 사용 가능한 모든 Docker 이미지 목록 확인
$ docker images
# 특정 이미지 다운로드
$ docker pull <이미지 이름>
# 이미지 정보 확인
$ docker inspect <이미지 이름>
# 이미지 삭제
$ docker rmi <이미지 이름>
불필요한 파일 줄이기 (.dockerignore 활용)
- .**dockerignore** 파일은 Docker 빌드 과정에서 제외할 파일과 디렉터리를 지정하는 역할을 합니다.
- Docker는 docker build를 실행할 때, 현재 디렉터리(.)의 모든 파일을 Docker 컨텍스트에 복사합니다.
- 이때 .dockerignore 파일을 사용하면 불필요한 파일을 제외하여 빌드 속도를 향상시키고, 보안성을 강화할 수 있습니다.
- .dockerignore 파일이 필요한 이유
- 빌드 속도 향상 → 불필요한 파일을 제외하여 Docker 컨텍스트 크기를 줄임
- 보안 강화 → 환경 변수 파일(.env), 인증 정보(.git, node_modules) 등이 이미지에 포함되지 않도록 방지
- 이미지 크기 최소화 → 최적화된 Docker 이미지를 생성하여 배포 용량을 줄임

레이어 캐싱 (Layer Caching)
도커의 가장 중요한 특징 중 하나는 레이어 캐싱입니다. 이미지를 빌드할 때, Dockerfile의 각 명령어를 순서대로 실행하며 레이어를 만듭니다. 이때 명령어의 내용이 이전 빌드와 동일하다면, 새로운 레이어를 만들지 않고 기존에 만들어 두었던 레이어를 재사용합니다. 이를 '캐시(Cache)를 사용한다'고 말합니다.
- 빌드 속도 향상: 변경되지 않은 부분은 다시 실행할 필요가 없으므로 이미지 빌드 시간이 크게 단축됩니다.
- 효율적인 저장 공간 사용: 여러 이미지가 동일한 레이어를 공유하는 경우, 해당 레이어는 디스크에 한 번만 저장됩니다. 예를 들어, ubuntu:22.04를 기반으로 하는 10개의 다른 이미지가 있더라도, 우분투 베이스 레이어는 단 한 번만 저장됩니다.
Dockerfile을 작성할 때, 자주 변경되지 않는 내용은 앞부분에, 자주 변경되는 내용은 뒷부분에 배치하는 것이 레이어 캐싱을 효율적으로 활용하는 좋은 방법입니다. 소스 코드는 자주 바뀌므로 COPY . . 명령어는 보통 뒷부분에 위치시킵니다.
Docker 이미지 Versioning 과 Semantic Versioning
Docker 이미지 versioning
- Docker 이미지는 태그(Tag) 를 사용하여 버전 관리를 수행합니다.
- latest 태그를 사용할 수도 있지만, 명확한 버전 관리를 위해 시멘틱 버저닝(Semantic Versioning) 을 사용하는 것이 좋습니다.
시멘틱 버저닝(Semantic Versioning)이란
- 시멘틱 버저닝(SemVer)은 주버전(Major), 부버전(Minor), 패치버전(Patch) 으로 구성됩니다.
- 형식: MAJOR.MINOR.PATCH
- MAJOR (주 버전): 호환성이 깨지는 큰 변경이 있을 때 올립니다.
- 예: 1.5.2 → 2.0.0
- 기존의 사용법이나 기능이 완전히 바뀌어, 이 버전을 사용하려면 내 코드도 수정해야 할 수 있다는 강력한 신호입니다. 마치 자동차 엔진이 바뀌는 것과 같습니다.
- MINOR (부 버전): 기존 버전과 호환되면서 새로운 기능이 추가될 때 올립니다.
- 예: 1.9.2 → 1.10.0
- 기존 기능은 그대로 잘 작동하며, 새로운 옵션이나 기능이 추가된 경우입니다. 자동차에 새로운 내비게이션 시스템이 추가된 것과 같습니다. 기존 운전 방식에는 영향이 없습니다.
- PATCH (패치 버전): 기존 버전과 호환되는 작은 버그 수정이 있을 때 올립니다.
- 예: 1.5.2 → 1.5.3
- 기능 변화 없이, 기존 기능의 오류를 바로잡은 경우입니다. 자동차의 사소한 부품 결함을 수리한 것과 같습니다.
버전 형식 설명
| 1.0.0 | 초기 릴리즈 버전 |
| 1.1.0 | 기능(feature) 추가 (하위 호환 유지) |
| 1.1.1 | 버그 수정 (패치 버전) |
| 2.0.0 | 기존 기능을 변경하거나 호환되지 않는 수정 |
Docker에서 Semantic Versioning 적용 예제
- Dockerfile을 사용하여 시멘틱 버저닝을 적용할 때, 태그를 명확하게 지정합니다.
- 시멘틱 버저닝을 활용하면 배포 관리가 쉬워지고, 특정 버전으로 롤백이 용이해집니다.
# 1.0.0 버전으로 빌드
docker build --build-arg PROFILE=dev -t spring-docker:1.0.0 .
# 1.0.1 버전으로 빌드 (패치 업데이트 포함)
docker build --build-arg PROFILE=dev -t spring-docker:1.0.1 .
3일차: Docker 네트워크 및 데이터 관리
- Docker 네트워크 개념 및 종류 이해
- 컨테이너 간 네트워크 설정 및 통신 실습
- Docker 볼륨을 활용한 데이터 관리 실습
- 보안 및 성능 최적화 기법 적용

1.3 컨테이너 간 기본 네트워크 통신 확인
- busybox
# 현재 Docker 네트워크 확인
docker network ls
# 사용자 지정 브리지 네트워크 생성
# sleep infinity : 컨테이너 내부에서 종료되지 않는 프로세스를 실행하여 유지
docker run -d --name svc1 --network bridge busybox sleep infinity
docker run -d --name svc2 --network bridge busybox sleep infinity
docker exec -it svc1 ping svc2
-------------------------------------------------
ping: bad address 'svc2'
- 기본 bridge 네트워크에서 컨테이너 간 직접 통신이 안 되는 이유
- 기본 bridge 네트워크에서는 컨테이너 이름 기반 DNS 해석이 지원되지 않음
- IP 주소를 직접 사용해야 하지만, IP는 컨테이너 재시작 시 변경될 수 있어 관리가 어려움
- 사용자 정의 네트워크를 만들면 컨테이너 이름을 통해 자동으로 통신 가능
- 해결책
- 기본 bridge 네트워크를 사용할 경우, 컨테이너 간 통신 시 IP 주소를 사용해야 합니다.
- 컨테이너 이름으로 통신하려면 사용자 정의 네트워크(docker network create <네트워크명>)를 사용해야 합니다.
4일차: Docker 를 활용한 Log 관리
1. 표준 로그 스트림 및 출력 관리
1.1 표준 에러 스트림과 표준 출력 스트림
- 컨테이너 실행 및 로그 생성
- sh -c 명령어를 통해 stdout과 stderr로 각각 로그를 출력합니다.
- echo "stderr log" >&2는 표준 에러로 메시지를 보냅니다.
- docker run --name log-test -d alpine sh -c ' for i in $(seq 1 10); do echo "$i: stdout log"; echo "$i: stderr log" >&2; done'
- 로그 확인하기
- 실행 중인 컨테이너의 모든 로그 출력
docker logs log-test- 최근 5개의 로그 출력
docker logs --tail 5 log-test
- 실시간 로그 스트림 확인
- f 옵션을 사용하면 컨테이너의 실시간 로그 스트림을 확인할 수 있습니다.
- docker logs -f log-test
- 로그 출력 시 타임스탬프 포함
- 각 로그에 타임스탬프를 추가하여 출력합니다.
docker logs --timestamps log-test - 실습 종료 및 컨테이너 정리
docker stop log-test && docker rm log-test
2. 컨테이너 로그 수집 및 관리
2.1 syslog 드라이버를 이용해 로그 전송 설정하기
Docker 컨테이너의 로그를 외부 syslog 서버로 전송 설정합니다.
docker run --log-driver=syslog --log-opt syslog-address=udp://localhost:514 -d ubuntu echo "Logging to syslog"
2.2 로그 로테이션 설정
Docker 컨테이너의 로그 드라이버는 기본적으로 json-file을 사용하며, 이 드라이버는 로그 로테이션 옵션이 있습니다. max-size와 max-file 옵션을 사용하여 로그 파일의 최대 크기와 보관할 로그 파일의 수를 제어할 수 있습니다.
# Docker 컨테이너를 로그 로테이션 설정과 함께 실행
docker run -d \\
--name=log-rotation-test \\
--log-opt max-size=10m \\
--log-opt max-file=3 \\
ubuntu bash -c 'while true; do echo "$(date) - Writing logs to fill up space..."; sleep 1; done'
# 로그 확인
docker logs -f log-rotation-test
# 종료
docker stop log-rotation-test
docker rm log-rotation-test
2.3 로그 모니터링 실습
2.3.1 로그 모니터링 스크립트 생성
- monitor-logs.sh
- chmod +x monitor-logs.sh
#!/bin/bash
# 첫 번째 인자로 컨테이너 이름을 받음
CONTAINER_NAME=$1
# 로그 라인 수 임계값 설정
THRESHOLD=1000
# 무한 루프로 계속 모니터링
while true; do
# 현재 컨테이너의 로그 라인 수를 계산
LOG_SIZE=$(docker logs $CONTAINER_NAME 2>&1 | wc -l)
# 현재 시간 저장
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
# 로그 크기가 임계값을 초과하면 경고
if [ $LOG_SIZE -gt $THRESHOLD ]; then
echo "[$CURRENT_TIME] Warning: Log size ($LOG_SIZE lines) exceeds threshold ($THRESHOLD) for $CONTAINER_NAME"
# 선택적: 관리자에게 이메일 발송
# mail -s "Docker Log Alert" admin@example.com <<< "Container $CONTAINER_NAME log size exceeds threshold"
else
echo "[$CURRENT_TIME] Log size ($LOG_SIZE lines) is normal for $CONTAINER_NAME"
fi
# 1초 대기
sleep 1
done
2.3.2 실습용 로그 생성 컨테이너 생성
# 로그를 지속적으로 생성하는 테스트용 Dockerfile
cat > Dockerfile << 'EOF'
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y stress
CMD while true; do date; echo "Test log message"; sleep 1; done
EOF
# 이미지 빌드
docker build -t log-generator .
# 컨테이너 실행
docker run -d --name log-test1 log-generator
2.3.3 모니터링 실행 및 테스트
# 모니터링 스크립트 실행
./monitor-logs.sh log-test1
# 별도 터미널에서 로그 확인
docker logs -f log-test1
2.3.4 모니터링 설정 (확장편)
#!/bin/bash
CONTAINER_NAME=$1
THRESHOLD=1000
LOG_FILE="container_logs.txt"
ALERT_EMAIL="admin@example.com"
monitor_logs() {
LOG_SIZE=$(docker logs $CONTAINER_NAME 2>&1 | wc -l)
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
DISK_USAGE=$(docker inspect $CONTAINER_NAME --format='{{.LogPath}}' | xargs du -h 2>/dev/null | cut -f1)
echo "[$CURRENT_TIME] Container: $CONTAINER_NAME" >> $LOG_FILE
echo "Log lines: $LOG_SIZE" >> $LOG_FILE
echo "Disk usage: $DISK_USAGE" >> $LOG_FILE
if [ $LOG_SIZE -gt $THRESHOLD ]; then
MESSAGE="Warning: Container $CONTAINER_NAME has exceeded log threshold
Current size: $LOG_SIZE lines
Disk usage: $DISK_USAGE
Time: $CURRENT_TIME"
echo "$MESSAGE" >> $LOG_FILE
echo "$MESSAGE" | mail -s "Docker Log Alert" $ALERT_EMAIL
# 로그 백업 및 클리어
docker logs $CONTAINER_NAME > "${CONTAINER_NAME}_logs_${CURRENT_TIME}.txt"
docker container restart $CONTAINER_NAME
fi
}
# 메인 모니터링 루프
while true; do
if docker ps | grep -q $CONTAINER_NAME; then
monitor_logs
else
echo "[$CURRENT_TIME] Container $CONTAINER_NAME is not running!" >> $LOG_FILE
fi
sleep 60
done
- 로그용 Dockerfile 및 로그 생성 스크립트 작성
# 로그 생성용 Dockerfile 생성
cat > Dockerfile << 'EOF'
FROM ubuntu:20.04
# 스트레스 테스트 도구 설치
RUN apt-get update && apt-get install -y stress
# 로그 생성 스크립트
COPY generate-logs.sh /
RUN chmod +x /generate-logs.sh
CMD ["/generate-logs.sh"]
EOF
# 로그 생성 스크립트 작성
cat > generate-logs.sh << 'EOF'
#!/bin/bash
while true; do
date
echo "Application log: Process running"
echo "System status: OK"
echo "Memory usage: $(free -m | grep Mem | awk '{print $3}') MB"
sleep 1
done
EOF
# 이미지 빌드
docker build -t log-generator .
# 컨테이너 실행
docker run -d --name test-container log-generator
- 모니터링 실행 및 테스트
# 터미널 1: 모니터링 스크립트 실행
sh advanced-monitor-logs.sh test-container
# 터미널 2: 로그 생성 테스트
docker exec -it test-container bash -c 'for i in {1..1500}; do echo "Test log entry $i"; done'
- 로그 확인 및 분석
# 모니터링 로그 확인
cat container_logs.txt
# 컨테이너 로그 확인
docker logs test-container
3. Docker 디스크 사용량 모니터링 실습
3.1 기본 디스크 사용량 모니터링
# Docker 전체 디스크 사용량 확인
docker system df
# 상세한 디스크 사용량 확인
docker system df -v
# 실시간 디스크 사용량 모니터링 스크립트 생성
cat > monitor-disk-usage.sh << 'EOF'
#!/bin/bash
while true; do
echo "=== Docker 디스크 사용량 모니터링 === ($(date))"
echo "1. 컨테이너 디스크 사용량:"
docker ps --size --format "table {{.Names}}\\t{{.Size}}\\t{{.State}}"
echo -e "\\n2. 이미지 디스크 사용량:"
docker system df -v | grep "Images space"
echo -e "\\n3. 볼륨 디스크 사용량:"
docker system df -v | grep "Volumes space"
echo -e "\\n4. 빌드 캐시 사용량:"
docker system df -v | grep "Build cache"
echo "======================================="
sleep 60
done
EOF
chmod +x monitor-disk-usage.sh
3.2 테스트용 컨테이너 생성 및 모니터링
# 테스트용 컨테이너 생성
docker run -d --name disk-test-1 ubuntu:20.04 tail -f /dev/null
docker run -d --name disk-test-2 nginx
# 데이터 생성 스크립트
cat > generate-data.sh << 'EOF'
#!/bin/bash
for i in {1..10}; do
echo "Generating data file $i..."
docker exec disk-test-1 dd if=/dev/zero of=/tmp/file$i bs=1M count=100
sleep 1
done
EOF
chmod +x generate-data.sh
3.3 디스크 모니터링 스크립트 작성
cat > advanced-disk-monitor.sh << 'EOF'
#!/bin/bash
LOG_FILE="disk_usage_log.txt"
THRESHOLD_PERCENT=80
ALERT_EMAIL="admin@example.com"
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
get_container_sizes() {
docker ps -s --format "{{.Names}}: {{.Size}}" | while read line; do
log_message "Container $line"
done
}
check_disk_usage() {
# Docker 루트 디렉토리 사용량 확인
DOCKER_ROOT=$(docker info | grep "Docker Root Dir" | cut -d: -f2 | tr -d ' ')
USAGE_PERCENT=$(df -h $DOCKER_ROOT | awk 'NR==2 {print $5}' | tr -d '%')
log_message "Docker root directory ($DOCKER_ROOT) usage: ${USAGE_PERCENT}%"
if [ $USAGE_PERCENT -gt $THRESHOLD_PERCENT ]; then
MESSAGE="Warning: Docker disk usage is at ${USAGE_PERCENT}%"
log_message "$MESSAGE"
# 가장 큰 컨테이너 5개 리스트
log_message "Top 5 largest containers:"
docker ps -s --format "{{.Size}}\\t{{.Names}}" | sort -hr | head -n 5 | \\
while read line; do
log_message "$line"
done
# 사용하지 않는 리소스 정리 추천
log_message "Recommended cleanup commands:"
log_message "docker system prune -f"
log_message "docker volume prune -f"
log_message "docker image prune -a -f"
fi
}
monitor_volumes() {
log_message "Volume usage:"
docker volume ls -q | while read vol; do
USAGE=$(docker run --rm -v $vol:/vol alpine du -sh /vol)
log_message "Volume $vol: $USAGE"
done
}
# 메인 모니터링 루프
while true; do
log_message "=== Starting disk usage check ==="
check_disk_usage
get_container_sizes
monitor_volumes
log_message "=== Completed disk usage check ==="
echo -e "\\n"
sleep 300 # 5분 간격으로 체크
done
EOF
chmod +x advanced-disk-monitor.sh
3.4 실습 시나리오
3.4.1 모니터링 시작
# 터미널 1: 기본 모니터링 실행
./monitor-disk-usage.sh
# 터미널 2: 데이터 생성
./generate-data.sh
3.4.2 모니터링 테스트
# 터미널 1: 고급 모니터링 실행
./advanced-disk-monitor.sh
# 터미널 2: 대용량 파일 생성
docker run -d --name big-data-test ubuntu:20.04 tail -f /dev/null
docker exec big-data-test dd if=/dev/zero of=/bigfile bs=1G count=2
3.4.3 디스크 정리
# 사용하지 않는 리소스 정리
docker system prune -f
# 사용하지 않는 볼륨 정리
docker volume prune -f
# 사용하지 않는 이미지 정리
docker image prune -a -f
# 정리 후 사용량 확인
docker system df -v
3.4.4 컨테이너 별 상세 모니터링
# 컨테이너별 디스크 사용량 모니터링 스크립트
cat > container-disk-monitor.sh << 'EOF'
#!/bin/bash
echo "=== Container Disk Usage Details ==="
docker ps --format "{{.Names}}" | while read container; do
echo "Container: $container"
echo "Size details:"
docker ps -s --filter "name=$container" --format "Virtual Size: {{.Size}}"
echo "Top 5 largest directories:"
docker exec $container du -h / 2>/dev/null | sort -hr | head -n 5
echo "------------------------"
done
EOF
chmod +x container-disk-monitor.sh
./container-disk-monitor.sh
'Software > Maker(Spring & Python & node)' 카테고리의 다른 글
| 꼬리를 문 뱀의 지혜: AI 시대, 자바 아키텍트가 '코드'보다 '명세'에 집착해야 하는 이유 (0) | 2026.04.29 |
|---|---|
| 조용한 실력자와 시끄러운 허세꾼의 차이 4가지 (0) | 2026.04.28 |
| 주사위를 굴려 나온 코드가 왜 빌드에 성공하는가 — LLM 비결정성과 AI 코딩의 정확성에 대한 고찰 (2) | 2026.04.23 |
| 분산 시스템 기반 대규모 트래픽 처리(wil. 6week) (0) | 2026.04.23 |
| 한국 솔루션의 진짜 해자 — 기술이 아닌 제도·관계·도메인의 구조 분석 (0) | 2026.04.23 |