-
Notifications
You must be signed in to change notification settings - Fork 249
tutorials vrx_docker_scripted
In this tutorial we automate the entire process of creating the competitor image using a script called a Dockerfile.
- This is one of two options for building a competitor image.
- The first option is described here.
- The primary advantage of this approach is that it is self-documenting and easily reproducible.
Follow the steps below to get a minimal version of a competitor image up and running:
-
Create a directory to store your
Dockerfileand any other files needed for your image.mkdir ~/my_vrx_docker; cd ~/my_vrx_docker -
Create a file called
Dockerfile, open it in a text editor, and copy in the following:FROM ros:noetic-ros-base # Install required utilities RUN apt update \ && apt install -y --no-install-recommends \ build-essential \ dirmngr \ git \ gnupg2 \ python3-rosdep \ python3-rosinstall \ python3-vcstools \ && rm -rf /var/lib/apt/lists/* # Install ROS packages RUN apt update \ && apt install -y --no-install-recommends \ ros-noetic-geographic-msgs \ && rm -rf /var/lib/apt/lists/* # Copy over script to Docker container COPY ./run_my_system.bash / # Use your ros_entrypoint COPY ./ros_entrypoint.sh /This script does the following:
- The
FROMcommand tells Docker to begin from theros:noetic-ros-baseimage. - The
RUNcommand executes arbitrary commands as if running them on the command line. In this case, they executeaptto install utilities and ROS packages. We don't actually need these packages yet. They are included as an examples of packages that might be useful later.- Note that a common pattern for
RUNcommands is to chain sequences of commands together using&&so each command is only run if the previous command succeeds. The reason for grouping commands together in this way is that environmental variables do not persist from one line of theDockerfileto the next. Only changes that would be written to disk persist. - Conversely, we clear out temporary files after each call to
aptto avoid written unneeded files to the disk and cluttering the image.
- Note that a common pattern for
- The
COPYcommand copies files from the host file system into the specified location in the docker image. In this case, the two files referenced do not yet exist. We will create them in the next step.
- The
By default, the ros:noetic-ros-base image we started from is configured to look for and execute the ros_entrypoint.sh script when it is run. We will create this script and use it to call a custom script that will control our WAMV.
-
First, use a text editor to create a file called
ros_entrypoint.shand copy the following text into the file:#!/bin/bash set -e # setup ros environment source "/opt/ros/$ROS_DISTRO/setup.bash" /run_my_system.bash -
Run
chmod +x ros_entrypoint.shto make it executable. -
Now use a text editor to create a file called
run_my_system.shand copy the following text into the file:#!/bin/bash # Create ros master if not already started rostopic list > /dev/null 2>&1 retVal=$? if [ $retVal -ne 0 ]; then roscore & echo "Wait for 5s to allow rosmaster to start" sleep 5s else echo "rosmaster already setup" fi # Send forward command RATE=1 CMD=2 echo "Sending forward command" rostopic pub /wamv/thrusters/left_thrust_cmd std_msgs/Float32 -r ${RATE} -- ${CMD} & rostopic pub /wamv/thrusters/right_thrust_cmd std_msgs/Float32 -r ${RATE} -- ${CMD} -
Run
chmod +x run_my_system.bashto make it executable.
We will now use the docker build command to create an image from the Dockerfile.
-
First, set up some useful variables, substituting the appropriate values below:
USERNAME=<dockerhub_username> IMAGE_NAME=<name_your_image> TAG=<image_version>-
USERNAMEmust match the username of your Dockerhub account. -
IMAGE_NAMEshould describe your image. It will be used to find your image locally and on Dockerhub. -
TAGcan be anything, but we recommend you use it to store version information.
-
-
Build the image:
docker build --tag ${USERNAME}/${IMAGE_NAME}:${TAG} . -
For example:
USERNAME=virtualrobotx IMAGE_NAME=vrx-competitor-example TAG=v2.2019 docker build --tag ${USERNAME}/${IMAGE_NAME}:${TAG} .
- Run your image
docker run -it ${USERNAME}/${IMAGE_NAME}:${TAG}- This will use the image you created in the previous step to run a container.
- The container will call the
ros_entrypoint.shscript, which will execute/run_my_system.bash. - The
-itoption specifies that we want an interactive terminal. This is useful for our current example because it allows us to see terminal output and kill the container withCTRL+Cwhen we're finished. (Without this option we would need to use adocker stopcommand to close the container.)
- You should see output that looks something like:
Wait for 5s to allow rosmaster to start ... logging to /root/.ros/log/b5d45620-ac91-11ec-a3ef-0242ac110002/roslaunch-2e00994a7ad0-45.log Checking log directory for disk usage. This may take a while. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http://2e00994a7ad0:45947/ ros_comm version 1.15.14 SUMMARY ======== PARAMETERS * /rosdistro: noetic * /rosversion: 1.15.14 NODES auto-starting new master process[master]: started with pid [54] ROS_MASTER_URI=http://2e00994a7ad0:11311/ setting /run_id to b5d45620-ac91-11ec-a3ef-0242ac110002 process[rosout-1]: started with pid [64] started core service [/rosout] Sending forward command - To verify that the script is working as expected, open a new terminal and get the container ID:
Copy the container ID in the far left column.
docker container ls - Now we will create a second connection to the running container:
Where
docker exec -it <container_id> bash<container_id>is the ID you just copied. This command will open an interactive bash session into the container. - In this session, check that your script is publishing data as expected.
source /opt/ros/noetic/setup.bash rostopic echo /wamv/thrusters/left_thrust_cmd - You should receive
/wamv/thrusters/left_thrust_cmddata (which is set to 2.0 in the script). - Switch back to your original terminal and hit
CTRL+Cto exit the container. - Note that this will also terminate your secondary bash session.
- Run
docker loginand enter your credentials. - Push your image:
docker push ${USERNAME}/${IMAGE_NAME}:${TAG} - You should be able to log onto your Dockerhub account at https://hub.docker.com and see your new repository.
- If you want to keep your repository private, you can click on your repository, then click Settings, then Make Private.
- To ensure we can access and evaluate your image, you can click Collaborators and add
virtualrobotx.
- Once you have a minimal image working, you can continue to develop it by adding commands to the
Dockerfileand rebuilding. - For efficiency, Docker will only rerun build commands starting from the first line in the Dockerfile which has changed, so it is advantageous to put commands that are unlikely to change (or take a long time to run) toward the top of the file.
- See Docker's Best Practices for Writing Dockerfiles for many useful tips on how to write good
Dockerfiles, as well as an extensive list of available commands.
- Because each command in a Dockerfile runs with a clean environment, commands that depend on sourcing many environment variables can be tricky.
- Commands that rely on ROS tools are an obvious example.
- The solution is generally to make sure the same run command both sets up the environment and immediately calls the command that requires it.
- For specific working examples, please see the minimal working examples provided in the
vrx-repositoryand discussed in the next tutorial.
| Back: Option 1: Interactive | Up: VRX Docker Image Overview | Next: Minimal Working Examples |
|---|