在docker映像中声明bash函数



使用Dockerfile构建映像,稍后我将使用该映像运行用于为目标平台交叉编译二进制文件的容器。这个容器是用于开发的,所以我在这个容器里工作。"老爷;命令正在正确构建二进制文件。

出于调试目的,我需要将make命令的输出透明地保存到日志文件中。我解决了这个问题,添加了bash "make"函数到Dockefile:

RUN echo 'make() { DATE=$(date "+%Y%m%d-%H%M%S"); LOGNAME=build_$DATE.log; $(which make) "$@" 2>&1 | tee /tmp/$LOGNAME; }' >> ~/.bashrc

可以看到,我修改了.bashrc。函数"老爷;在运行到容器中时声明。在容器内部,每当我运行"make"命令,日志总是按照预期保存到/tmp/$LOGNAME。

我想知道是否有一种更方便/干净的方法来在运行的shell中定义bash函数,而不用在Dockefile中定义这个RUN命令。

调用Docker容器的大多数路径不读取shell dotfile或具有良好定义的主目录概念。在Dockerfile中写入.bashrc很少有用,因为该文件很可能不会被读取;例如,在执行make命令之前,docker run --rm your-image make不会读取.bashrc文件。

你能做的是把这些命令写进一个shell脚本。这只是一个包含将要运行的命令列表的文件。在Docker之外,创建一个简单的文件:

#!/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"

将此脚本标记为可执行并运行。

chmod +x make_and_log
./make_and_log compile
ls -l build_*.log
tail build_20220706-063319.log

现在在你的Dockerfile中,你只需要将这个脚本复制到标准$PATH目录下的某个地方;/usr/local/bin通常是一个很好的选择。

COPY make_and_log /usr/local/bin/

如果需要修改包含shell的环境变量(如果需要export LOGNAME并稍后使用),则不能使用这样的shell脚本,但此脚本不需要这样做。否则,shell脚本通常会比外壳函数更容易管理。在这种情况下,请注意,我们从来没有需要转义引号内的引号字符串,我们写出来的文件;我们刚刚编写了脚本,并将其与Docker设置分开进行了手工测试。

,因为这是一个普通的程序在一个正常的地方,你可以运行它

docker run --rm 
-v "$PWD:/src" -w /src 
the-image 
make_and_log compile

我将

  • Dockerfile之外的专用文件make.sh中外部化Bash函数:
#!/usr/bin/env bash
make() {
DATE=$(date "+%Y%m%d-%H%M%S")
LOGNAME=build_$DATE.log
$(which make) "$@" 2>&1 | tee /tmp/$LOGNAME
}
  • 添加Dockerfile指令将make.sh脚本复制到容器中:
COPY make.sh ~/make.sh
  • .bashrc中添加Dockerfile指令来获取make.sh脚本的源代码:
RUN echo "source ~/make.sh" >> .bashrc

[EDIT]

在阅读@david-maze答案后,摆脱.bashrc源部分并直接在/usr/local/bin下复制脚本似乎是一种更有效和更干净的方式,因为它允许从容器内部和外部调用函数。

另一种选择是从主机内部完全控制您的.bashrc文件,并使用DockerfileCOPY指令将其复制到映像中。

相关内容

  • 没有找到相关文章

最新更新