在Docker图像中声明bash功能

发布于 2025-02-13 09:28:52 字数 487 浏览 1 评论 0 原文

使用Dockerfile来构建图像,后来我用来运行用于跨编译目标平台二进制的容器。该容器用于开发,因此我在该容器内工作时间。 “ make”命令正正确地构建二进制。

出于调试目的,我需要透明地将Make命令的输出保存到日志文件中。我解决了此添加bash“ make”函数的函数:

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”。在容器中,每当我运行“ make”命令时,日志总是会如预期的那样保存到 /tmp /$ logName中。

我想知道是否有一种更方便 /干净的方法可以在不定义dockefile中的此运行命令的情况下定义bash函数。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俯瞰星空 2025-02-20 09:28:52

调用Docker容器的大多数路径都不读取Shell Dotfiles或具有明确定义的主目录概念。在您的Dockerfile中写入 .bashrc 很少有用,因为很可能不会读取文件;例如, docker run -rm your-image make 在尝试运行 make> 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中的环境变量,则不能使用类似的脚本(如果需要 导出logName 并稍后使用),但是此脚本不需要。否则,Shell脚本通常比Shell功能更容易管理。在这种情况下,请注意,我们永远不需要逃脱引用字符串中的引用,我们正在写入文件。我们刚刚编写了脚本,并与Docker设置分开进行了手工测试。

由于这是正常位置的普通程序,因此您可以运行它

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

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
酒几许 2025-02-20 09:28:52

我将

  • 在专用文件 make.sh 旁边外部化您的bash函数,而 dockerfile
#!/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
  • 添加 dockerfile 指令,以在 make.sh 脚本中源 .bashrc
RUN echo "source ~/make.sh" >> .bashrc

[编辑]

阅读 @David-Maze 答案摆脱 > .bashrc 采购零件并在/usr/usr/local/bin 下直接复制脚本似乎是一种更有效,更清洁的方式它允许从容器内部和外部调用该功能。

I will

  • Externalize your Bash function in a dedicated file make.sh aside your Dockerfile:
#!/usr/bin/env bash

make() {
   DATE=$(date "+%Y%m%d-%H%M%S")
   LOGNAME=build_$DATE.log
   $(which make) "$@" 2>&1 | tee /tmp/$LOGNAME
}
  • Add a Dockerfile instruction to copy the make.sh script in the container:
COPY make.sh ~/make.sh
  • Add a Dockerfile instruction to source the make.sh script in the .bashrc:
RUN echo "source ~/make.sh" >> .bashrc

[ EDIT ]

After reading @david-maze answer getting rid of the .bashrc sourcing part and copying the script directly under /usr/local/bin seems to be a more efficient and cleaner way since it allows calling the function both from inside and outside the container.

泪意 2025-02-20 09:28:52

一种替代方法是从主机内部完全控制您的 .bashrc 文件,并使用Dockerfile 复制指令将其复制到图像。

One alternative is to fully control your .bashrc file from within the host and copy it to the image with a Dockerfile COPY instruction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文