Using a Dockerfile to build an image which I later use to run a container used to cross-compile a binary for a target platform. This container is used for development, so I work hours inside this container. The "make" command is building the binary properly.
For debug purposes, I need the output of the make command being saved to a logfile transparently. I solved this adding a bash "make" function to my Dockefile:
RUN echo 'make() { DATE=$(date "+%Y%m%d-%H%M%S"); LOGNAME=build_$DATE.log; $(which make) "$@" 2>&1 | tee /tmp/$LOGNAME; }' >> ~/.bashrc
As you can see, I modify the .bashrc. Function "make" is declared when I run into the container. Inside the container, whenever I run "make" command, the logs are always saved into /tmp/$LOGNAME, as expected.
I wonder if there is a more convenient / clean way to define a bash function in the running shell without defining this RUN command in the Dockefile.
Most paths of invoking Docker containers don't read shell dotfiles or have well-defined concepts of home directories. It's rarely useful to write to a .bashrc
in your Dockerfile since it's highly likely that file won't be read; for example, docker run --rm your-image make
won't read the .bashrc
file before trying to run the make
command.
What you can do is write these commands into a shell script. This is just a file with a list of commands that will be run. Outside of Docker, create a simple file:
#!/bin/sh
# ^^ Name the interpreter that will run this script.
# This must be the absolute very first line of the file.
# Use /bin/sh in most cases; many images do not have GNU bash.
# (And make sure to avoid bash-specific syntax, like "function"
# or "source").
# This is the sequence of commands you had originally,
# one to a line.
DATE=$(date "+%Y%m%d-%H%M%S")
LOGNAME="build_$DATE.log"
make "$@" 2>&1 | tee "/tmp/$LOGNAME"
Mark this script as executable and run it.
chmod +x make_and_log
./make_and_log compile
ls -l build_*.log
tail build_20220706-063319.log
Now in your Dockerfile, you just need to copy this script into somewhere that's in the standard $PATH
directories; /usr/local/bin
is frequently a good choice.
COPY make_and_log /usr/local/bin/
You can't use shell scripts like this if they need to modify environment variables in the containing shell (if you needed to export LOGNAME
and use it later) but this script doesn't need that. Otherwise, a shell script will generally be a little easier to manage than a shell function. In this case note that we've never needed to escape a quote inside a quoted string we're writing out to a file; we've just written the script and hand-tested it separately from the Docker setup.
Since this is now an ordinary program in a normal place, you can just run it
docker run --rm \
-v "$PWD:/src" -w /src \
the-image \
make_and_log compile