在Container中挂载目录并与Host共享

Hat*_*ber 25 docker

我以为我理解了文档,但也许我没有.我的印象是-v /HOST/PATH:/CONTAINER/PATH旗帜是双向的.如果我们在容器中有文件或目录,它们将在主机上镜像,为我们提供了一种方法来保留目录和文件,即使在删除docker容器之后也是如此.

在官方MySQL docker镜像中,这是有效的.所述/var/lib/mysql可以被绑定到主机和生存重启和替换容器的同时维持在主机上的数据.

我为sphinxsearch-2.2.9编写了一个docker文件,作为一种练习,为了学习和理解,这里是:

FROM debian

ENV SPHINX_VERSION=2.2.9-release

RUN apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq\
    build-essential\
    wget\
    curl\
    mysql-client\
    libmysql++-dev\
    libmysqlclient15-dev\
    checkinstall

RUN wget http://sphinxsearch.com/files/sphinx-${SPHINX_VERSION}.tar.gz && tar xzvf sphinx-${SPHINX_VERSION}.tar.gz && rm sphinx-${SPHINX_VERSION}.tar.gz

RUN cd sphinx-${SPHINX_VERSION} && ./configure --prefix=/usr/local/sphinx

EXPOSE 9306 9312

RUN cd sphinx-${SPHINX_VERSION} && make

RUN cd sphinx-${SPHINX_VERSION} && make install

RUN rm -rf sphinx-${SPHINX_VERSION}

VOLUME /usr/local/sphinx/etc
VOLUME /usr/local/sphinx/var
Run Code Online (Sandbox Code Playgroud)

在学习的过程中,非常简单易学.我正在将sphinx构建中的/ etc和/ var目录分配给VOLUME命令,认为它允许我做类似的事情-v ~/dev/sphinx/etc:/usr/local/sphinx/etc -v ~/dev/sphinx/var:/usr/local/sphinx/var,但事实并非如此,而是覆盖容器内的目录并将它们留空.当我删除-v标志并创建容器时,目录具有预期的文件,并且它们不会被覆盖.

这是我在导航到它所在的目录后运行以创建docker文件的方法: docker build -t sphinxsearch .

一旦我创建了它,我会执行以下操作来创建基于该图像的容器: docker run -it --hostname some-sphinx --name some-sphinx --volume ~/dev/docker/some-sphinx/etc:/usr/local/sphinx/etc -d sphinxsearch

我真的很感激有关如何使其发挥作用的任何帮助和见解.我查看了MySQL图像,并没有看到他们为使目录绑定所做的任何魔法,他们使用了VOLUME.

先感谢您.

Hat*_*ber 15

经过无数个小时的研究,我决定使用以下Dockerfile扩展我的图像:

FROM sphinxsearch

VOLUME /usr/local/sphinx/etc
VOLUME /usr/local/sphinx/var

RUN mkdir -p /sphinx && cd /sphinx && cp -avr /usr/local/sphinx/etc . && cp -avr /usr/local/sphinx/var .

ADD docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

ENTRYPOINT ["/docker-entrypoint.sh"]
Run Code Online (Sandbox Code Playgroud)

扩展它使我受益,因为我不需要在测试时从头开始构建整个图像,并且只构建相关的部件.

我创建了一个ENTRYPOINT来执行一个bash脚本,该脚本会将文件复制回所需的目标,以便sphinx正常运行,这里是代码:

#!/bin/sh
set -e

target=/usr/local/sphinx/etc

# check if directory exists
if [ -d "$target" ]; then
    # check if we have files
    if find "$target" -mindepth 1 -print -quit | grep -q .; then
        # no files don't do anything
        # we may use this if condition for something else later
        echo not empty, don\'t do anything...
    else
        # we don't have any files, let's copy the
        # files from etc and var to the right locations
        cp -avr /sphinx/etc/* /usr/local/sphinx/etc && cp -avr /sphinx/var/* /usr/local/sphinx/var
    fi
else
    # directory doesn't exist, we will have to do something here
    echo need to creates the directory...
fi

exec "$@"
Run Code Online (Sandbox Code Playgroud)

访问主机上的/ etc&/ var目录允许我调整文件,同时保持它们在重新启动之间保留在主机上等等......我还保存在主机上的数据,这些数据应该在重启后继续存在.

我知道这是关于数据容器与存储在主机上的辩论主题,此时我倾向于存储在主机上,但稍后会尝试其他方法.如果有人有任何提示,建议等...改善我所拥有或更好的方式,请分享.

感谢@ h3nrik的建议和提供帮助!


h3n*_*rik 5

将容器目录挂载到主机违反了docker概念。这将破坏流程/资源封装原则。

另一种方法是将主机文件夹安装到容器中。但是我宁愿建议使用卷容器,而不是。

  • 如果这违反概念,那么如何在Docker内部开发应用程序?如果我在每次代码更改后都构建Docker映像,那么它将很慢。如果我在Docker之外运行应用程序,那么它将扼杀Docker的优势。 (4认同)
  • 它的行为类似于linux挂载。假设您有一个包含现有文件的目录。然后,您将一个空磁盘驱动器装入该目录。结果将是该目录中存在的文件被安装“隐藏”,并且该目录似乎为空。绑定的docker卷也会发生类似的情况。因此不要将卷挂载到`/ etc`之类的文件中。这将隐藏所有先前存在的配置文件。如果您只想在`/ etc`目录中提供一小部分文件,请尽可能使用所描述的单个文件挂载。 (2认同)