Change directory command in Docker? – Dev

The best answers to the question “Change directory command in Docker?” in the category Dev.

QUESTION:

In docker I want to do this:

git clone XYZ
cd XYZ
make XYZ

However because there is no cd command, I have to pass in the full path everytime (make XYZ /fullpath). Any good solutions for this?

ANSWER:

You can run a script, or a more complex parameter to the RUN. Here is an example from a Dockerfile I’ve downloaded to look at previously:

RUN cd /opt && unzip treeio.zip && mv treeio-master treeio && \
    rm -f treeio.zip && cd treeio && pip install -r requirements.pip

Because of the use of ‘&&’, it will only get to the final ‘pip install’ command if all the previous commands have succeeded.

In fact, since every RUN creates a new commit & (currently) an AUFS layer, if you have too many commands in the Dockerfile, you will use up the limits, so merging the RUNs (when the file is stable) can be a very useful thing to do.

ANSWER:

To change into another directory use WORKDIR. All the RUN, CMD and ENTRYPOINT commands after WORKDIR will be executed from that directory.

RUN git clone XYZ 
WORKDIR "/XYZ"
RUN make

ANSWER:

Mind that if you must run in bash shell, you need not just the RUN make, but you need to call the bash shell before, since in Docker, you are in the sh shell by default.

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 directory

Works:

 => [stage-2 18/21] RUN ["/bin/bash", "-c", "source /opt/ros/melodic/setup.bash"]                                  0.5s
 => [stage-2 19/21] [...]

See “/bin/sh: 1: MY_COMMAND: not found” at SuperUser for some more details on how this looks with many lines, or how you would fill the “.bashrc” instead. But that goes a bit beyond the actual question here.

PS: 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.bash

ANSWER:

I was wondering if two times WORKDIR will work or not, but it worked 🙂

FROM ubuntu:18.04

RUN apt-get update && \
    apt-get install -y python3.6

WORKDIR /usr/src

COPY ./ ./

WORKDIR /usr/src/src

CMD ["python3", "app.py"]