dockerfile 建立新 image
如果你想要建立一個 新的 Docker Image,基於 osrf/ros:indigo-desktop-full
,並且能夠運行 Gazebo,這裡是你的 Dockerfile 建立方式。
1. 建立 Dockerfile
在你的工作目錄中,建立一個 Dockerfile
檔案:
Dockerfile# 使用 OSRF 官方的 ROS Indigo + Gazebo 映像 FROM osrf/ros:indigo-desktop-full # 設定時區 (可選) ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y tzdata \ && ln -sf /usr/share/zoneinfo/Asia/Taipei /etc/localtime \ && dpkg-reconfigure -f noninteractive tzdata # 安裝必要的工具和 Gazebo 依賴 RUN apt-get update && apt-get install -y \ mesa-utils \ x11-xserver-utils \ xauth \ ros-indigo-gazebo-ros \ ros-indigo-gazebo-ros-control \ ros-indigo-gazebo-plugins \ ros-indigo-gazebo-msgs \ python-rosdep \ python-rosinstall \ python-rosinstall-generator \ python-wstool \ build-essential # 初始化 rosdep RUN rosdep init && rosdep update # 建立 ubuntu 使用者 (密碼 ubuntu) RUN useradd -m -s /bin/bash ubuntu && echo "ubuntu:ubuntu" | chpasswd && adduser ubuntu sudo # 切換到 ubuntu 使用者 USER ubuntu WORKDIR /home/ubuntu # 設定 ROS 環境變數 RUN echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc RUN echo "export DISPLAY=:0" >> ~/.bashrc # 預設啟動 Bash CMD ["/bin/bash"]
2. 建立 Docker Image
在 Dockerfile 所在的目錄,執行:
bashdocker build -t my_ros_gazebo .
這會建立一個名為 my_ros_gazebo
的 Docker Image。
3. 啟動容器
執行以下指令來啟動容器,並確保 GUI 可以顯示:
bashxhost +local:docker
docker run -it --rm \
--net=host \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--privileged \
--name ros_container \
my_ros_gazebo bash
進入容器後,你可以執行:
bashgazebo
確認 Gazebo 能夠顯示 GUI。
4. 儲存並重新使用 Image
如果你想要儲存這個 Image,讓它保持你安裝的環境:
bashdocker commit ros_container my_ros_gazebo:latest
然後下次就可以直接執行:
bashdocker run -it --rm --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --privileged my_ros_gazebo bash
總結
- 建立
Dockerfile
- 使用
docker build -t my_ros_gazebo .
來建立 Image - 使用
docker run
來執行,並確保 GUI 可以顯示 - 可以使用
docker commit
來保存修改後的 Image
這樣你就有一個完整的 ROS Indigo + Gazebo 環境,可以在 Docker 內運行 Gazebo GUI 🚀!
你說:
如果你的 Docker Image 顯示為 <none>
,表示它是個 dangling image(沒有被命名的 image)。你可以透過 docker tag
來修改名稱。
更改 Docker Image 的名稱
方法 1:使用 docker tag
執行以下指令,把 IMAGE ID
替換成你想要命名的 image ID:
bashdocker tag 29f1c59c8e0c my_ros_gazebo:latest
這樣 IMAGE ID = 29f1c59c8e0c
會變成:
nginxREPOSITORY TAG IMAGE ID CREATED SIZE
my_ros_gazebo latest 29f1c59c8e0c 8 seconds ago 2.21GB
如果你要給不同的版本命名,例如:
bashdocker tag 29f1c59c8e0c my_ros_gazebo:v1.0
方法 2:使用 docker commit
(如果正在運行)
如果你正在運行的容器已經修改過,並且想要存成新的 image:
bashdocker commit <container_id> my_ros_gazebo:latest
你可以用 docker ps -a
來查詢 container_id
。
方法 3:刪除舊的 unnamed images
如果你不需要 <none>
的 image,可以清理掉:
bashdocker image prune -a
這會刪除所有沒有被 tag 的 images。
檢查結果
執行:
bashdocker images
應該會看到:
nginxREPOSITORY TAG IMAGE ID CREATED SIZE
my_ros_gazebo latest 29f1c59c8e0c 8 seconds ago 2.21GB
這樣你就成功將 Docker Image 命名,之後可以用:
bashdocker run -it my_ros_gazebo:latest bash
來運行這個 Image 🚀!
你說:
要讓 Gazebo 在不同 Docker 容器中連接,需要確保 ROS Master 和 Gazebo 之間可以通訊,通常有以下方式:
方法 1:使用 --net=host
讓所有 Docker 共享網路
這是最簡單的方式,適用於 單機環境:
啟動 ROS Master 和 Gazebo(第一個 Docker 容器)
bashdocker run -it --rm \
--net=host \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--privileged \
--name ros_master \
my_ros_gazebo bash
進入容器後,執行:
bashroscore & gazebo --verbose
這樣 ROS Master 和 Gazebo 都會在 localhost
上運行。
在第二個 Docker 容器中連接
開啟新的終端機,然後啟動 第二個 ROS 容器:
bashdocker run -it --rm \
--net=host \
--name ros_client \
my_ros_gazebo bash
進入容器後,執行:
bashexport ROS_MASTER_URI=http://localhost:11311
export GAZEBO_MASTER_URI=http://localhost:11345
rostopic list
如果 rostopic list
可以顯示 Gazebo 的 Topic,表示連線成功!
方法 2:使用 Docker 網路橋接模式
這適用於 不同機器 或 不想使用 --net=host
的情況。
1. 創建 Docker 網路
bashdocker network create ros_network
2. 啟動 ROS Master 和 Gazebo
bashdocker run -it --rm \
--net=ros_network \
--name ros_master \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--privileged \
my_ros_gazebo bash
然後在容器內執行:
bashroscore & gazebo --verbose
3. 啟動第二個 ROS 容器
bashdocker run -it --rm \
--net=ros_network \
--name ros_client \
my_ros_gazebo bash
進入容器後,執行:
bashexport ROS_MASTER_URI=http://ros_master:11311
export GAZEBO_MASTER_URI=http://ros_master:11345
rostopic list
如果 rostopic list
顯示 Gazebo 的 topic,表示連線成功!
方法 3:在不同機器上的 Docker 容器連接
如果 ROS 和 Gazebo 在不同主機的 Docker 容器內運行,需要手動設定 IP。
1. 在 ROS Master 主機(A機器)執行
bashdocker run -it --rm \
--net=host \
--name ros_master \
my_ros_gazebo bash
然後執行:
bashexport ROS_IP=192.168.1.100 # A機器的IP
export ROS_MASTER_URI=http://192.168.1.100:11311
roscore &
gazebo --verbose
2. 在客戶端(B機器)Docker 容器內執行
bashdocker run -it --rm \
--net=host \
--name ros_client \
my_ros_gazebo bash
然後設定連接:
bashexport ROS_IP=192.168.1.101 # B機器的IP
export ROS_MASTER_URI=http://192.168.1.100:11311
export GAZEBO_MASTER_URI=http://192.168.1.100:11345
rostopic list
這樣 B機器的 ROS 也可以連接 A機器的 Gazebo。
總結
- 在同一台電腦上,使用
--net=host
是最簡單的方法 - 使用 Docker 自訂網路
docker network create ros_network
可以讓不同容器通訊 - 在不同機器上,手動設定
ROS_MASTER_URI
和GAZEBO_MASTER_URI
試試這些方法,你的 Docker 容器應該就能互相連接 ROS 和 Gazebo 🚀!
沒有留言:
張貼留言