如何在Dockerfile中为docker容器设置Bash别名?

145

我是Docker新手。我发现我们可以使用Dockerfile中的ENV指令设置环境变量。但是如何在Dockerfile中设置Bash别名以用于长命令?

9个回答

252

基本上像平常一样,将它添加到用户的.bashrc文件中:

FROM foo
RUN echo 'alias hi="echo hello"' >> ~/.bashrc

通常这只适用于交互式shell:

docker build -t test .
docker run -it --rm --entrypoint /bin/bash test hi
/bin/bash: hi: No such file or directory
docker run -it --rm test bash
$ hi
hello

对于非交互式 shell,您应该创建一个小脚本并将其放在您的路径中,例如:

RUN echo -e '#!/bin/bash\necho hello' > /usr/bin/hi && \
    chmod +x /usr/bin/hi

如果您的别名使用参数(例如:hi Jim -> hello Jim),只需添加"$@"
RUN echo -e '#!/bin/bash\necho hello "$@"' > /usr/bin/hi && \
    chmod +x /usr/bin/hi

谢谢,你能提供一个非交互式 shell 的例子吗?我正在寻找 ENTRYPOINT 和 CMD 来解决这个问题。 - c24b
5
Bash 别名只能在交互式 Shell 中使用。只需创建一个小型的 Shell 脚本并将其放在路径中,就可以达到与别名相同的效果。更新了答案,并提供了一个简单的例子。 - Erik Dannenberg
2
注意:来自 https://dev59.com/mGoy5IYBdhLWcg3wkO2g#8467449 的建议是使用 printf 而不是 echo,以确保更一致的行为。因此,printf '#!/bin/bash\necho hello' > /usr/bin/hi chmod +x /usr/bin/hi - barraq
3
多个参数转义时,应该使用"$@"而不是$*。请参见https://unix.stackexchange.com/questions/248464/escape-shell-arg-from-one-script-to-another。 - gnou
2
对于非交互式 shell,-e 对我无效。移除它后一切正常。 - Prasannjeet Singh
显示剩余2条评论

27

要创建一个现有命令的别名,还可以使用 ln -s 命令:

ln -s $(which <existing_command>) /usr/bin/<my_command>

13
我不会称这为别名,而是软链接。别名的方便之处在于可以向命令传递参数,比如 alias ll='ls -lh',但这在使用符号链接时是不可能的。 - qwertz

5

如果您只想在Dockerfile中使用别名,而不是在容器内部使用,则最简单的方法是使用ENV声明

ENV update='apt-get update -qq'
ENV install='apt-get install -qq'

RUN $update && $install apt-utils \
    curl \
    gnupg \
    python3.6

如果要在容器中使用,可以按照之前描述的方式进行:

 RUN printf '#!/bin/bash \n $(which apt-get) install -qq $@' > /usr/bin/install
 RUN chmod +x /usr/bin/install

大多数时候我只在构建阶段使用别名,不进入容器,因此第一个示例对于日常使用来说更快、更清晰、更简单。


5
我认为最简单的方法是将一个包含你的别名的文件挂载到容器中,然后指定 Bash 应该在哪里找到它:
docker run \
    -it \
    --rm \
    -v ~/.bash_aliases:/tmp/.bash_aliases \
    [image] \
    /bin/bash --init-file /tmp/.bash_aliases

使用示例:

echo 'alias what="echo it works"' > my_aliases
docker run -it --rm -v ~/my_aliases:/tmp/my_aliases ubuntu:18.04 /bin/bash --init-file /tmp/my_aliases
alias

输出:

alias what='echo it works'

what

输出:

it works

4

我刚刚在我的 app.dockerfile 文件中添加了以下内容:

# Set up aliases
ADD ./bashrc_alias.sh /usr/sbin/bashrc_alias.sh
ADD ./initbash_profile.sh /usr/sbin/initbash_profile
RUN chmod +x /usr/sbin/initbash_profile
RUN /bin/bash -C "/usr/sbin/initbash_profile"

initbash_profile.sh文件中,只需添加自定义别名,无需引用.bashrc文件:

# Add the Bash aliases
cat /usr/sbin/bashrc_alias.sh >> ~/.bashrc

这真是太好了!

另一个选项是仅使用"docker exec -it <container-name> 命令"来自容器外部,然后使用您自己的.bashrc.bash_profile文件(无论您喜欢哪个)。

例如:

docker exec -it docker_app_1 bash

2
您可以在Dockerfile中使用ENTRYPOINT,但它无法用于别名。
ADD dev/entrypoint.sh /opt/entrypoint.sh
ENTRYPOINT ["/opt/entrypoint.sh"]

你的entrypoint.sh文件:

#!/bin/bash
set -e

function dev_run()
{

}

export -f dev_run

exec "$@"

请注意,一些 Docker 镜像可能已经覆盖了默认的入口点(例如 phusion 基础镜像)。 - Thomas Decaux

1
这是一个 Bash 函数,可以让你在每个交互式容器中使用你的别名。
ducker_it() {
    docker cp ~/bin/alias.sh "$1":/tmp
    docker exec -it "$1" /bin/bash -c "[[ ! -f /tmp/alias.sh.done ]] \
        && [[ -w /root/.bashrc ]] \
        && cat /tmp/alias.sh >> /root/.bashrc \
        && touch /tmp/alias.sh.done"
    docker exec -it "$1" /bin/bash
}

前置步骤:

grep ^alias ~/.zshrc > ~/bin/alias.sh

0

@ErikDannenberg的回答解决了问题,但在我的情况下需要进行一些调整。

由于交互式 shell 存在问题,使用别名无法正常工作。

我尝试了他的第二个解决方案,但仍然没有真正解决问题。我检查了项目中现有的 shell 脚本,并注意到头注释(第一行 = #!/usr/bin/env sh)与 #!/usr/bin/bash 有些不同。更改后,它开始适用于我的 ttc“别名”,但我必须使用他的第二个解决方案的附录才能让 tf 正常工作。

这是完整的 Dockerfile。

FROM php:8.1.1-fpm-alpine AS build

RUN apk update && apk add git

RUN curl -sS https://getcomposer.org/installer | php && mv composer.phar /usr/local/bin/composer

RUN apk add --no-cache $PHPIZE_DEPS \
    && pecl install xdebug \
    && docker-php-ext-enable xdebug \
    && touch /usr/local/etc/php/conf.d/99-xdebug.ini \
    && echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/99-xdebug.ini \
    && echo -e '#!/usr/bin/env sh\nphp artisan test' > /usr/bin/t \
    && chmod +x /usr/bin/t \
    && echo -e '#!/usr/bin/env sh\nphp artisan test --coverage' > /usr/bin/tc \
    && chmod +x /usr/bin/tc \
    && echo -e '#!/usr/bin/env sh\nphp artisan test --filter "$@"' > /usr/bin/tf \
    && chmod +x /usr/bin/tf

WORKDIR /var/www


0

使用了之前的一些解决方案,但是别名仍然无法被识别。

我正在尝试设置别名,并在稍后的Dockerfile步骤和容器运行时中使用它们。

RUN echo "alias model-downloader='python3 ${MODEL_DL_PATH}/downloader.py'" >> ~/.bash_aliases && \
    echo "alias model-converter='python3 ${MODEL_DL_PATH}/converter.py'" >> ~/.bash_aliases && \
    source ~/.bash_aliases

# Download the model
RUN model-downloader --name $MODEL_NAME -o $MODEL_DIR --precisions $MODEL_PRECISION;

对我来说,解决方案是使用保存文件夹路径的环境变量,然后添加确切的可执行文件。我也可以使用ARG,但对于更多的场景,我需要在构建阶段和运行时都使用别名。
我将ENV变量与Bash脚本一起使用,该脚本在依赖项完成后运行一次,并设置Bash源,设置更多的环境变量,并允许进一步的命令通过管道传输。

1
每个RUN指令都在新的shell中执行,因此在您的示例中,当您尝试使用别名时,别名文件不再被加载。 - Erik Dannenberg
100% @ErikDannenberg 感谢您的评论,也提醒我需要发布更新 - 我已经找到了一个解决方案,非常像您建议的那样。 - alanionita
2
"ponged" 是什么意思?我猜应该是指“散发臭味,闻起来难闻”(在英国、澳大利亚和新西兰这样的俚语中)。或者是指“在戏剧中以夸张、暗示或不自然的方式表达一行台词,以引起过度关注”(在俚语、戏剧中贬义)或“当忘记实际台词时,杜撰一句台词。”(俚语、戏剧、不及物动词)。 - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接