welcom ! Handel home

2025年3月5日 星期三

dockerfile 建立新 image

 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 所在的目錄,執行:

bash
docker build -t my_ros_gazebo .

這會建立一個名為 my_ros_gazebo 的 Docker Image。


3. 啟動容器

執行以下指令來啟動容器,並確保 GUI 可以顯示:

bash
xhost +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

進入容器後,你可以執行:

bash
gazebo

確認 Gazebo 能夠顯示 GUI。


4. 儲存並重新使用 Image

如果你想要儲存這個 Image,讓它保持你安裝的環境:

bash
docker commit ros_container my_ros_gazebo:latest

然後下次就可以直接執行:

bash
docker run -it --rm --net=host -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --privileged my_ros_gazebo bash

總結

  1. 建立 Dockerfile
  2. 使用 docker build -t my_ros_gazebo . 來建立 Image
  3. 使用 docker run 來執行,並確保 GUI 可以顯示
  4. 可以使用 docker commit 來保存修改後的 Image

這樣你就有一個完整的 ROS Indigo + Gazebo 環境,可以在 Docker 內運行 Gazebo GUI 🚀!

你說:
REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 29f1c59c8e0c 8 seconds ago 2.21GB <none> <none> 7185793e11ee 7 weeks ago 5.79GB osrf/ros indigo-desktop-full 02cc98cfb8ba 14 months ago 2.16GB 如何更改 images 名稱

如果你的 Docker Image 顯示為 <none>,表示它是個 dangling image(沒有被命名的 image)。你可以透過 docker tag 來修改名稱。


更改 Docker Image 的名稱

方法 1:使用 docker tag

執行以下指令,把 IMAGE ID 替換成你想要命名的 image ID:

bash
docker tag 29f1c59c8e0c my_ros_gazebo:latest

這樣 IMAGE ID = 29f1c59c8e0c 會變成:

nginx
REPOSITORY TAG IMAGE ID CREATED SIZE my_ros_gazebo latest 29f1c59c8e0c 8 seconds ago 2.21GB

如果你要給不同的版本命名,例如:

bash
docker tag 29f1c59c8e0c my_ros_gazebo:v1.0

方法 2:使用 docker commit(如果正在運行)

如果你正在運行的容器已經修改過,並且想要存成新的 image:

bash
docker commit <container_id> my_ros_gazebo:latest

你可以用 docker ps -a 來查詢 container_id


方法 3:刪除舊的 unnamed images

如果你不需要 <none> 的 image,可以清理掉:

bash
docker image prune -a

這會刪除所有沒有被 tag 的 images。


檢查結果

執行:

bash
docker images

應該會看到:

nginx
REPOSITORY TAG IMAGE ID CREATED SIZE my_ros_gazebo latest 29f1c59c8e0c 8 seconds ago 2.21GB

這樣你就成功將 Docker Image 命名,之後可以用:

bash
docker run -it my_ros_gazebo:latest bash

來運行這個 Image 🚀!

你說:
ros gazebo 在不同 docker 中啟動要如何連接

要讓 Gazebo 在不同 Docker 容器中連接,需要確保 ROS Master 和 Gazebo 之間可以通訊,通常有以下方式:


方法 1:使用 --net=host 讓所有 Docker 共享網路

這是最簡單的方式,適用於 單機環境

啟動 ROS Master 和 Gazebo(第一個 Docker 容器)

bash
docker run -it --rm \ --net=host \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ --privileged \ --name ros_master \ my_ros_gazebo bash

進入容器後,執行:

bash
roscore & gazebo --verbose

這樣 ROS Master 和 Gazebo 都會在 localhost 上運行


在第二個 Docker 容器中連接

開啟新的終端機,然後啟動 第二個 ROS 容器

bash
docker run -it --rm \ --net=host \ --name ros_client \ my_ros_gazebo bash

進入容器後,執行:

bash
export 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 網路

bash
docker network create ros_network

2. 啟動 ROS Master 和 Gazebo

bash
docker run -it --rm \ --net=ros_network \ --name ros_master \ -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ --privileged \ my_ros_gazebo bash

然後在容器內執行:

bash
roscore & gazebo --verbose

3. 啟動第二個 ROS 容器

bash
docker run -it --rm \ --net=ros_network \ --name ros_client \ my_ros_gazebo bash

進入容器後,執行:

bash
export 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機器)執行

bash
docker run -it --rm \ --net=host \ --name ros_master \ my_ros_gazebo bash

然後執行:

bash
export ROS_IP=192.168.1.100 # A機器的IP export ROS_MASTER_URI=http://192.168.1.100:11311 roscore & gazebo --verbose

2. 在客戶端(B機器)Docker 容器內執行

bash
docker run -it --rm \ --net=host \ --name ros_client \ my_ros_gazebo bash

然後設定連接:

bash
export 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


總結

  1. 在同一台電腦上,使用 --net=host 是最簡單的方法
  2. 使用 Docker 自訂網路 docker network create ros_network 可以讓不同容器通訊
  3. 在不同機器上,手動設定 ROS_MASTER_URIGAZEBO_MASTER_URI

試試這些方法,你的 Docker 容器應該就能互相連接 ROS 和 Gazebo 🚀!

沒有留言: