Docker Container에 Local GPU 연결하기
[Docker container와 Local GPU 연결하기]
docker container와 local GPU를 연결함을 통해 docker container에서 생성한 개발 환경에서도 GPU 자원을 사용할 수 있도록 한다.
NVIDIA-Container-Toolkit 설치
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# NVIDIA 패키지 repository 및 GPG key 설정
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \ # 호스트 리눅스 배포판의 정보를 읽어 vesion 설정
&& curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# nvidia-docker2 설치
$ sudo apt-get update
$ sudo apt-get install -y nvidia-docker2
# 설치한 내용 적용을 위한 docker 재시작
$ sudo systemctl restart docker
정상 작동 확인
docker run 명령어를 통해 docker container를 생성해보고 터미널에서 nvidia-smi를 입력하여 Local GPU에 연결되었는 지 확인해보도록 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker run -it \
--rm \
--privileged \
--env DISPLAY=$DISPLAY \
--network host \
--gpus all \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--device=/dev/video0:/dev/video0 \
--ipc=host \
-v humble_ws:/root/ros_ws/ \
-w /root/ros_ws \
--name humble_ws \
osrf/ros:humble-desktop-full
여기에 사용된 docker image와 docker run 명령어의 옵션에 대한 내용은 이전 포스팅을 보면 알 수 있다.
위의 명령어를 입력하여 docker container를 생성되는지 확인하자.
성공적으로 docker container에 접속할 수 있다면 아래 명령어를 입력하여 Nvidia GPU에 대한 정보가 나타나는지 확인하자.
위와 같이 출력된다면 성공적으로 local GPU와 docker container가 연결되었음을 알 수 있다.
Trouble Shooting
만약, docker run 명령어를 통해 container를 생성해보았을 때 아래와 같은 에러 메세지가 출력된다면 docker를 지웠다가 다시 설치하는 것을 권한다.
1
2
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: initialization error: load library failed: libnvidia-ml.so.1: cannot open shared object file: no such file or directory: unknown.
[Docker 재설치]
1
2
3
4
5
6
7
8
9
10
11
12
13
# 설치된 docker 제거
$ sudo apt-get purge -y docker-engine docker docker.io docker-ce docker-ce-cli
$ sudo apt-get autoremove -y --purge docker-engine docker docker.io docker-ce
# docker 관련 컨테이너, 이미지, 파일 삭제
$ sudo rm -rf /var/lib/docker /etc/docker
$ sudo rm /etc/apparmor.d/docker
$ sudo groupdel docker
$ sudo rm -rf /var/run/docker.sock
# 재설치
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
$ sudo apt-get install --reinstall docker-ce
Dockerfile 작성시
GPU를 사용하기 위해 아래의 내용을 Dockerfile에 추가한다.
1
2
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
그리고, NVIDIA 공식 CUDA 이미지를 base로 사용하여 GPU 사용에 필요한 CUDA나 cuDNN을 사용하는 것을 권장한다.
나는 ROS2 환경에서 GPU를 사용하고 싶으니, nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04를 base 이미지로 설정하고, RUN을 통해 ROS2를 따로 설치하도록 하겠다. (CUDA를 설치하는 것보다는 ROS2를 설치하는 것이 더욱 편하니깐..!)
이를 위한 dockerfile을 작성해보면 아래와 같다.
[Nvidia CUDA & cuDNN & ROS2]
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# 1. 베이스 이미지 선택: NVIDIA CUDA 이미지 (CUDA, cuDNN 포함)
# ROS2 Humble은 Ubuntu 22.04 기반이므로, 해당 Ubuntu 버전을 지원하는 CUDA 이미지를 선택합니다.
# 'devel' 태그는 개발 도구 (컴파일러 등)를 포함하여 빌드에 용이합니다.
FROM nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04
# 2. 필요한 환경 변수 설정 (옵션이지만 권장)
# 이것은 컨테이너가 GPU를 인식하고 사용할 수 있도록 합니다.
# NVIDIA CUDA 이미지에는 이미 설정되어 있을 수 있지만 명시적으로 넣어주는 것이 좋습니다.
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,graphics # 그래픽 관련 기능도 필요할 수 있으므로 추가
# 3. 시스템 업데이트 및 필수 패키지 설치
# ROS2 설치에 필요한 기본 유틸리티 및 라이브러리 설치
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
locales \
software-properties-common \
curl \
gnupg \
lsb-release \
libglvnd0 \
libgl1 \
libglx0 \
libegl1 \
libxext6 \
libx11-6 \
&& rm -rf /var/lib/apt/lists/*
# 4. ROS2 저장소 및 GPG 키 추가 (Humble 기준)
RUN locale-gen en_US en_US.UTF-8 \
&& update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 \
&& export LANG=en_US.UTF-8
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null
# 5. ROS2 설치
# ROS2 설치시 지역 설정 관련되 부분을 SKIP하기 위함
ENV DEBIAN_FRONTEND=noninteractive
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen en_US.UTF-8 && \
/usr/sbin/update-locale LANG=en_US.UTF-8
ENV LANG="en_US.UTF-8" \
LC_ALL="en_US.UTF-8" \
LANGUAGE="en_US.UTF-8"
# ROS2 설치
RUN apt-get update && apt-get install -y --no-install-recommends \
ros-humble-desktop \
ros-dev-tools \
&& rm -rf /var/lib/apt/lists/*
RUN rosdep init && rosdep update
# 6. ROS2 환경 설정 스크립트 소싱 (매번 수동으로 할 필요 없도록)
COPY bashrc_config.txt /tmp/bashrc_config_temp.txt
# 복사된 파일의 내용을 /root/.bashrc에 추가
# /root/.bashrc 파일이 이미 존재하는 경우, 내용을 덮어쓰지 않고 추가합니다 (>>).
RUN cat /tmp/bashrc_config_temp.txt >> /root/.bashrc && \
rm /tmp/bashrc_config_temp.txt # 임시 파일 삭제
# 7. (선택 사항) 필요한 ROS2 패키지 및 사용자 코드 추가
WORKDIR /ros_ws
COPY . .
RUN apt-get update && rosdep install --from-paths src --ignore-src -r -y && rm -rf /var/lib/apt/lists/*
# 8. 컨테이너 시작 시 기본 명령 설정 (선택 사항)
CMD ["bash"]
아래 명령어를 통해 dockerfile을 build한다.
1
2
# dockerfile이 존재하는 디렉토리에서 아래 명령어 입력
$ docker build -t ros2-cuda-humble:latest .
docker_compose.yaml 작성시
docker run 명령어를 사용해도 되지만 ROS2를 사용하면서 여러 센서나 GPU, GUI 포워딩을 위한 여러 복잡한 옵션들을 설정해주어야 하기 때문에 간편하게 docker-compose를 활용하는 것이 좋다.
GPU사용 옵션을 추가하기 위해 docker-compose.yaml은 아래와 같이 작성한다.
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
services:
humble_ws:
image: humble-gpu-env:latest
container_name: humble_ws
# GPU를 사용하는 경우 (NVIDIA GPU, nvidia-container-toolkit 설치 필요)
# runtime: nvidia
# environment:
# - NVIDIA_VISIBLE_DEVICES=all
# - NVIDIA_DRIVER_CAPABILITIES=all # compute,utility,graphics,video,display 등 필요한 기능 추가
# `--gpus` 옵션은 Docker Compose v3.8 이상에서만 지원되며,
# `runtime: nvidia`와 함께 사용하거나 단독으로 사용 가능합니다.
# 단독 사용 시에는 Docker Compose 파일의 최상위 level에
# `x-ndv: "gpu"`와 같이 서비스 정의 외부에 추가 설정이 필요할 수 있습니다.
# 여기서는 `runtime: nvidia`를 사용하는 것이 더 일반적입니다.
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all # 모든 GPU 사용
capabilities: [gpu, compute, utility, graphics] # 필요한 기능 명시
privileged: true
network_mode: host
ipc: host
runtime: nvidia
environment:
- DISPLAY=${DISPLAY}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- /dev/video0:/dev/video0
- .:/root/ros_ws
working_dir: /root/ros_ws
# 컨테이너가 시작될 때 자동으로 실행할 명령 (Dockerfile CMD를 오버라이드)
# `docker run`의 `--entrypoint` 또는 CMD와 유사
command: ["/bin/bash", "-c", "tail -f /dev/null"]
# 명명된 볼륨 정의 (컨테이너 간 데이터 공유 또는 영구 저장용)
volumes:
humble_ws:
# driver: local # 로컬 파일 시스템 드라이버 (기본값)
# name: custom_humble_ws_volume # 볼륨 이름 명시 (선택 사항)
docker-compose 사용하여 docker container 접속 방법
1
2
3
4
5
6
7
8
# 1. 터미널에서 docker-compose.yaml 파일이 있는 디렉토리로 이동
# 2. docker container 시작
$ xhost +local:docker # GUI 포워딩을 위해 X서버 접근 권한 부여
$ docker compose up-d # 백그라운드에서 실행
# 3. 컨테이너에 접속
$ docker exec -it humble_ws
컨테이너 사용 후 이를 중지하고 제거하기 위해 아래 명령어 입력
1
$ docker compose down

