Published on

Docker에서 NVIDIA GPU가 안 잡힐 때 nvidia-smi는 되는데 컨테이너에서 CUDA not found 뜨는 7가지 원인과 해결

Authors

서버에서 nvidia-smi는 잘 뜨는데, 막상 Docker 컨테이너 안에서 torch.cuda.is_available()False거나 CUDA not found, libcuda.so.1: cannot open shared object file 같은 메시지가 튀어나오면 정말 사람 미치게 합니다. 특히 운영 환경에서는 “호스트 GPU는 정상인데 컨테이너만 안 됨”이라는 애매한 상태가 길어질수록 배포 지연과 비용이 커집니다.

이 글은 그런 상황에서 가장 자주 밟는 7가지 지뢰를 원인별로 분해해, 확인 명령 → 증상 → 해결 순서로 정리한 실전 체크리스트입니다. (드라이버·nvidia-container-toolkit·cgroup v2·권한·이미지 태그까지 포함)


먼저 2분 컷 기본 진단 루틴

아래 3가지만 먼저 확인하면, 문제 범위를 절반 이상 줄일 수 있습니다.

1) 호스트 드라이버 상태

nvidia-smi
lsmod | grep -E 'nvidia|nouveau'
cat /proc/driver/nvidia/version
  • nvidia-smi가 정상 출력되고, nouveau가 잡혀있지 않다면 호스트 드라이버 자체는 대체로 OK입니다.

2) Docker가 GPU 런타임을 제대로 붙이는지

docker info | grep -i runtime -A3

Runtimes: nvidia runc처럼 nvidia가 보여야 합니다.

3) 가장 단순한 CUDA 컨테이너로 테스트

docker run --rm --gpus all nvidia/cuda:12.3.2-base-ubuntu22.04 nvidia-smi
  • 여기서도 실패하면 환경/런타임 문제 가능성이 큽니다.
  • 여기서는 성공하지만 내 앱 이미지에서만 실패하면 이미지 태그/라이브러리/권한/엔트리포인트 문제일 확률이 높습니다.

원인 1. 호스트 NVIDIA 드라이버는 있는데 컨테이너용 런타임이 없다 (nvidia-container-toolkit 미설치/미구성)

전형적인 증상

  • docker run --gpus all ... 실행 시
    • could not select device driver "" with capabilities: [[gpu]]
    • 또는 컨테이너에서 nvidia-smi: command not found / libcuda.so.1 로딩 실패

확인

which nvidia-container-runtime || true
nvidia-container-cli -V || true

해결 (Ubuntu/Debian 예시)

# 1) 설치
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

# 2) Docker 런타임에 연결
sudo nvidia-ctk runtime configure --runtime=docker

# 3) Docker 재시작
sudo systemctl restart docker

# 4) 재테스트
docker run --rm --gpus all nvidia/cuda:12.3.2-base-ubuntu22.04 nvidia-smi

> 운영에서 자주 하는 실수: toolkit은 설치했는데 runtime configure를 안 해서 Docker가 GPU 런타임을 모르는 상태로 남는 경우가 많습니다.


원인 2. Docker 버전/옵션 문제로 --gpus가 무시되거나 런타임이 runc로 고정됨

전형적인 증상

  • --gpus all을 줬는데도 컨테이너 내부에 /dev/nvidia*가 없음

확인

docker run --rm --gpus all ubuntu:22.04 bash -lc 'ls -al /dev | grep nvidia || true'

해결 포인트

  • Docker Engine이 너무 오래된 경우 업그레이드
  • daemon.json에 런타임을 강제로 설정(필요 시)

/etc/docker/daemon.json 예시:

{
  "runtimes": {
    "nvidia": {
      "path": "nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}

적용:

sudo systemctl restart docker

원인 3. cgroup v2 환경에서 nvidia-container-toolkit/런타임이 제대로 연동되지 않음

요즘 배포판(특히 Ubuntu 22.04+, Debian 12, 최신 RHEL 계열)은 cgroup v2가 기본인 경우가 많고, 여기서 GPU 장치 권한/디바이스 필터링이 꼬이면 “호스트는 되는데 컨테이너는 안 됨”이 발생합니다.

전형적인 증상

  • 컨테이너에서 /dev/nvidia0 등이 안 보이거나 권한 오류
  • nvidia-container-cli 관련 로그에 device permission 관련 메시지

확인

stat -fc %T /sys/fs/cgroup
# cgroup2fs면 v2

Docker가 어떤 cgroup driver를 쓰는지도 확인:

docker info | grep -i cgroup

해결 방향

  1. nvidia-container-toolkit 최신화
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
  1. (임시/회피) 부트 파라미터로 cgroup v1로 내리기

운영에서는 권장하지 않지만, 원인 절단용으로는 유효합니다.

  • /etc/default/grub에서:
GRUB_CMDLINE_LINUX="... systemd.unified_cgroup_hierarchy=0"
  • 적용:
sudo update-grub
sudo reboot

> cgroup v2는 "무조건 끄기"가 정답이 아니라, 런타임/도커/커널 조합을 최신으로 맞추는 것이 정공법입니다. 다만 장애 대응 중에는 v1 전환이 빠른 우회가 될 수 있습니다.


원인 4. 컨테이너 이미지가 CUDA 런타임/라이브러리를 포함하지 않거나 태그를 잘못 골랐다

여기서 가장 흔한 착각이 있습니다.

  • nvidia-smiCUDA Toolkit이 없어도 동작할 수 있습니다(드라이버 유틸리티).
  • 하지만 프레임워크(예: PyTorch, TensorFlow)나 CUDA 샘플은 CUDA 런타임/라이브러리가 필요합니다.

전형적인 증상

  • nvidia-smi는 컨테이너에서 되는데
  • nvcc: command not found 또는 CUDA not found
  • PyTorch에서 torch.cuda.is_available() == False

확인

docker run --rm --gpus all <YOUR_IMAGE> bash -lc '
  nvidia-smi || true
  which nvcc || true
  ls -al /usr/local/cuda || true
  ldconfig -p | grep -E "libcuda|libcudart" || true
'

해결

  • 목적에 맞는 이미지 태그를 선택
    • 개발(컴파일 필요): nvidia/cuda:<ver>-devel-...
    • 실행만: nvidia/cuda:<ver>-runtime-... 또는 -base-...

예: CUDA 런타임이 필요한 앱이라면:

FROM nvidia/cuda:12.3.2-runtime-ubuntu22.04

RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cu121

CMD ["python3", "-c", "import torch; print(torch.cuda.is_available()); print(torch.version.cuda)"]

> 이미지 태그 하나 잘못 고르면, 컨테이너에서 GPU가 “보이긴 보이는데 쓸 수 없는” 상태가 됩니다.


원인 5. 호스트 드라이버 버전과 컨테이너 CUDA 버전의 호환성이 깨짐

NVIDIA는 대체로 “드라이버가 충분히 최신이면, 여러 CUDA 런타임을 수용”하지만, 반대로 너무 오래된 드라이버에서 너무 최신 CUDA 런타임을 쓰면 실패합니다.

전형적인 증상

  • CUDA driver version is insufficient for CUDA runtime version
  • 프레임워크 로딩 시 undefined symbol 류 에러

확인

호스트:

nvidia-smi --query-gpu=driver_version --format=csv,noheader

컨테이너:

docker run --rm --gpus all nvidia/cuda:12.3.2-runtime-ubuntu22.04 bash -lc 'cat /usr/local/cuda/version.json || true'

해결

  • 가장 안전한 순서

    1. 호스트 드라이버 업그레이드
    2. 그 다음 컨테이너 CUDA 버전/프레임워크 빌드 선택
  • 운영에서 자주 쓰는 전략

    • 호스트 드라이버를 LTS/production branch로 올려두고
    • 컨테이너는 프로젝트별로 CUDA 버전을 고정(tag pinning)

원인 6. 권한/보안 옵션 때문에 /dev/nvidia* 접근이 막힘 (rootless, userns-remap, SELinux/AppArmor)

보안 강화를 해 둔 서버에서 특히 많이 터집니다.

전형적인 증상

  • 컨테이너에서 /dev/nvidia0: Permission denied
  • rootless Docker에서 GPU 전달이 불안정
  • SELinux enforcing에서 디바이스 접근 차단

확인

컨테이너 내부에서:

docker run --rm --gpus all ubuntu:22.04 bash -lc '
  id
  ls -al /dev/nvidia* || true
  cat /proc/self/cgroup
'

호스트에서 Docker가 rootless인지:

docker info | grep -i rootless

해결 방법들 (상황별)

  • rootless 사용 중이면: GPU 패스스루가 제약될 수 있어, 운영 워크로드는 rootful Docker/Containerd로 전환 검토
  • AppArmor/SELinux 정책 조정
  • (진단용) 권한 완화 플래그로 원인 분리
docker run --rm --gpus all --security-opt apparmor=unconfined --privileged nvidia/cuda:12.3.2-base-ubuntu22.04 nvidia-smi

위처럼 --privileged에서만 되면, 런타임 자체보다 보안 정책/권한 이슈일 확률이 큽니다. (운영에서는 최소 권한으로 다시 좁혀야 합니다)


원인 7. 컨테이너 안에서 CUDA 경로/라이브러리 로딩이 깨짐 (LD_LIBRARY_PATH, conda, slim 이미지)

GPU는 전달됐는데, 애플리케이션이 libcudart.so, libnccl.so, libcublas.so 등을 못 찾아서 “CUDA not found”로 보이는 케이스입니다.

전형적인 증상

  • ImportError: libcudart.so.X: cannot open shared object file
  • OSError: libcuda.so.1: cannot open shared object file
  • conda 환경에서만 실패하고 시스템 파이썬에선 성공

확인

docker run --rm --gpus all <YOUR_IMAGE> bash -lc '
  echo $LD_LIBRARY_PATH
  ldconfig -p | head
  python3 -c "import ctypes; ctypes.CDLL(\"libcuda.so.1\"); print(\"libcuda ok\")" || true
'

해결

  • CUDA 런타임을 이미지에 포함(runtime/devel 태그)
  • 프레임워크 휠을 CUDA 버전에 맞게 설치(예: PyTorch cu121, cu124 등)
  • 필요 시 라이브러리 경로를 명시

예: 컨테이너에서 런타임 라이브러리 경로 보강

ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH}

> 특히 python:slim, ubuntu:rolling 같은 최소 이미지에 conda/venv를 얹으면 동적 라이브러리 탐색이 꼬이기 쉽습니다.


트러블슈팅을 더 빠르게 만드는 로그/관찰 포인트

nvidia-container-toolkit 로그 힌트

호스트에서 다음을 보면 “왜 디바이스가 안 붙는지” 단서가 나옵니다.

sudo journalctl -u docker -n 200 --no-pager

컨테이너가 실제로 GPU 디바이스를 받았는지

docker inspect <container_id> | jq '.[0].HostConfig.DeviceRequests'

DeviceRequests가 비어 있으면 --gpus가 적용되지 않은 겁니다.


Best Practice 운영 체크리스트

1) 이미지 태그 고정과 호환성 표준화

  • nvidia/cuda:12.3.2-runtime-ubuntu22.04처럼 버전 핀
  • 팀 표준 CUDA 버전 1~2개로 제한

2) “호스트 드라이버 업그레이드가 먼저” 원칙

  • 컨테이너 CUDA를 올리기 전에 호스트 드라이버를 충분히 최신으로

3) 배포 파이프라인에 GPU 스모크 테스트 포함

예:

docker run --rm --gpus all $IMAGE bash -lc '
  nvidia-smi
  python3 -c "import torch; print(torch.cuda.is_available())" || true
'

이런 스모크 테스트는, API 호출 실패를 지수 백오프로 버티는 것처럼 사후 대응보다 훨씬 싸게 장애를 막습니다. 대규모 운영에서 재시도/큐잉을 설계할 때는 OpenAI API 429 폭탄 대응 실전 가이드 지수 백오프 큐잉 토큰 버짓으로 비용과 지연을 함께 줄이기처럼 “실패를 전제로 한 설계”가 결국 시스템을 안정화합니다.


결론

nvidia-smi가 된다고 해서 Docker 컨테이너에서 CUDA가 된다는 보장은 없습니다. 컨테이너 CUDA 실패는 대부분 아래 7가지 중 하나입니다.

  1. nvidia-container-toolkit 미설치/미구성
  2. Docker 런타임/버전 문제로 --gpus 미적용
  3. cgroup v2에서 디바이스/권한 연동 이슈
  4. CUDA 런타임 없는 이미지/잘못된 태그 선택
  5. 호스트 드라이버 ↔ 컨테이너 CUDA 호환성 불일치
  6. rootless/userns/SELinux/AppArmor 등 권한/보안 정책
  7. LD_LIBRARY_PATH/conda/slim 이미지로 라이브러리 로딩 실패

지금 장애를 겪고 있다면, 이 글 상단의 2분 컷 진단 루틴부터 그대로 실행해 보세요. 그리고 nvidia/cuda:* 공식 이미지에서 성공/실패를 먼저 갈라내면, 원인 추적 시간이 체감상 70% 이상 줄어듭니다.