如何正确挂载/绑定/...本地(主机)目录到docker容器中

如何正确挂载/绑定/...本地(主机)目录到docker容器中

我目前正在使用 Windows 11,并尝试为我的开发环境构建一个 docker 文件,如下所示。对我来说,这行RUN --mount=type=bind,target=/home/$username/src很有趣。我理解“建立上下文“作为文件夹,其中Dockerfile谎言。来自文档:

RUN --mount允许您创建作为构建的一部分运行的进程可以访问的挂载。这可用于绑定构建其他部分的文件,而无需复制 [...] 或创建缓存位置以加快构建速度。

RUN --mount=type=bind[...] 允许将上下文或图像中的目录(只读)绑定到构建容器。

因此,我最好希望通过以下方式实现绑定安装像这样的命令:(docker run -dit --mount type=bind,source="${PWD}\target",target=/home/foo/src来自 PowerShell)或docker run -dit --mount type=bind,source="%cd%\target",target=/home/foo/src(来自 cmd)... 由于某种原因$username无法工作,target=/home/foo/src- 但我不知何故需要将其放入Dockerfile

FROM ubuntu:20.04

ENV RUBY_VERSION 2.6.6
ENV NODE_VERSION 8.2.1

ARG username=foo
ENV RVM_DIR "/home/$username/.rvm"
ENV NVM_DIR "/home/$username/.nvm"

RUN apt-get update && apt-get -y dist-upgrade && apt-cache policy libssl1.0-dev
#libssl1.0-dev:
#  Installed: (none)
#  Candidate: (none)
#  Version table:

RUN apt-get update && apt-get install -y curl build-essential whois unzip sudo libpq-dev passwd git wget


RUN echo "$username  ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/$username
## create user for Heizkosten-Plattform
RUN adduser --gecos "" --disabled-password --shell /bin/bash $username
## continue as non-root user
USER $username


## create application directory (as non-root user)
RUN sudo mkdir /opt/$username && sudo chown $username:$username /opt/$username

# 0. Git
WORKDIR /opt/$username

RUN git config --global url."https://".insteadOf git:// 
RUN git init 
RUN git config --global user.name "John Doe"
RUN git config --global user.email "[email protected]" 

# 1. Preparations for RVM
RUN sudo sh -c 'echo "deb http://security.ubuntu.com/ubuntu bionic-security main" >> /etc/apt/sources.list'
RUN sudo apt update && apt-cache policy libssl1.0-dev
RUN sudo apt-get install libssl1.0-dev -y
RUN sudo apt-get install libpq-dev -y

# 2.a RVM (Ruby Version Manager)
RUN curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -
RUN \curl -sSL https://get.rvm.io | bash
# \curl -sSL https://get.rvm.io | bash -s stable --rails
RUN . $RVM_DIR/scripts/rvm # Doen't seem to do much. source instead of . doesn't work.
RUN $RVM_DIR/bin/rvm install $RUBY_VERSION
RUN $RVM_DIR/bin/rvm use default $RUBY_VERSION

# 3 NVM (Node Version Manager)
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
RUN . "$NVM_DIR/nvm.sh" && nvm install $NODE_VERSION && nvm use $NODE_VERSION
ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
RUN npm install 

# 2.b # Add RVM to PATH for scripting. Make sure this is the last PATH variable change.
ENV PATH $PATH:$RVM_DIR/rubies/ruby-$RUBY_VERSION/bin
ENV PATH $PATH:$RVM_DIR/bin

#MOUNT
RUN mkdir ~/src
RUN --mount=type=bind,target=/home/$username/src 
# ,from     Build stage or image name for the root of the source. Defaults to the build context.

WORKDIR /home/$username/src
run pwd && ls -la /home/foo/src && exit 1
RUN bundle install

# make port of rails server available
EXPOSE 3000

run pwd && ls -la /home/foo/src && exit 1只是为了验证src目录仍然为空:

------
 > [28/29] RUN pwd && ls -la /home/foo/src && exit 1:
#32 0.449 /home/foo/src
#32 0.451 total 8
#32 0.451 drwxr-xr-x 2 foo foo 4096 Oct 17 13:04 .
#32 0.451 drwxr-xr-x 1 foo foo 4096 Oct 17 13:04 ..
------
executor failed running [/bin/sh -c pwd && ls -la /home/foo/src && exit 1]: exit code: 1

(我使用&& exit 1跳出并让docker保留输出)

答案1

按照Dockerfile 参考-RUN命令旨在在构建映像时执行操作。您已为其指定了绑定挂载定义,但没有要执行的程序或命令。您通常会执行的操作是挂载数据并在同一RUN指令内对其执行操作。如下所示:

RUN --mount=type=bind,target=/home/$username/src bundle install

或者查看你已安装的内容

RUN --mount=type=bind,target=/home/$username/src ls -la /home/foo/src

我还没有在文档中看到这一点的明确说明,但据我所知,这意味着 Dockerfile 挂载仅在相应RUN指令的持续时间内处于活动状态。您可以在官方教程。请注意,RUN即使每个指令相同,它们也有自己的挂载定义。还值得注意的是 Dockerfile绑定默认安装只读,因此尝试修改已挂载的树通常会引发错误。

我还建议您使用WORKDIR说明代替RUN mkdir。它完全满足您的需要通过沿着指定的路径创建所有必要的目录并更改为最终目录,这与以下RUN指令完美契合。这样您就可以创建一个挂载目标,将其挂载到其中并立即对挂载的数据采取行动。例如:

WORKDIR /home/$username/src
RUN --mount=type=bind,target=/home/$username/src bundle install

正如您正确指出的那样,在容器运行时绑定挂载是一种替代方法。在运行时绑定保持可用,直到容器停止。

相关内容