【问题标题】:Inspect non-daemon Docker container, after it has completed running检查非守护程序 Docker 容器,在它完成运行后
【发布时间】:2017-05-27 06:08:43
【问题描述】:

我有一个创建容器

# start
docker build -t cdt-tests .
docker run -it --name cdt-tests cdt-tests
# end => I want to inspect the container filesystem after it's done

因为它没有在分离模式下运行,我如何检查容器?我想要做的是防止容器“自动关闭”,以便在容器完成后检查容器的文件系统。

用于 cdt-tests 的 Dockerfile 如下所示:

FROM node:6

RUN apt-get update && \
      apt-get -y install sudo

RUN sudo apt-get -y update
RUN sudo apt-get -y upgrade
RUN sudo apt-get install -y sqlite3 libsqlite3-dev

USER root

RUN mkdir -p /tmp/test-deps
RUN mkdir -p /usr/local/cdt-tests
WORKDIR /usr/local/cdt-tests

ENV SUMAN_POSTINSTALL_IS_DAEMON no

RUN rm -rf node_modules

RUN npm set progress=false
RUN npm config set loglevel=warn
RUN npm set loglevel=warn

COPY package.json .

RUN npm install --no-optional > /dev/null 2>&1
RUN npm install bower  > /dev/null 2>&1

COPY . .

RUN ./node_modules/.bin/bower install --config.interactive=false --allow-root  > /dev/null 2>&1

ENTRYPOINT ["/bin/bash", "/usr/local/cdt-tests/@run-tests.sh"]

我知道要使用的技巧,覆盖入口点并检查容器,如下所示:

docker run -it --entrypoint /bin/bash --name cdt-tests cdt-tests

但是,这不适用于我当前的用例,因为我想在 @run-tests.sh 完成后检查容器

所以我有两个问题:

  1. 如何在非守护程序容器完成运行后检查其文件系统?
  2. 如何获取为非守护程序容器创建的容器的容器 ID(不使用 $(docker ps))。

如果我执行docker ps -a,我会看到:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
08740a432d1c        cdt-tests           "/bin/bash /usr/lo..."   24 seconds ago      Exited (130) 7 seconds ago                       cdt-tests
f27a302b1d8f        cdt-server          "/bin/bash /usr/lo..."   38 seconds ago      Up 36 seconds                                    cdt-server
b854506e75df        cisco-selenium      "/opt/bin/entry_po..."   41 seconds ago      Up 39 seconds                4444/tcp            cdt-selenium
a37cab33b293        mongo               "docker-entrypoint..."   43 seconds ago      Up 41 seconds                27017/tcp           cdt-mongo

所以我们可以看到 cdt-tests 存在,即使它不是守护进程。

所以我们尝试检查它,如下所示:

docker exec cdt-tests /bin/bash

但我们得到一个错误:

Error response from daemon: Container 08740a432d1c8f014bc138c82706de1e9682a052c088531d60b33c6acbbd5559 is not running

怎么办?

【问题讨论】:

    标签: bash docker docker-entrypoint


    【解决方案1】:

    如何在非守护程序容器完成运行后检查其文件系统?

    使用docker cp。见docs

    docker cp 实用程序将 SRC_PATH 的内容复制到 DEST_PATH。您可以从容器的文件系统复制到本地机器,反之亦然,从本地文件系统复制到容器。 (...) CONTAINER 可以是正在运行或已停止的容器。 SRC_PATH 或 DEST_PATH 可以是文件或目录。

    另一种选择是将您的容器具体化为一个新图像并在其上运行 bash:

    docker commit <stopped-container> new_image_name
    docker run -it --entrypoint /bin/bash new_image_name
    

    如何获取为非守护程序容器创建的容器的容器 ID(不使用 $(docker ps))。

    1) 当您执行docker run -d 时,输出是已创建的容器 ID,因此您可以保存该信息:

    container_id=$(docker run -d .......)
    

    2) 这将显示已停止的测试容器:

    docker ps -a --filter ancestor=cdt-tests
    

    这会将最后停止的测试容器放入 var 中:

    container_id=$(docker ps -q -a --filter ancestor=cdt-tests | head -n1)
    

    每种情况都有许多其他变体。


    编辑。使用卷版本方法,您可以将单个文件绑定为卷:

    docker run -v ./tests.log:/path/to/logs/file.log -it --name cdt-tests cdt-tests
    

    【讨论】:

    • 嘿,罗伯特,我所说的非守护程序容器是指一个不使用 -d 标志运行的容器……但让我试试 docker cp 的想法……我不确定 docker cp 会不会工作,因为我可能会收到一条消息说“cdt-tests 容器没有运行”(因为它已经完成)。我想要做的是将目录的内容从容器复制到主机。我认为他们建议使用的另一个答案更好 -v dir:/dir
    • 您必须查看其他答案中的 cmets,您会明白我的意思。
    • 请注意,cp 可以正常工作,正如我所说:CONTAINER 可以是正在运行或已停止的容器。
    • 好吧,我会试试 docker cp...我不知道你为什么要大写 container
    【解决方案2】:

    我不知道问题 2。 但是对于问题 1,一个可能的解决方案是捕获退出信号——尽管这将在容器本身内执行。但我想如果目标是检查容器中的文件系统,您可以将结果通过管道传输到已安装的目录。

    例如在 run-tests.sh 脚本中添加

    exiting() {
      # do file system inspection here
    }
    
    # trap the exit signal
    trap exiting SIGINT SIGTERM EXIT
    

    编辑: 要将日志目录/文件挂载到主机,请使用 -v 选项,

    docker run -it -v $HOME/log:/var/log --name cdt-tests cdt-tests
    

    注意,使用 -v 选项时,请确保您没有挂载到容器的工作目录 - docker 会用主机内容覆盖它。

    docker cp 命令的其他答案也应该有效。我主要使用 -v ,因为在主机上运行日志意味着我可以在程序运行时使用 tail -f 检查或观看它。这取决于用例。要记住的另一件事是,如果程序运行正常,容器将退出而不会出错,并且无法复制。容器仅在错误退出时才保留。

    【讨论】:

    • 是的,谢谢,所以当我在 Jenkins(或作为 CI/CD 管道的一部分的远程服务器)上运行此测试脚本时,我不想阻止该过程完成..但是如果出现问题,我确实想给自己一个调试的机会。不知道该怎么办。
    • 我不确定我是否理解正确,如果您的意思是 run-tests.sh 脚本中的部分步骤,我想您可以检查脚本中程序的退出代码并记录它... 像 [[ $? != 0 ]]; echo "Error here" - 再次显示到已挂载目录中的日志文件,以便您事后检查。
    • @run-test.sh 脚本将写入容器中的一些日志文件......它目前没有设置为写入容器外的日志文件......虽然这看起来像我的现在最好的选择...您有显示如何挂载共享目录或其他内容的链接吗?
    • 在 docker run 命令中,使用 -v 选项,如 docker run -v $PWD:/log - 将当前主机目录挂载到容器日志目录
    • 你应该挂载到容器中不是你的工作目录的目录,否则它会覆盖它。通常,您可以在 Dockerfile 中标记要从主机挂载的目录,然后挂载到该目录。例如。在 Dockerfile VOLUME /var/log 命令行中 docker run -v $HOME/foo:/var/log
    猜你喜欢
    • 2019-08-13
    • 2019-06-01
    • 2020-12-13
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2018-07-11
    相关资源
    最近更新 更多