【问题标题】:How can I run a docker container and commit the changes once a script completes?脚本完成后,如何运行 docker 容器并提交更改?
【发布时间】:2015-08-16 22:10:10
【问题描述】:

我想设置一个 cron 作业以在 docker 容器内运行一组命令,然后将更改提交到 docker 映像。我可以将容器作为守护进程运行并使用以下命令获取容器 ID:

CONTAINER_ID=$(sudo docker run -d my-image /bin/sh -c "sleep 10")

但是我在第二部分遇到了问题——一旦sleep 10 命令完成,就提交对图像的更改。有没有办法让我知道 docker 容器何时将被杀死并在它之前运行另一个命令?

编辑:作为替代方案,有没有办法通过容器中的 shell 脚本触发 ctrl-p-q 以使容器保持运行但返回主机?

【问题讨论】:

    标签: bash docker sh commit


    【解决方案1】:

    持久化容器数据有以下几种方式:

    1. Docker 卷

    2. Docker 提交

      a) 从 ubuntu 镜像创建容器并运行 bash 终端。

         $ docker run -i -t ubuntu:14.04 /bin/bash
      

      b) 在终端内安装 curl

         # apt-get update
         # apt-get install curl
      

      c) 退出集装箱码头

         # exit
      

      d) 通过执行以下命令记下您的容器 ID:

         $ docker ps -a
      

      e) 将容器保存为新图像

         $ docker commit <container_id> new_image_name:tag_name(optional)
      

      f) 验证您是否可以看到安装了 curl 的新图像。

         $ docker images           
      
         $ docker run -it new_image_name:tag_name bash
            # which curl
              /usr/bin/curl
      

    【讨论】:

    • 这在更改环境变量时似乎不起作用。 export FOO="bar" 由于某种原因不会持续提交。
    • @Granitosaurus 那是因为您将它导出到当前运行的外壳中,然后退出外壳。这不是节省内存,而是节省您的存储空间。如果你想保存它,你必须把它放在你的 ~/.bashrc、/etc/profile 等中。
    • 自动化时,我不想查看docker ps -a 的输出,所以看起来像是从进程中吐出:docker run -i -t ubuntu:14.04 /bin/bash -c echo "MY_CONTAINER_ID=$HOSTNAME'"。然后我可以grep '^MY_CONTAINER_ID=' 来获取我(可能会或可能不会)想要提交的容器ID。
    【解决方案2】:

    在前台运行它,而不是作为守护进程。当它结束启动的脚本时,它会控制并提交/推送它

    【讨论】:

    • 感谢您的回复。我仍然无法在容器被杀死之前提交。有没有办法在命令被杀死之前运行它?或者有没有办法从 shell 脚本发送ctrl-p-q 信号以使容器保持运行但返回主机?
    • 容器结束,但没有被删除,您可以使用存储库或系统名称提交该容器 id。
    • 太棒了,谢谢!我不知道你可以在容器停止后提交它。
    • 这个答案需要关于如何获取容器id等的命令。
    【解决方案3】:

    我没有找到任何令人满意的答案,因为我的目标是 1) 启动一个容器,2) 运行一个设置脚本,以及 3) 捕获/存储设置后的状态,这样我就可以立即运行各种脚本后来反对那个状态。并且所有这些都在本地、自动化、持续集成环境中(例如脚本化和非交互式)。

    这是我想出的(我在 Travis-CI install 部分运行它)来设置我的测试环境:

    #!/bin/bash
    
    # Run a docker with the env boot script
    docker run ubuntu:14.04 /path/to/env_setup_script.sh
    
    # Get the container ID of the last run docker (above)
    export CONTAINER_ID=`docker ps -lq`
    
    # Commit the container state (returns an image_id with sha256: prefix cut off)
    # and write the IMAGE_ID to disk at ~/.docker_image_id
    (docker commit $CONTAINER_ID | cut -c8-) > ~/.docker_image_id
    

    请注意,我的基本图像是 ubuntu:14.04,但您的可以是您想要的任何图像。

    通过该设置,现在我可以针对此快照运行任意数量的脚本(例如单元测试)(对于 Travis,这些在我的 script 部分中)。例如:

    docker run `cat ~/.docker_image_id` /path/to/unit_test_1.sh
    docker run `cat ~/.docker_image_id` /path/to/unit_test_2.sh
    

    【讨论】:

      【解决方案4】:

      如果您想为所有正在运行的程序自动提交,请尝试此操作。如果有帮助,请将其放入 cron 或其他内容中

      #!/bin/bash
      for i in `docker ps|tail -n +2|awk '{print $1}'`; do docker commit -m "commit new change" $i; done
      

      【讨论】:

        猜你喜欢
        • 2017-11-12
        • 1970-01-01
        • 1970-01-01
        • 2018-05-20
        • 2018-05-16
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 2018-11-28
        相关资源
        最近更新 更多