"/bin/sh: 1: MY_COMMAND: not found"
Error
During docker build -t MY_IMAGE_NAME ., using a Dockerfile for a ROS project, at line
RUN source /opt/ros/melodic/setup.bashthe following error appeared:
=> ERROR [stage-2 19/19] RUN source /opt/ros/melodic/setup.bash
[...]
#23 0.404 /bin/sh: 1: source: not found
------ executor failed running [/bin/sh -c source /opt/ros/melodic/setup.bash]: exit code: 127Test
To test this, I created an image of a step before the error step, and checked the command inside the container: and it worked. Thus, the "source" command is available in the bash of the container. How can it be not available in the image, then?
docker run -dit --name MY_CONTAINER_NAME -v /opt/ros/melodic/ MY_IMAGE:latest
docker exec -it MY_CONTAINER_NAME /bin/bashFyi: -v /opt/ros/melodic/ mounts the volume -v, else /opt/ros/melodic/ would be empty. By default, only the "build context", in this case where you start the Dockerfile, is not empty.
Now in the container, in the bash (which was loaded using /bin/bash above):
root@1b2bdc5131sy:/# cd opt
root@1b2bdc5131sy:/opt# cd ros
root@1b2bdc5131sy:/opt/ros# ls
melodic
root@1b2bdc5131sy:/opt/ros# cd melodic
root@1b2bdc5131sy:/opt/ros/melodic# ls
_setup_util.py env.sh include local_setup.bash local_setup.zsh setup.sh share
bin etc lib local_setup.sh setup.bash setup.zsh
root@1b2bdc5131sy:/opt/ros/melodic# ls
_setup_util.py env.sh include local_setup.bash local_setup.zsh setup.sh share
bin etc lib local_setup.sh setup.bash setup.zshAnd I could have just checked it directly anyway, works:
root@1b2bdc5131sy:/# source /opt/ros/melodic/setup.bash Question
Since the "source" command works in the container MY_CONTAINER_NAME, how can I get the bash shell working in the underlying image MY_IMAGE_NAME during the docker build of the Dockerfile, instead of using the sh shell?
1 Answer
Taken from /bin/sh: 1: gvm: not found, which would say more or less:
Your shell is /bin/sh, but source expects /bin/bash, perhaps because it puts its initialization in
~/.bashrc.
In other words, this problem can occur in any setting where the "sh" shell is used instead of the "bash", causing "/bin/sh: 1: MY_COMMAND: not found".
In the Dockerfile case, use the recommended
RUN /bin/bash -c 'source /opt/ros/melodic/setup.bash'or with the "[]" (which I would rather not use):
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash"]Every new RUN of a bash is isolated, "starting at 0". For example, mind that setting WORKDIR /MY_PROJECT before the bash commands in the Dockerfile does not affect the bash commands since the starting folder would have to be set in the ".bashrc" again. It needs cd /MY_PROJECT even if you have set WORKDIR.
Side-note: do not forget the first "/" before "opt/../...". Else, it will throw the error:
/bin/bash: opt/ros/melodic/setup.bash: No such file or directoryWorks:
=> [stage-2 18/21] RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash"] 0.5s => [stage-2 19/21] [...]You might also put the commands you want to execute in a single bash script and run that bash script in the Dockerfile (though I would rather put the bash commands in the Dockerfile as well, just my opinion):
#!/bin/bash
set -e
source /opt/ros/melodic/setup.bashPS: You can also put many bash commands in a row:
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash && MY_BASH_COMMAND && MY_BASH_COMMAND"]or same with
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash;MY_BASH_COMMAND;MY_BASH_COMMAND"]or in many lines with
RUN /bin/bash -c 'source /opt/ros/melodic/setup.bash &&\ cd /MY_PROJECT &&\ catkin_make -j8;\ echo "source /MY_PROJECT/devel/setup.bash" >> ~/.bashrc'or same with
RUN /bin/bash -c 'source /opt/ros/melodic/setup.bash;\ cd /MY_PROJECT;\ catkin_make -j8;\ echo "source /MY_PROJECT/devel/setup.bash" >> ~/.bashrc'Mind that when using RUN ["/bin/bash", "-c", "..."] with this [] frame, this works only in a one-liner. At least I could not (!) get it to run with:
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash && \ cd /MY_PROJECT && \ catkin_make -j8"]nor with
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash && cd /MY_PROJECT && catkin_make -j8"]nor with
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash; \ cd /MY_PROJECT; \ catkin_make -j8"]nor with
RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash; cd /MY_PROJECT; catkin_make -j8"]The error was always like:
executor failed running ... exit code: 127PS2: You can also add the source command to the .bashrc (the "run commands" at the start of the bash) so that this is loaded at every start of the bash:
RUN ["/bin/bash", "-c", "echo 'source /MY_PROJECT/devel/setup.bash' >> ~/.bashrc"]or
RUN /bin/bash -c 'echo "source /MY_PROJECT/devel/setup.bash" >> ~/.bashrc'