脚本
#! /bin/bash
# A script to start ros:melodic-desktop-full in docker.
# You need to install the latest docker first.
# Author: liuqixuan.cn
# Email: [email protected]
# set -x
RES_NAME=ros
TAG=melodic-desktop-full
if [[ -z `which docker` ]]
then
echo "Can't find docker. You need to install the latest docker first."
exit
fi
if [[ `docker images $RES_NAME:$TAG | grep $TAG | wc -l` == 0 ]]
then
echo "Docker image $RES_NAME:$TAG not exist!"
echo
echo "Do you want to setup docker image now? It will take about 20 minutes and 3GB disk space."
read -t 20 -p "(wait 20 sec) Enter your choce: [y/N]" choice
choice=${choice:-n} # Default is No
if `echo $choice | grep -qi n`; then echo -e "\033[1m\033[32mAbort.\033[0m" && exit; fi # Uniform cases through grep
echo
dir="$(mktemp -d)"
script="$dir/Dockerfile"
if [[ ! (-f "$script" && -s "$script") ]]
then
echo -e "\033[1m\033[32mWrite script to\033[0m $script"
cat>"$script"<<EOF
# FROM ubuntu:18.04
FROM nvidia/cudagl:10.2-base-ubuntu18.04
LABEL Description="A Dockerfile to setup $RES_NAME:$TAG" Author="liuqixuan" Version="1.0"
# Official sources.list
ARG sourcelist="http://packages.ros.org/ros/ubuntu"
# Mirrors sources.list
# ARG sourcelist="http://mirrors.ustc.edu.cn/ros/ubuntu/"
# ARG sourcelist="http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/"
# ARG sourcelist="http://mirrors.sjtug.sjtu.edu.cn/ros/ubuntu/"
ARG workdir="/root/catkin_ws"
ARG DEBIAN_FRONTEND=noninteractive
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=YES
ENV XDG_RUNTIME_DIR="/tmp/runtime-root"
RUN set -x \
&& apt-get update \
&& apt-get install -y --no-install-recommends gnupg2 curl vim git xarclock \
&& sh -c '. /etc/lsb-release && echo "deb \${sourcelist} \${DISTRIB_CODENAME} main" > /etc/apt/sources.list.d/ros-latest.list' \
&& curl -sSL 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xC1CF6E31E6BADE8868B172B4F42ED6FBAB17C654' | apt-key add - \
&& apt-get update \
&& apt-get install -y --no-install-recommends ros-melodic-desktop-full \
&& echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc \
&& bash -c '. ~/.bashrc' \
&& apt-get install -y --no-install-recommends python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential \
&& rosdep init \
&& rosdep update \
&& apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir \${XDG_RUNTIME_DIR} && chmod 700 \${XDG_RUNTIME_DIR} \
&& mkdir \${workdir} \
&& set +x
WORKDIR \${workdir}
ENTRYPOINT ["/bin/bash"]
EOF
fi
echo -e "\033[1m\033[32m docker build -f $script -t $RES_NAME:$TAG --network host $dir\033[0m"
docker build -f "$script" -t $RES_NAME:$TAG --network host "$dir"
if [ $? == 0 ]
then
echo -e "\033[1m\033[32m\nBuild finished!\n\033[0m"
else
echo -e "\033[1m\033[31m\nBuild failed!\033[0m"
echo "Most problems are caused by network connection, please check your network on host machine, then try again."
exit 1
fi
rm -rf "$dir"
fi
# Enabel XServer
echo -e "\033[32m xhost +local:\033[0m"
xhost +local:docker
# Starting docker containers
CONTAINER_NAME=$RES_NAME
STATUS=$(docker ps -a --format "{
{.Names}}\t{
{.Status}}" | grep -m 1 $CONTAINER_NAME$'\t' | awk '{print $2}')
ENV="DISPLAY=$DISPLAY"
MOUNT_FROM="/tmp/.X11-unix/"
MOUNT_TO="/tmp/.X11-unix"
if [[ $1 == "-c" ]]
then
echo -e "\033[32m docker stop $CONTAINER_NAME\033[0m"
docker stop $CONTAINER_NAME
echo -e "\033[32m docker rm $CONTAINER_NAME\033[0m"
docker rm $CONTAINER_NAME
exit
fi
if [ -z $STATUS ]
then
CMD="docker run -it --gpus all --name $CONTAINER_NAME"
if [ -n $ENV ]; then CMD=$CMD" -e $ENV"; fi
if [[ -n $MOUNT_FROM && -n $MOUNT_TO ]]; then CMD=$CMD" -v $MOUNT_FROM:$MOUNT_TO"; fi
CMD=$CMD" $RES_NAME:$TAG"
echo -e "\033[32m $CMD\033[0m"
$CMD
elif [ $STATUS == "Up" ]
then
echo -e "\033[33m Attaching to $CONTAINER_NAME \033[0m"
docker exec -it $CONTAINER_NAME bash
elif [ $STATUS == "Exited" ]
then
echo -e "\033[32m docker restart $CONTAINER_NAME \033[0m"
docker restart $CONTAINER_NAME
echo -e "\033[32m docker exec -it $CONTAINER_NAME bash \033[0m"
docker exec -it $CONTAINER_NAME bash
else
echo -e "\033[31m Unknown $CONTAINER_NAME Status: $STATUS \033[0m"
fi
使用説明書
ローカル PATH ( など~/.local/bin
)の下に新しいファイルを作成しros-docker-run
、上記のコードを貼り付け、chmod 755 ros-docker-run
実行可能権限を追加するために使用します。実行スクリプトを使用すると、ros イメージが自動的にビルドされ、コンテナーが起動されます。コンテナーが以前にビルドまたは起動されている場合は、コンテナーに再接続されます
。を使用すると、コンテナが空になって削除され、すべての変更が無効になります。最初に必ず変更を保存してください。ros-docker-run
ros-docker-run -c
docker commit
脚本解析
まず、ホストに docker がインストールされているかどうかを確認し、インストールされていない場合は終了します。
次に、このスクリプトで ros イメージが構築されているかどうかを確認し、構築されていない場合は、/tmp に一時ディレクトリが生成され、そのディレクトリに Dockerfile の内容が出力され、イメージが構築さdir="$(mktemp -d)"
れscript="$dir/Dockerfile"
ますdocker build -f "$script" -t $RES_NAME:$TAG --network host "$dir"
。イメージの名前を付けます$RES_NAME:$TAG
。このコードは に適していますros:melodic-desktop-full
。
rosdep init
接続できないためにエラーを報告する一般的な実行についてはraw.githubusercontent.com
、最初に Dockerfile 内のホストを変更するステートメントを追加し、その後--network host
ビルド コマンドにオプションを追加するように変更しました。このように、ホスト マシンがアドレスにアクセスできる限り、ミラーもそのアドレスにアクセスできるはずです。
したがって、ホストの/etc/hosts
ファイルを変更して追加することで、199.232.96.133 raw.githubusercontent.com
この問題を解決できます。
他のネットワーク問題の解決策も同様です。
次に、スタートアップフェーズが始まります。
まず、ホストの XServer がローカル コンテナからの出力を受信できるようにします。xhost +local:
次に、コンテナの現在のステータスを確認します。ステータスが空の場合は、コンテナが起動されていないことを意味します。$CMD
起動コンテナを使用します。
CMD="docker run -it --gpus all --name $CONTAINER_NAME" -e $ENV -v $MOUNT_FROM:$MOUNT_TO $RES_NAME:$TAG
--gpus all
: Nvidia GPU サポートを有効にする--name $CONTAINER_NAME"
:$CONTAINER_NAME
後でコンテナの状態を確認するために設定すると便利ですENV="DISPLAY=$DISPLAY"
: モニターIDを設定します$MOUNT_FROM:$MOUNT_TO
: x11 インターフェイスを設定します
ピットに足を踏み入れて注意してください。
- このオプションを追加すると、
--network=host
コンテナ内でrosrun rviz rviz
GUI を必要とするノードを実行するときに次のエラーが報告されます。
dbus[XXX]: The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.
- オプションを追加する必要がある場合は、GUI を正常に表示するために同時にオプションを
--network=host
追加する必要がありますが、これはホスト システム ファイルに脅威を与える可能性があるため、推奨されません。--priviledged
コンテナーが実行中 (Up) の場合は、docker exec -it $CONTAINER_NAME bash
アクセス コンテナーを使用します。これは、新しいターミナル ウィンドウを開くのと同じです。
コンテナが停止 (Exited) している場合は、再起動されdocker restart $CONTAINER_NAME
て接続されます。
その他の珍しい状態については、ご自身で対処してください。
Dockerfile の解析
以下に、Dockerfile の内容 (スクリプトの 33 行目から 64 行目) を簡単に紹介します。
最初はこれをFROM ubuntu:18.04
使ってビルドしていましたが、後でガゼボなどのコンポーネントにはまだ nvidia ドライバーのサポートが必要であることがわかり、ベースイメージを に変更しましたFROM nvidia/cudagl:10.2-base-ubuntu18.04
。
次に ROS ソースです。デフォルトでは公式ソースが使用されます。ネットワークが利用できない場合は、後で他のミラー ソースのコメントをキャンセルして、公式ソースを置き換えることができます。
次に、デフォルトの作業ディレクトリがあります/root/catkin_ws
。
次に、対話型の動作と、apt を禁止する警告文があります。
このXDG_RUNTIME_DIR
設定の目的は、GUI 使用時に必ず表示される警告を回避することですQStandardPaths: XDG_RUNTIME_DIR not set
。(私の他のブログを参照してください)
次に、apt によってインストールされるツールがあります。このうち、gnupg2
と はcurl
apt-keyのインストールが必要で、残りのvim、git、xarクロックはよく使われるツールで、xarクロックはGUI表示機能をテストできます。
次のステップは、ros-melodic-desktop-full オントロジーとさまざまなサードパーティ ライブラリをインストールすることです。
次に、ROS の構築です。
次に、さまざまなキャッシュを削除します。
次に、XDG_RUNTIME_DIR
権限を作成して設定します。
最後に、作業ディレクトリに切り替えて、ユーザーがイメージをロードするためのデフォルトのエントリ ポイントを設定します/bin/bash
。