可以在Docker容器中安装ASDF,但可以通过Dockerfile在构建时间安装

发布于 2025-01-25 03:34:22 字数 1270 浏览 2 评论 0 原文

我有一个Dockerfile,我正在尝试安装和使用ASDF来管理Python软件包版本。我的Dockerfile的片段出现在下面。


SHELL ["/bin/bash", "-c"] 

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.0
RUN chmod +x ~/.asdf/asdf.sh ~/.asdf/completions/asdf.bash
RUN echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc
RUN echo ". $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc
ENV PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
ENV PATH="$HOME/.asdf:$PATH"
RUN echo -e '\nsource $HOME/.asdf/asdf.sh' >> ~/.bashrc
RUN source ~/.bashrc
RUN bash -c 'echo -e which asdf'
RUN asdf plugin-add python

最后一行是有问题的线。当我尝试构建此Docker映像时,我会得到以下内容。

 => ERROR [17/19] RUN asdf plugin-add python                                                                                                                    0.3s
------
 > [17/19] RUN asdf plugin-add python:
#21 0.292 /bin/bash: asdf: command not found
------
executor failed running [/bin/bash -c asdf plugin-add python]: exit code: 127

但是,如果删除该行,我可以运行一个容器,然后立即成功运行ASDF。

docker run -it <image ID>
root:# asdf plugin-add python
initializing plugin repository...Cloning into '/root/.asdf/repository'...
<etc>

当我尝试通过Dockerfile运行它时,为什么这不起作用?

I have a Dockerfile in which I am trying to install and use asdf to manage Python package versions. A snippet of my Dockerfile appears below.


SHELL ["/bin/bash", "-c"] 

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.0
RUN chmod +x ~/.asdf/asdf.sh ~/.asdf/completions/asdf.bash
RUN echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc
RUN echo ". $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc
ENV PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
ENV PATH="$HOME/.asdf:$PATH"
RUN echo -e '\nsource $HOME/.asdf/asdf.sh' >> ~/.bashrc
RUN source ~/.bashrc
RUN bash -c 'echo -e which asdf'
RUN asdf plugin-add python

That last line is the offending line. When I try to build this Docker image, I get the following.

 => ERROR [17/19] RUN asdf plugin-add python                                                                                                                    0.3s
------
 > [17/19] RUN asdf plugin-add python:
#21 0.292 /bin/bash: asdf: command not found
------
executor failed running [/bin/bash -c asdf plugin-add python]: exit code: 127

However, if I remove that line, I'm able to run a container and then just immediately run asdf successfully.

docker run -it <image ID>
root:# asdf plugin-add python
initializing plugin repository...Cloning into '/root/.asdf/repository'...
<etc>

Why doesn't this work when I try to run it through the Dockerfile?

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

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

发布评论

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

评论(5

瞳孔里扚悲伤 2025-02-01 03:34:22

我发现 source〜/.bashrc; 并不总是在docker容器中执行此操作(有时不在实时操作系统中),也不是<代码>/bin/bash -c'source〜/.bashrc'; 。

我发现,在构建时间安装 ASDF 的诀窍是,我发现要远至重新启动bash (即 exec exec bash 。这可能与我们实际上没有修改 path = 以及随后 source&lt; file&gt; '之类的事实有关,而是使用POSIX兼容的源指令以文件名(减去其扩展名)来吸用可执行脚本。

。 $ home/.asdf/asdf.sh

表示:

source/home/home/.asdf/asdf.sh

,它似乎给出了:

别名asdf =/home/home/home/home/home/用户/.asdf/asdf.sh

简单地采购文件无法正常工作,因为安装说明(ASDF作者提供)基本上提供了一个源指令,以放置〜/.bashrc ,我相信,与我们使用的外壳相比,上下文成为了一个。

要解决此问题,我们必须重新启动bash-别无其他方式。

我们还会遇到很多怪癖,并且在尝试将用户软件包(实际上只是语义)配置为root时必须规定的问题,因此,为了避免,最好建立一个非根源用户。

这是一个工作示例,可以进一步安装Ruby和nodejs:

FROM debian:bookworm-slim
# .. LABEL, etc., ...
#
RUN apt-get update && \
# prep tools also for asdf (last 2)
    apt-get install -y curl git \
        software-properties-common \
        gnupg2 apt-transport-https \
# prep deps for asdf-ruby
        build-essential autoconf \
        bison patch rustc \
        libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev \
        libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev \
# prep deps for asdf-nodejs
        dirmngr gawk \
# prep deps for non-root user
        sudo; \
# create special user
    useradd --create-home --shell /bin/bash gitlab; \
    /bin/bash -c 'echo "gitlab:password" | chpasswd'; \
    adduser gitlab sudo

## change user for all subsequent commands
USER gitlab

# change working directory
WORKDIR /home/gitlab

# install asdf
RUN \
    # configure git to get rid of detached head warnings
    git config --global advice.detachedHead false; \
    git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.10.2; \
    /bin/bash -c 'echo -e "\n\n## Configure ASDF \n. $HOME/.asdf/asdf.sh" >> ~/.bashrc'; \
    /bin/bash -c 'echo -e "\n\n## ASDF Bash Completion: \n. $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc'; \
    exec bash; \
# install asdf-ruby
    /bin/bash -c asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git; \
# install asdf-nodejs
    /bin/bash -c asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git;

# whatever you now want to do -

I found that source ~/.bashrc; just doesn't always do it in a docker container (it doesn't in a live OS at times), nor does /bin/bash -c 'source ~/.bashrc';.

The trick to installing asdf in a Docker container at build time, I found, was to go as far as to restart bash (i.e. exec bash). Possibly it has to do with the fact that we're not actually modifying something like PATH= and subsequently source <file>'ing it, but using posix compliant source directives to alias an executable script by the filename (minus its extension).

. $HOME/.asdf/asdf.sh

Means:

source /home/user/.asdf/asdf.sh

Which seemingly gives the effect of:

alias asdf=/home/user/.asdf/asdf.sh

Simply sourcing the file won't work because the install instructions (provided by asdf authors) provide essentially a source directive to place inside of ~/.bashrc, and I believe the context then becomes one other than the one the shell we're using is subsequently under.

To fix this, we have to restart bash - there's no other way.

We'll also run into a lot of quirks and issues we have to circumvent when trying to configure user packages (just semantics, really) as root, so to avoid that its best to establish a non-root user to work with.

Here's a working example that goes further to install Ruby and NodeJS:

FROM debian:bookworm-slim
# .. LABEL, etc., ...
#
RUN apt-get update && \
# prep tools also for asdf (last 2)
    apt-get install -y curl git \
        software-properties-common \
        gnupg2 apt-transport-https \
# prep deps for asdf-ruby
        build-essential autoconf \
        bison patch rustc \
        libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev \
        libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev \
# prep deps for asdf-nodejs
        dirmngr gawk \
# prep deps for non-root user
        sudo; \
# create special user
    useradd --create-home --shell /bin/bash gitlab; \
    /bin/bash -c 'echo "gitlab:password" | chpasswd'; \
    adduser gitlab sudo

## change user for all subsequent commands
USER gitlab

# change working directory
WORKDIR /home/gitlab

# install asdf
RUN \
    # configure git to get rid of detached head warnings
    git config --global advice.detachedHead false; \
    git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.10.2; \
    /bin/bash -c 'echo -e "\n\n## Configure ASDF \n. $HOME/.asdf/asdf.sh" >> ~/.bashrc'; \
    /bin/bash -c 'echo -e "\n\n## ASDF Bash Completion: \n. $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc'; \
    exec bash; \
# install asdf-ruby
    /bin/bash -c asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git; \
# install asdf-nodejs
    /bin/bash -c asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git;

# whatever you now want to do -
庆幸我还是我 2025-02-01 03:34:22

exec bash 此答案中的建议对我不起作用,但是我确实发现您可以在dockerfile中指定外壳,并且每个运行命令将坚持使用bash更改。前任。 shell [“/bin/bash”,“ - lc”]

感谢此Github用户和要点向我展示此信息,这也是一个广泛的ASDF Dockerfile。

The exec bash suggestion in this answer wasn't working for me, but I did find you can specify the shell in your dockerfile and bash changes will be persisted with each RUN command. Ex. SHELL ["/bin/bash", "-lc"]

Thanks to this github user and gist for showing me this, also it is a pretty extensive asdf Dockerfile. https://gist.github.com/BrutalSimplicity/882af1d343b7530fc7e005284523d38d

怀中猫帐中妖 2025-02-01 03:34:22

这个...

RUN source ~/.bashrc

绝对什么都不做。每个 run 命令在新的shell中执行,该命令在命令完成时退出。采购bash脚本,设置变量和其他修改当前环境的事物不会持续到后续运行命令。

您可以修改 dockerfile 以在运行命令中运行一系列命令,例如:

RUN source ~/.bashrc; \
  asdf plugin-add python

...它至少会成功地源自 .bashrc 文件,大概使 asdf 工具可用。

This...

RUN source ~/.bashrc

Does absolutely nothing. Each RUN command executes in a new shell, which exits when the command completes. Sourcing bash scripts, setting variables, and other things that modify the current environment will not persist to subsequent RUN commands.

You could modify your Dockerfile to run a sequence of commands in a RUN command, like this:

RUN source ~/.bashrc; \
  asdf plugin-add python

...which would at least successfullly source the .bashrc file and presumably make the asdf tool available.

灼疼热情 2025-02-01 03:34:22

我发现,克隆 asdf 要安装它后,获得 asdf 命令的最简单方法是通过设置 path 来包括:

ENV PATH="$PATH:/root/.asdf/bin"

完整示例:

FROM debian:12

# Install asdf dependencies
RUN apt-get update -y && apt-get install -y \
  curl \
  git

# Install asdf
RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git ~/.asdf

# Add asdf to PATH, so it can be run in this Dockerfile
ENV PATH="$PATH:/root/.asdf/bin"

# Add asdf shims to PATH, so installed executables can be run in this Dockerfile
ENV PATH=$PATH:/root/.asdf/shims

# Now you're free to install asdf plugins:
RUN asdf plugin add nodejs
RUN asdf install nodejs 20.5.1
RUN asdf global nodejs 20.5.1

我还建议您查看更强大的配置。您可以将其用作基本图像,也可以将其命令阅读以获得灵感。

I have found that after cloning asdf to install it, the easiest way to get the asdf command to run is by setting PATH to include it:

ENV PATH="$PATH:/root/.asdf/bin"

Full example:

FROM debian:12

# Install asdf dependencies
RUN apt-get update -y && apt-get install -y \
  curl \
  git

# Install asdf
RUN git clone --depth 1 https://github.com/asdf-vm/asdf.git ~/.asdf

# Add asdf to PATH, so it can be run in this Dockerfile
ENV PATH="$PATH:/root/.asdf/bin"

# Add asdf shims to PATH, so installed executables can be run in this Dockerfile
ENV PATH=$PATH:/root/.asdf/shims

# Now you're free to install asdf plugins:
RUN asdf plugin add nodejs
RUN asdf install nodejs 20.5.1
RUN asdf global nodejs 20.5.1

I also recommend looking at this Dockerfile which has a more robust configuration. You can either use that as a base image, or just read its commands for inspiration.

征﹌骨岁月お 2025-02-01 03:34:22

如前所述,运行

RUN source ~/.bashrc

无济于事 - 该文件是针对其他外壳实例的。将Shell设置为使用 - 登录选项bash bash bash

SHELL ["/bin/bash", "--login", "-c"]

命令后,每个实例都可以读取配置文件。因此,您的 dockerfile 变为:

SHELL ["/bin/bash", "--login", "-c"] 

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.0
RUN echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc
RUN echo ". $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc
RUN asdf plugin-add python

您也不需要其他几行,在调试 dockerfile ;-)

更新时很可能会添加它们:

显然您的配置链文件需要源 .bashrc 。 事情

if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

类似于 .bash_profile 应该做的 。或者使用 .bash_profile 而不是 .bashrc 也应该这样做。 bash Invocation

As mentioned already, running

RUN source ~/.bashrc

doesn't help – the file is sourced for a different shell instance. Setting shell to bash with --login option makes every instance after

SHELL ["/bin/bash", "--login", "-c"]

command to read configuration files though. Therefore your Dockerfile becomes:

SHELL ["/bin/bash", "--login", "-c"] 

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.0
RUN echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc
RUN echo ". $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc
RUN asdf plugin-add python

As you also don't need those few other lines, which you most probably added while debugging your Dockerfile ;-)

Update:

obviously your chain of config files needs to source .bashrc. Something like

if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

in .bash_profile should do. Alternatively using .bash_profile instead of .bashrc should also do. More information in bash man page - section INVOCATION

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