Bash 在非守护进程Docker容器完成运行后检查它

Bash 在非守护进程Docker容器完成运行后检查它,bash,docker,docker-entrypoint,Bash,Docker,Docker Entrypoint,我有一个用来创建的容器 # 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测试的Dockerfile如下所示: FROM node:6

我有一个用来创建的容器

# 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测试的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完成后检查容器

所以我有两个问题:

  • 在非守护进程容器完成运行后,如何检查其文件系统
  • 如何获取为非守护进程容器创建的容器的容器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测试在那里,即使它不是守护进程

    所以我们试着检查它,像这样:

    docker exec cdt-tests /bin/bash
    
    但我们得到了一个错误:

    Error response from daemon: Container 08740a432d1c8f014bc138c82706de1e9682a052c088531d60b33c6acbbd5559 is not running
    

    怎么办?

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

    e、 g.在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检查或观看它。这取决于用例。要记住的另一件事是,如果程序运行正常,容器将无误退出,并且无法进行复制。容器只有在错误退出时才被保留

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

    使用
    docker cp
    。见

    docker cp实用程序将SRC_PATH的内容复制到DEST_PATH。您可以从容器的文件系统复制到本地计算机,也可以从本地文件系统复制到容器。(…)容器可以是正在运行或已停止的容器。SRC_路径或DEST_路径可以是文件或目录

    另一个选项是将容器具体化为一个新图像,并在其上运行bash:

    docker commit <stopped-container> new_image_name
    docker run -it --entrypoint /bin/bash new_image_name
    
    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
    

    是的,谢谢,所以当我在Jenkins上运行这个测试脚本时(或者在某个作为CI/CD管道一部分的远程服务器上),我不想停止这个过程的完成。但是我确实想给自己一个机会,在出现问题时调试一些东西。不确定该怎么办。我不确定我是否理解正确,如果您是指run-tests.sh脚本中的部分步骤,我想您可以检查脚本中程序的退出代码并将其记录下来。。。类似于[[$?!=0];回显“此处出错”-再次写入已装入目录中的日志文件,以便以后检查。@run-test.sh脚本将写入容器中的某些日志文件…当前未设置为写入容器外部的日志文件…尽管这似乎是我目前的最佳选择…您是否有显示如何装入共享目录或其他内容的链接?在docker run命令,使用-v选项,如docker run-v$PWD:/log-mount current host directory to container log directory您应该装载到容器中不是您的工作目录的目录,否则它会覆盖它。通常,您可以在Dockerfile中标记要从主机装入的目录,然后装入该目录。例如,在Dockerfile VOLUME/var/log命令行docker run-v$HOME/foo:/var/logHey Robert中,我所说的非deamon容器是指未使用-d标志运行的容器……但让我试试docker cp的想法……我不确定docker cp是否有效,因为我可能会收到一条消息说“cdt tests container未运行”(因为它已经完成了)。我想做的是将目录的内容从容器复制到主机。我认为另一个答案更好,因为他们建议使用-v dir:/dir。您必须查看另一个答案中的注释,您将了解我的意思。请注意,cp是有效的,正如我所说:容器可以是正在运行或停止的容器。好的,我将尝试docker cp那么…我不知道你为什么把容器大写
    docker run -v ./tests.log:/path/to/logs/file.log -it --name cdt-tests cdt-tests