본문 바로가기
로봇 이야기/ros2

ROS2 Foxy Docker 이미지 만들기

by 노땅엔진니어 2023. 3. 2.

ROS2 버전은 우분투 버전에 영향을 많이 받습니다. ROS2-foxy 버전은 우분투 20.04 버전에 설치하는 것을 권장하고, ROS2-humble 버전은 우분투 22.04 버전을 권장합니다. 특히 ROS2의 경우 우분투 버전에 영향을 많이 받기 때문에 도커(docker)이미지로 만들어서 구축을 하면 컴퓨터에 ROS2 버전에 따라 여러 개의 우분투 버전을 설치할 필요가 없습니다.

1. 도커(Docker)

도커는 컨테이너(container)기반의 오픈소스로써 가상화 플랫폼 입니다. 도커를 통해 ROS2-foxy 가상 이미지를 만드는 과정과 사용하는 방법에 대해 설명을 합니다. 이 문서는 도커에 대해 알고 있어야 합니다.

1.1. 도커 설치

도커는 다른 패키지처럼 패키지로 설치하지 않고 도커의 홈페이지에 있는 설치 스크립트를 다운로드 받아 설치합니다. 그러므로 우분투 컴퓨터에 curl 패키지가 먼저 설치되어 있어야 합니다.

당연한 이야기지만, 도커를 설치하기 위해서는 루트 권한을 갖고 있어야 합니다. 다음은 curl 패키지를 설치하고, 도커 스크립트를 다운로드 받아 루트권한으로 스크립트를 실행 합니다.

$ sudo apt install curl
$ curl -fsSL https://get.docker.com/ | sudo sh

도커를 설치 한 후에 리부팅을 해도 되지만 설치 후에 다음과 같이 도커 서비스를 시작하면 다음과 같이 수동으로 서비스를 실행 할 수 있습니다.

$ sudo systemctl start docker
$ sudo systemctl enable docker

도커는 항상 루트(root)권한으로 실행을 해야 합니다. 도커 실행할 때마다 매번 sudo 명령어로 실행하는 것은 상당히 귀찮은 일입니다. 다음과 같이 도커에 사용자를 도커 그룹에 추가를 하면 매번 sudo 명령으로 실행하지 않아도 됩니다.

다만, 아래와 같이 권한을 주었을 때는 도커 서비스를 재시작으로는 적용이 되지 않는 경우가 있어 시스템 리부팅을 권장 합니다.

$ sudo usermod -aG docker $USER     # 현재 접속중인 사용자에게 권한주기
$ sudo usermod -aG docker your-user # your-user 사용자에게 권한주기

1.2. 도커 이미지 만들기

도커 이미지는 도커 허브(docker-hub)에 이미 만들어진 이미지를 사용할 수 있지만, 직접 이미지를 만들고 도커 허브에도 올릴 수 있습니다.

도커 이미지를 만들기 위해서는 먼저 Dockerfile이라는 도커 스크립트 파일을 만들어야 합니다. 이 문서에서는 도커 스크립트에 대해서는 다루지 않습니다. (자세한 문서는 https://docs.docker.com/를 참조 합니다.)

1.2.1. Dockerfile

Dockerfile에서 첫 번째 문자 #이 있으면 해당 줄은 주석(comment)로 인식을 합니다.

###############################################################################
# 
# Copyright (C) 2023
# 
# Dockerfile for ROS2-foxy
#
# by duvallee
# 
###############################################################################

도커 허브(docker-hub)로 부터 이미지를 가져오기

필요에 따라 다른 사람이 이미 작성해 놓은 도커 이미지를 가져다가 사용할 수 있습니다. ros2 버전의 경우에 우분투 버전 영향을 많이 받기 때문에 다음과 같이 우분투와 ros2를 도커 허브에 있는 이미지를 가져 옵니다.

도커 이미지를 다시 만드는 가장 큰 이유가 ros2 버전에 따라 우분투 버전의 영향 때문 입니다. 도커 이미지를 통하지 않고 컴퓨터에 직접 우분투 버전을 설치할 때, 한 가지 ros2 버전을 사용할 때는 크게 문제가 없으나, 여러가지 버전을 사용할 때는 매번 우분투를 다시 설치하거나, 저장 장치를 여러 개의 파티션으로 나누어 우분투의 여러 버전을 설치해야 하는 불편함이 있습니다.

또 하나는 리눅스나 ros가 모두 오픈 소스(open source)기반의 소프트웨어로써 버전에 따른 소프트웨어의 종속성(dependency) 문제가 많습니다. 어떤 소프트웨어는 특정 라이브러리 버전 1.0에 종속성을 갖고 있는데 다른 소프트웨어는 해당 라이브러리 버전을 1.1에 종속성을 갖는다고 했을 때, 해당 소프트웨어를 구동할 때마다 특정 라이브러리의 버전을 번갈아 설치해야 합니다. 또한 패키지간 종속문제가 자주 발생하는 것이 상업용 소프트웨어보다 오픈 소스에서 좀 더 빈번하게 발생 합니다.

도커 이미지를 만들고 사용하게 되면, 저장장치 및 메모리를 좀 더 많이 사용하고 직접 컴퓨터에서(native) 실행하는 것보다 실행 속도가 느리지만, 도커는 이런 단점을 충분히 커버(cover)할 수 있습니다.

FROM ubuntu:20.04
FROM ros:foxy

우분투 저장소 변경하기

도커 허브에 있는 우분투의 이미지는 우분투 저장소가 미국으로 되어 있습니다. 국내에서는 미국 우분투 저장소에 연결하는 것보다 국내에 있는 우분투 미러 저장소로 변경을 하면 소프트웨어 설치를 할 때 좀 더 원할하게 됩니다.

국내에는 2개의 미러사이트가 있는데 다음카카오가 좀 더 원할 합니다.

# ----------------------------------------------------------------------------
# changed mirror site from archive.ubuntu.com to kr.archive.ubunyu.com
RUN sed -i 's/archive.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/ftp.daumkakao.com/g' /etc/apt/sources.list

저장소를 변경한 후에는 다음과 같이 update를 해 주어야 하고 우분투 패키지 설치관련 프로그램을 설치 합니다.

# ----------------------------------------------------------------------------
RUN apt-get update
RUN apt-get -y install apt-utils

64-비트 우분투에서 32-비트 소프트웨어 실행

최근에는 거의 모든 소프트웨어가 64비트이기 때문에 필요가 없지만, 간혹 예전 소프트웨어 중에 아직도 32비트가 있습니다. 64비트 우분투에서 32비트 소프트웨어를 실행하기 위해서는 다음과 같이 아키텍쳐와 라이브러리를 설치해야 합니다.

32비트 소프트웨어를 사용할 일이 없는 경우라면 생략을 해도 됩니다.

# -----------------------------------------------------------------------------
# running 32 bit program on 64 bit uBuntu
RUN dpkg --add-architecture i386
RUN apt-get -y install libc6-i386

로케일(locale)

ros2가 주로 영문권(미국)에서 개발되었기 때문에 간혹 한글 환경으로 되었을 때 문제가 발생하는 경우가 종종 있습니다. 영어로 설정 해 놓으면 이런 문제에서 좀 더 자유로울 수 있습니다.

도커 허브에 있는 우분투 이미지는 시간을 세계시간(UTC, Universal Time Coordinated) 0(그리니치 천문대, 영국)으로 설정됩니다. 서울은 "UTC+9:00"로써 시스템에서 파일을 생성하면 시간이 "UTC+0:00"기준으로 표시되기 때문에 파일의 시간으로 확인할 때 많이 불편 합니다. 우분투 시스템에서 표시되는 시간을 "UTC+9:00"(서울)로 변경을 합니다.

# -----------------------------------------------------------------------------
# add locale package & set
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -y install locales
RUN dpkg-reconfigure locales
RUN locale-gen en_US.UTF-8
RUN update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
RUN export LANG=en_US.UTF-8

# -----------------------------------------------------------------------------
# change time-zone from UTC to Seoul of korea
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

필수 패키지

ros2 및 개발에 필요한 필수 패키지를 추가 합니다.

# -----------------------------------------------------------------------------
# install package
RUN apt-get install -y  \
                     curl  \
                     sudo  \
                     vim   \
                     unzip \
                     tree  \
                     xterm \
                     sed   \
                     flex  \
                     screen   \
                     git-core \
                     gnupg2   \
                     lsb-release \
                     build-essential \
                     cmake \
                     git   \
                     libbullet-dev  \
                     python3-flake8 \
                     python3-pip \
                     python3-pytest-cov \
                     python3-rosdep \
                     python3-setuptools \
                     wget
 
RUN python3 -m pip install -U   \
                     argcomplete \
                     flake8-blind-except \
                     flake8-builtins \
                     flake8-class-newline \
                     flake8-comprehensions \
                     flake8-deprecated \
                     flake8-docstrings \
                     flake8-import-order \
                     flake8-quotes \
                     pytest-repeat \
                     pytest-rerunfailures \
                     pytest
RUN apt-get install --no-install-recommends -y \
                     libasio-dev \
                     libtinyxml2-dev \
                     libcunit1-dev

그래픽 드라이버 패키지

공용으로 제작하는 도커 이미지에는 하드웨어에 종속적인 패키지를 추가하지 않는 것이 좋습니다. 이 문서는 개인이 사용할 목적이기 때문에 해당 그래픽 드라이버 패키지를 설치하지 않으면, 도커 이미지를 실행한 후에 매번 그래픽 드라이버 패키지를 설치해야 합니다.

ros2와 gazebo 소프트웨어는 로봇을 시뮬레이션 GUI 소프트웨어로써 그래픽 카드(Graphic Card)에 영향을 받습니다. 이 문서에서 작성된 도커 이미지를 실행되는 우분투 컴퓨터의 그래픽 카드 드라이버를 설치해야 원할하게 ros2와 gazebo 소프트웨어를 실행 할 수 있습니다.

다음은 NVIDIA사의 RTX 1060 모델이 설치된 컴퓨터에 필요한 NVIDIA사의 그래픽 드라이버를 설치하는 예 입니다.

추가로 "mesa-utils"는 그래픽 카드가 지원하는 OpenGL 버전 확인을 위해 설치를 합니다.

RUN apt-get install -y mesa-utils nvidia-driver-515

우분투 패키지 저장소 종류

우분투의 저장소(repository)는 6가지 종류가 있습니다.

  • Main : 기본 저장소로써 무료 및 오픈 소스 소프트웨어 또는 FOSS(무료 및 오픈 소스 소프트웨어)만 포함되어 "Main"에서 제공하는 모든 소프트웨어는 제한없이 자유롭게 배포 할 수 있습니다.
  • Universe : "Main"과 같이 FOSS를 제공합니다. 차이점은 정기적인 보안 업데이트를 보장하는 것이 우분투가 아닌 각각의 커뮤니티 입니다. ROS 소프트웨어는 "Main"이 아닌 "Universe" 입니다.
  • Multiverse : FOSS가 아닌 소프트웨어가 포함되어 있으며, 우분투는 라이선스 및 법적 문제가 발생할 후 있습니다.
  • Restricted : 보통은 그래픽 카드, 터치 패널과 같이 하드웨어에 관련된 저장소 입니다.
  • Partner : 파트너가 제공하는 우분투에서 컴파일한 독정 소프트웨어가 포함되어 있습니다.

ROS2를 위해 "Universe" 저장소를 활성화 합니다.

# -----------------------------------------------------------------------------
RUN apt-get install -y software-properties-common
RUN add-apt-repository universe

ROS 데스크탑(desktop) 버전 및 gazebo 설치

ROS2와 gazebo를 설치하여 시뮬레이션을 실행하기 위해서는 ros2의 데스크탑(desktop) 버전을 설치해야 합니다. 다음은 관련 패키지 및 gazebo 패키지를 도커 이미지에 추가를 합니다.

RUN apt-get update
RUN apt-get install -y ros-foxy-desktop
RUN apt-get install -y ros-foxy-joint-state-publisher-gui 
RUN apt-get install -y ros-foxy-xacro 
RUN apt-get install -y python3-colcon-common-extensions 
RUN apt-get install -y python3-vcstool

# -----------------------------------------------------------------------------
RUN apt-get install -y ignition-fortress

업데이트 임시 파일 및 정리

소프트웨어 설치를 한 후에 업데이트 파일이나 임시파일에 도커 이미지에 남아 있으면 도커 이미지 파일만 커지게 됩니다. 필요없는 파일을 정리 합니다.

# -----------------------------------------------------------------------------
# clean update files
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* -vf
RUN apt-get update

사용자 추가 및 편의성 추가

도커를 통해 도커 이미지를 실행하는 경우

  • 호스트(host, docker daemon) : 도커 서비스가 실행되는 컴퓨터 입니다.
  • 클라이언트(client) : 도커 이미지를 통해 실행되는 가상환경 입니다.

가상 환경에서의 저장 공간은 가상 환경이 종료 한 후에 사라지게 됩니다. 이로 인하여 도커는 호스트의 저장 공간을 도커 가상환경 실행할 때 공유할 수 있도록 합니다. 호스트의 저장 공간에서 작업을 하게 되면 도커 가상환경 종료 후에도 작업한 데이터가 유지 됩니다.

호스트가 루트로 로그인을 하고 도커 가상 환경을 루트로 로그인을 하여 작업을 하게 되는 경우에는 큰 문제가 없으나 일반 유저로 호스트의 저장 공간을 공유한 후에 가상 환경에서 루트로 로그인을 하여 작업을 하게 되면, 가상 환경 종료 후에 호스트에 공유되었던 저장 공간에 새로 생성된 파일들의 권한은 루트로 되어 있어 간혹 불편할 때가 많습니다.

이러한 문제로 호스트의 사용자 ID(user id)와 가상 환경의 사용자 ID를 동일하게 놓으면 가상환경 종료 후에도 파일의 권한 문제를 해결할 수 있습니다.

다음 예는 호스트 컴퓨터의 사용자의 ID가 1001일 때 도커 이미지의 사용자를 user(호스트 컴퓨터의 사용자 이름과 달라도 됩니다.)에 사용자 ID를 1001로 사용자를 추가하는 예 입니다.

# -----------------------------------------------------------------------------
ENV RUN_USER user
ENV DEFAULT_PASSWORD 1234
ENV RUN_UID 1001

# -----------------------------------------------------------------------------
# change root password
RUN echo "root:$DEFAULT_PASSWORD" | chpasswd

# -----------------------------------------------------------------------------
# add user
RUN useradd -m -s /bin/bash -u $RUN_UID $RUN_USER
RUN id $RUN_USER
RUN echo "$RUN_USER:$DEFAULT_PASSWORD" | chpasswd

도커 빌드는 루트로 로그인 되어 있어 중간에 sudo 명령을 사용하지 않아도 됩니다. 도커 빌드 중간에 추가된 사용자로 로그인을 할 수 있으며, 사용자의 쉘 환경을 변경 할 수 있습니다.

# -----------------------------------------------------------------------------
# login as RUN_USER
USER $RUN_USER
WORKDIR /home/$RUN_USER

# -----------------------------------------------------------------------------
# environment
# Sets language to UTF8 : this works in pretty much all cases
ENV LANG en_US.UTF-8
ENV LS_COLORS "di=00;36:fi=00;37"
ENV PATH=/bin:/sbin:/usr/bin:/usr/local/bin:$PATH

# -----------------------------------------------------------------------------
RUN echo "" >> /home/$RUN_USER/.bashrc
RUN echo "alias l='ls -l'" >> /home/$RUN_USER/.bashrc
RUN echo "alias ll='ls -al'" >> /home/$RUN_USER/.bashrc
RUN echo "LS_COLORS=\"di=00;36:fi=00;37\"" >> /home/$RUN_USER/.bashrc
RUN echo "" >> /home/$RUN_USER/.bashrc

# -----------------------------------------------------------------------------
# for ROS2
RUN echo "source /opt/ros/foxy/setup.bash" >> /home/$RUN_USER/.bashrc
RUN echo "export RMW_IMPLEMENTATION=rmw_fastrtps_cpp" >> /home/$RUN_USER/.bashrc
RUN echo "glxinfo | grep \"OpenGL version\"" >> /home/$RUN_USER/get_opengl.sh
RUN echo "ign gazebo empty.sdf --render-engine ogre" >> /home/$RUN_USER/old_gazebo.sh
RUN echo "ign gazebo empty.sdf" >> /home/$RUN_USER/gazebo.sh
RUN chmod 775 /home/$RUN_USER/get_opengl.sh
RUN chmod 775 /home/$RUN_USER/old_gazebo.sh
RUN chmod 775 /home/$RUN_USER/gazebo.sh

우분투에서 사용자를 추가하면 보안문제로 인하여 sudo 권한이 없습니다. 추가한 사용자가 sudo 권한이 없으면 불편하기 때문에 다음과 같이 사용자에게 sudo 권한을 추가 합니다.

sudo 권한을 추가하기 위해선 위에서 사용자로 로그인을 다시 루트로 로그인을 해야 합니다.

# -----------------------------------------------------------------------------
USER root

# -----------------------------------------------------------------------------
# add user to sudoers
RUN chmod 0666 /etc/sudoers
RUN echo "$RUN_USER  ALL=(ALL:ALL) ALL " >> /etc/sudoers
RUN chmod 0440 /etc/sudoers

도커 이미지가 실행될 때 사용자로 로그인을 하도록 다음과 같이 합니다.

1.2.2 도커 빌드(docker build)

도커 이미지는 이름과 버전으로 빌드를 합니다. Dockerfile이 있는 디렉토리에서 다음과 같이 빌드를 합니다.

이미지 이름 : ros2-ubuntu
버전 : foxy-focal-rtx1060

$ docker build -t ros2-ubuntu:foxy-focal-rtx1060 .

1.2.3 도커 이미지 실행

도커 이미지는 시뮬레이션을 위해서는 GUI가 필요하기 때문에 xterm에서 실행해야 합니다. 다만, 시뮬레이션을 하지 않고 단순히 ROS2 패키지를 빌드한다면 일반 terminal에서 실행을 해도 됩니다.

$ docker run --rm -it --privileged  --net=host -e DISPLAY=$DISPLAY \
           -v /tmp/.X11-unix:/tmp/.X11-unix  \
           -v /tmp/runtime-user:/tmp/runtime-user \
           --name ros2-os -v $PWD:/home/user/project ros2-ubuntu:foxy-focal-rtx1060 /bin/bash

-v 옵션은 호스트 시스템과 도커 컨테이너 간 파일 시스템을 공유하는 옵션 입니다.
-- name ros2-os

* 다른 터미널을 연 후에 $ docker attach ros2-os 와 같이 다른 터미널에서 연결을 할 수 있습니다.

Dockerfile
0.01MB

'로봇 이야기 > ros2' 카테고리의 다른 글

ROS2 Humble Docker 이미지 만들기  (0) 2023.03.03
기구학 (Kinematics) 이란?  (0) 2023.01.03
매니퓰레이터(manipulator) URDF 모델링  (0) 2022.12.31
xacro (XML macro)  (0) 2022.12.30
URDF(Unified Robot Description Format)란?  (0) 2022.12.13

댓글