4

I want to use a customized ros-indigo on docker. I prepared the following Dockerfile

FROM ros:indigo-robot

RUN echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc
RUN mkdir -p /home/catkin_ws/src
WORKDIR /home/catkin_ws/src
RUN catkin_init_workspace
WORKDIR /home/catkin_ws
RUN catkin_make
RUN echo "source /home/catkin_ws/devel/setup.bash" >> ~/.bashrc

However, it throws me an error at both RUN catkin_init_workspace and RUN catkin_make that says

/bin/sh: catkin_make: command not found
The command '/bin/sh -c catkin_init_workspace' returned a non-zero code: 127

Surprisingly, it builds succesfully if I change RUN with CMD for catkin commands, i.e. the following Dockerfile builds just fine

RUN echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc
RUN mkdir -p /home/catkin_ws/src
WORKDIR /home/catkin_ws/src
CMD catkin_init_workspace
WORKDIR /home/catkin_ws
CMD catkin_make
RUN echo "source /home/catkin_ws/devel/setup.bash" >> ~/.bashrc

What is more surprising is these catkin commands work perfectly on a container that is built separately on top of any ros-indigo image.

This clearly indicates that either RUN is not an appropriate way to invoke catkin commands or I am invoking it incorrectly.

Now, given that the nature of CMD command is different from the RUN command, it does not make sense to use it in my case. Hence, I shall appreciate if someone can point me out the right way to do so.

Sanjay
  • 363
  • 1
  • 3
  • 14

2 Answers2

3

Your second case will build because CMD is not executed during the build. It simply defines the default command to execute when starting the container. See the docker CMD docs for more information.

The root of your problem is that ~/.bashrc is not being called in the shell used by the RUN instruction. As a result, the environment variables are not present to allow catkin_make or other ros commands to work. I address this issue in my images by running a command similar to the below.

RUN . /opt/ros/kinetic/setup.sh && \
    catkin_make

You will need to activate the environment in each RUN instruction that needs those environment variables because the shell is not re-used between RUN commands.

Edited to include the improvement from David Maze.

  • 1
    If you use the [standard `.` command](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_18) instead of bash's `source` extension command, it will work in all Bourne-compatible shells, including the minimal shell in Busybox and Alpine base images, and you won't need to set `SHELL`. – David Maze May 02 '19 at 00:19
  • Thanks for the suggestion, I've updated the answer accordingly. – Joseph Moster May 02 '19 at 00:28
  • This is great, it worked like magic. Thank you so much. For future readers, this is what the working Dockerfile looks like exactly `FROM ros:indigo-robot` `RUN apt-get update && apt-get install -y build-essential` `RUN mkdir -p /home/catkin_ws/src` `RUN . /opt/ros/indigo/setup.sh && catkin_init_workspace /home/catkin_ws/src` `RUN . /opt/ros/indigo/setup.sh && cd /home/catkin_ws && catkin_make` `RUN echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc` – Sanjay May 02 '19 at 02:08
3

You need to setup a proper bash environment for the commands to work (by default Docker uses sh to execute commands). These commands worked for me:

FROM ros:indigo-robot

RUN echo "source /opt/ros/indigo/setup.bash" >> ~/.bashrc
RUN mkdir -p /home/catkin_ws/src
WORKDIR /home/catkin_ws/src
#RUN /opt/ros/indigo/bin/catkin_init_workspace
RUN /bin/bash -c '. /opt/ros/indigo/setup.bash; catkin_init_workspace /home/catkin_ws/src'

WORKDIR /home/catkin_ws
RUN /bin/bash -c '. /opt/ros/indigo/setup.bash; cd /home/catkin_ws; catkin_make'
RUN echo "source /home/catkin_ws/devel/setup.bash" >> ~/.bashrc
Alassane Ndiaye
  • 4,427
  • 1
  • 10
  • 19