Back to main Docker page
Creates a Dockerfile called Dockerfile-ros-melodic :
# # this dockerfile roughly follows the 'Ubuntu install of ROS Melodic' from: # http://wiki.ros.org/melodic/Installation/Ubuntu # and Niryo ROS installation : # https://docs.niryo.com/dev/ros/v3.2.0/en/source/simulation.html # # start from base image Ubuntu 18.04 ARG BASE_IMAGE=ubuntu:18.04 FROM ${BASE_IMAGE} # label this new image LABEL maintainer="benblop@gmail.com" LABEL version="0.1" LABEL description="basic ROS melodic Docker image for teaching" ENV ROS_DISTRO=melodic ENV ROS_ROOT=/opt/ros/${ROS_DISTRO} # disable prompt during package installation ENV DEBIAN_FRONTEND=noninteractive # # add the ROS deb repo to the apt sources list # RUN apt-get update && \ apt-get install -y --no-install-recommends \ git \ cmake \ build-essential \ curl \ wget \ gnupg2 \ lsb-release \ ca-certificates \ && rm -rf /var/lib/apt/lists/* RUN sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - # # install ROS packages # RUN apt-get update && \ apt-get install -y --no-install-recommends \ ros-${ROS_DISTRO}-desktop-full \ python-rosdep \ && rm -rf /var/lib/apt/lists/* # # init/update rosdep # RUN apt-get update && \ cd ${ROS_ROOT} && \ rosdep init && \ rosdep update && \ rm -rf /var/lib/apt/lists/* # # always initialize ROS by default RUN echo "# init ROS" >> /etc/bash.bashrc RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /etc/bash.bashrc # define a user ENV newuser=rosuser RUN useradd -ms /bin/bash ${newuser} USER ${newuser} WORKDIR /home/${newuser}
Create the image :
docker build -f Dockerfile-ros-melodic -t ros-melodic .
run the image interactively, try running roscore at prompt, then stop roscore with CTRL-C and leave the container with CTRL-D :
docker run -it ros-melodic:latest /bin/bash roscore CTRL-C CTRL-D
In this container, a standard user (called rosuser) has been created. To run the conatiner as root user, add -u root in the command line :
docker run -u root -it ros-melodic:latest /bin/bash
To get the image name (ros-melodic:latest) , just type :
docker images
Save the container so it can be moved and restored on another host (from this link)
docker export container-name | gzip > container-name.gz zcat container-name.gz | docker import - container-name
Open a terminal, start the container and execute roscore
docker run --rm --name ROS-Melodic-Test -it ros-melodic:latest /bin/bash roscore
In a second terminal, verify that ROS is running, first we need to get the ID (and the name) of the container. Here the name is ROS-Melodic-Test and the ID is c012f4611c54. Then using the ID (or the name) of the container we can get its IP address by processing the docker inspect command output :
docker container ls docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ROS-Melodic-Test
Here the IP address is 172.14.0.1. We can now setup the host so it can use ROS running in the ROS-Melodic-Test container :
export ROS_MASTER_URI=http://172.14.0.1:11311 rostopic list
This container aims at starting roscore without starting an interactive session and typing roscore. The dockerfile starts from the previous image and looks like this :
# start from base image ros-melodic:latest ARG BASE_IMAGE=ros-melodic:latest FROM ${BASE_IMAGE} SHELL ["/bin/bash", "-c"] COPY ./ros_init.bash . ENTRYPOINT ["/bin/bash","/home/rosuser/ros_init.bash"] CMD /opt/ros/melodic/bin/roscore
The command (CMD) is roscore and the entry point (ENTRYPOINT) is used to to initialize ROS with the following script (ros_init.bash) :
#!/bin/bash set -e #setup ros environment source "/opt/ros/$ROS_DISTRO/setup.bash" #setup workspace if it exists if [ -n "$WORKSPACE_NAME" ]; then if [ ! -e "/root/$WORKSPACE_NAME/devel/setup.sh" ]; then previousDirectory=$(pwd) cd /root/$WORKSPACE_NAME catkin_make cd $previousDirectory fi source "/root/$WORKSPACE_NAME/devel/setup.sh" fi exec "$@"
In a first terminal, roscore is started
docker run --rm --name "ROS-Melodic-roscore" ros-melodic-roscore:latest
In a second terminal we get the IP address of the container (here 170.14.0.1) and we try to get the default topics from roscore :
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ROS-Melodic-roscore export ROS_MASTER_URI=http://172.14.0.1:11311 rostopic list
We should see the default /rosout and /rosout_agg topics. Now we will wait for a /counter topic to be published :
rostopic echo /counter
The publication of this /counter topic we be done in a container. We start an interactive session on ROS-Melodic-Test container. In a third terminal, using docker inspect, we can get the IP address of this container (here 170.14.0.2) so we can connect both containers on the same **roscore*.
docker run --rm --name "ROS-Melodic-Test" -it ros-melodic:latest /bin/bash export ROS_MASTER_URI=http://172.14.0.1:11311 export ROS_IP=172.14.0.2 rostopic pub -r 1 /counter std_msgs/Int32 "data: 8"
In the last line we are sending an integer value (8) in the topic /counter every second. Going back in second terminal, the value 8 should be echoed every second. Other terminals can be connected to the ROS-Melodic-Test container. For example, a new session can be started in a fourth terminal as follows :
docker exec -it ROS-Melodic-Test /bin/bash export ROS_MASTER_URI=http://172.14.0.1:11311 export ROS_IP=172.14.0.2 rostopic pub -r 4 /counter std_msgs/Int32 "data: 1"
In the last line we are sending an integer value (1) in the topic /counter at 4 Hz (every 250 ms). Going back in second terminal, the values 1 and 8 should be echoed with corresponding rates , 1Hz and 4Hz.