포스트

[이제와서 시작하는 Docker 마스터하기 - 고급편 #8] 문제 해결과 트러블슈팅

[이제와서 시작하는 Docker 마스터하기 - 고급편 #8] 문제 해결과 트러블슈팅

“이제와서 시작하는 Docker 마스터하기” Docker를 사용하다 보면 다양한 문제에 직면하게 됩니다. 이번 편에서는 일반적인 Docker 문제들과 해결 방법, 디버깅 기법을 정리했습니다. 이 가이드를 통해 문제를 빠르게 진단하고 해결할 수 있습니다.

일반적인 Docker 문제

1. 컨테이너가 시작되지 않을 때

1
2
3
4
5
6
7
8
9
10
11
12
# 문제 진단 순서
# 1. 컨테이너 상태 확인
docker ps -a

# 2. 컨테이너 로그 확인
docker logs container-name

# 3. 상세 정보 확인
docker inspect container-name

# 4. 이벤트 확인
docker events --since '10m' --filter container=container-name

일반적인 원인과 해결법:

1
2
3
4
5
6
7
8
9
10
# Exit Code 125: Docker 데몬 문제
systemctl status docker
systemctl restart docker

# Exit Code 126: 컨테이너 명령을 실행할 수 없음
docker run --rm -it image-name /bin/sh
# 실행 파일 권한 확인

# Exit Code 127: 명령을 찾을 수 없음
docker run --rm -it image-name which command-name

2. 네트워크 연결 문제

1
2
3
4
5
6
7
8
9
10
11
12
13
# 네트워크 진단
# 1. 네트워크 목록 확인
docker network ls

# 2. 네트워크 상세 정보
docker network inspect bridge

# 3. 컨테이너 네트워크 설정 확인
docker inspect container-name | grep -A 20 NetworkMode

# 4. 컨테이너 간 연결 테스트
docker exec container1 ping container2
docker exec container1 nc -zv container2 80

해결 방법:

1
2
3
4
5
6
7
8
9
10
# DNS 문제 해결
docker run --dns 8.8.8.8 --dns 8.8.4.4 image-name

# 네트워크 재생성
docker network rm problematic-network
docker network create new-network

# 방화벽 규칙 확인
sudo iptables -L -n
sudo iptables -L DOCKER -n

3. 디스크 공간 부족

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Docker 디스크 사용량 확인
docker system df

# 상세 정보
docker system df -v

# 정리 명령어
# 사용하지 않는 컨테이너 삭제
docker container prune

# 사용하지 않는 이미지 삭제
docker image prune -a

# 사용하지 않는 볼륨 삭제
docker volume prune

# 사용하지 않는 네트워크 삭제
docker network prune

# 전체 정리 (주의!)
docker system prune -a --volumes

자동 정리 스크립트:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# docker-cleanup.sh

echo "Docker 정리 시작..."

# 중지된 컨테이너 삭제
echo "중지된 컨테이너 삭제 중..."
docker container prune -f

# 사용하지 않는 이미지 삭제 (1주일 이상)
echo "오래된 이미지 삭제 중..."
docker image prune -a -f --filter "until=168h"

# 사용하지 않는 볼륨 삭제
echo "사용하지 않는 볼륨 삭제 중..."
docker volume prune -f

# 빌드 캐시 정리
echo "빌드 캐시 정리 중..."
docker builder prune -f --filter "until=168h"

echo "정리 완료!"
docker system df

성능 문제 해결

1. 느린 빌드 속도

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 개선 전
FROM node:16
COPY . /app
WORKDIR /app
RUN npm install
RUN npm run build

# 개선 후
FROM node:16 AS builder
WORKDIR /app
# 의존성 캐싱
COPY package*.json ./
RUN npm ci --only=production

# 소스 복사
COPY . .
RUN npm run build

# 멀티 스테이지
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

BuildKit 활성화:

1
2
3
4
5
6
7
8
9
# BuildKit으로 빌드
DOCKER_BUILDKIT=1 docker build -t myapp .

# 또는 daemon.json에 설정
{
  "features": {
    "buildkit": true
  }
}

2. 메모리 문제

1
2
3
4
5
6
7
8
# 컨테이너 메모리 사용량 확인
docker stats --no-stream

# 메모리 제한 설정
docker run -m 512m --memory-swap 512m image-name

# OOM Kill 비활성화
docker run -m 512m --oom-kill-disable image-name

Java 애플리케이션 메모리 설정:

1
2
3
# JVM 메모리 설정
ENV JAVA_OPTS="-Xmx512m -Xms256m"
CMD ["java", "$JAVA_OPTS", "-jar", "app.jar"]

3. CPU 사용률 문제

1
2
3
4
5
6
7
8
# CPU 사용률 제한
docker run --cpus="1.5" image-name

# CPU 공유 가중치
docker run --cpu-shares=512 image-name

# 특정 CPU 코어 지정
docker run --cpuset-cpus="0,1" image-name

로깅과 디버깅

1. 상세 로그 활성화

1
2
3
4
5
6
7
8
9
10
11
12
# Docker 데몬 디버그 모드
# /etc/docker/daemon.json
{
  "debug": true,
  "log-level": "debug"
}

# 재시작
systemctl restart docker

# 로그 확인
journalctl -u docker.service -f

2. 컨테이너 디버깅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 실행 중인 컨테이너 디버깅
docker exec -it container-name /bin/sh

# 디버깅 도구 설치
docker exec container-name apk add --no-cache \
  curl wget netcat-openbsd tcpdump

# 프로세스 확인
docker exec container-name ps aux
docker exec container-name top

# 네트워크 상태 확인
docker exec container-name netstat -tulpn
docker exec container-name ss -tulpn

3. 디버깅용 컨테이너

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Dockerfile.debug
FROM myapp:latest

# 디버깅 도구 설치
RUN apt-get update && apt-get install -y \
    strace \
    tcpdump \
    netcat \
    curl \
    vim \
    procps \
    && rm -rf /var/lib/apt/lists/*

# 디버그 포트 노출
EXPOSE 9229

# Node.js 디버그 모드
CMD ["node", "--inspect=0.0.0.0:9229", "app.js"]

보안 문제 해결

1. 권한 문제

1
2
3
4
5
6
7
8
9
# 권한 오류 해결
# 사용자 추가
docker exec container-name adduser -D -u 1000 appuser

# 파일 권한 변경
docker exec container-name chown -R appuser:appuser /app

# 특정 사용자로 실행
docker run --user 1000:1000 image-name

2. SELinux 문제 (CentOS/RHEL)

1
2
3
4
5
6
7
8
# SELinux 상태 확인
getenforce

# 볼륨 마운트 시 :z 옵션 사용
docker run -v /host/path:/container/path:z image-name

# SELinux 컨텍스트 확인
ls -Z /var/lib/docker

Docker Compose 문제 해결

1. 서비스 시작 순서

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# docker-compose.yml
version: '3.8'

services:
  web:
    image: myapp
    depends_on:
      db:
        condition: service_healthy
    command: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]

  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

2. 환경 변수 문제

1
2
3
4
5
6
7
8
# 환경 변수 확인
docker compose config

# 환경 변수 디버깅
docker compose run --rm web env

# .env 파일 검증
docker compose --env-file .env.test config

도구와 유틸리티

1. Docker 디버깅 도구

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ctop - 컨테이너 모니터링
docker run --rm -it \
  --name=ctop \
  -v /var/run/docker.sock:/var/run/docker.sock \
  quay.io/vektorlab/ctop:latest

# dive - 이미지 레이어 분석
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  wagoodman/dive:latest image-name

# docker-debug - 실행 중인 컨테이너 디버깅
docker run -it --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -p 2333:2333 \
  zeromake/docker-debug:latest

2. 모니터링 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# monitoring-stack.yml
version: '3.8'

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker:/var/lib/docker:ro
    ports:
      - "8080:8080"

  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

일반적인 에러 메시지와 해결법

1. “Cannot connect to the Docker daemon”

1
2
3
4
5
6
7
8
9
# Docker 서비스 상태 확인
systemctl status docker

# Docker 소켓 권한 확인
ls -la /var/run/docker.sock

# 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
newgrp docker

2. “No space left on device”

1
2
3
4
5
6
7
8
9
10
# Docker 루트 디렉토리 변경
# /etc/docker/daemon.json
{
  "data-root": "/mnt/docker"
}

# 기존 데이터 이동
systemctl stop docker
rsync -aqxP /var/lib/docker/ /mnt/docker/
systemctl start docker

3. “Port is already allocated”

1
2
3
4
5
6
7
8
9
# 포트 사용 프로세스 확인
sudo lsof -i :80
sudo netstat -tulpn | grep :80

# 프로세스 종료
sudo kill -9 PID

# 또는 다른 포트 사용
docker run -p 8080:80 image-name

체크리스트

문제 해결 체크리스트

  • Docker 데몬이 실행 중인가?
  • 충분한 디스크 공간이 있는가?
  • 메모리와 CPU 리소스가 충분한가?
  • 네트워크 연결이 정상인가?
  • 올바른 이미지 태그를 사용하고 있는가?
  • 환경 변수가 올바르게 설정되어 있는가?
  • 볼륨 마운트 경로가 존재하는가?
  • 포트가 이미 사용 중이지 않은가?
  • SELinux나 AppArmor 정책에 문제가 없는가?
  • 로그에 명확한 에러 메시지가 있는가?

성능 최적화 팁

1. 빌드 최적화

1
2
3
4
5
# 빌드 캐시 활용
docker build --cache-from myapp:latest -t myapp:new .

# 병렬 빌드
docker buildx build --platform linux/amd64,linux/arm64 .

2. 런타임 최적화

1
2
3
4
5
6
7
8
# 로깅 드라이버 최적화
docker run --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  image-name

# 스토리지 드라이버 확인
docker info | grep "Storage Driver"

마무리

Docker 문제 해결은 체계적인 접근이 중요합니다. 로그 확인, 리소스 모니터링, 네트워크 진단 등의 기본적인 절차를 따르면 대부분의 문제를 해결할 수 있습니다. 다음 편에서는 Docker 생태계와 미래에 대해 알아보겠습니다.

다음 편 예고

  • Docker 생태계 소개
  • 관련 기술과 도구들
  • 컨테이너 기술의 미래
  • 학습 리소스와 커뮤니티

Docker 여정의 마지막 이야기! 🎯

📚 Docker 마스터하기 시리즈

🐳 기초편 (입문자용 - 5편)

  1. Docker란 무엇인가?
  2. Docker 설치 및 환경 설정
  3. 첫 번째 컨테이너 실행하기
  4. Docker 이미지 이해하기
  5. Dockerfile 작성하기

💼 실전편 (중급자용 - 6편)

  1. Docker 네트워크 기초
  2. Docker 볼륨과 데이터 관리
  3. Docker Compose 입문
  4. 멀티 컨테이너 애플리케이션
  5. Docker Hub 활용하기
  6. Docker 보안 베스트 프랙티스

🚀 고급편 (전문가용 - 9편)

  1. Docker 로그와 모니터링
  2. Docker로 Node.js 애플리케이션 배포
  3. Docker로 Python 애플리케이션 배포
  4. Docker로 데이터베이스 운영
  5. Docker 이미지 최적화
  6. Docker와 CI/CD
  7. Docker Swarm 기초
  8. 문제 해결과 트러블슈팅 ← 현재 글
  9. Docker 생태계와 미래
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.