【问题标题】:How to run a docker container if not already running如果尚未运行,如何运行 docker 容器
【发布时间】:2017-11-27 15:00:08
【问题描述】:

仅当 docker 容器尚未运行时,我才需要运行它。给出这个命令。如果它不存在,我将如何运行它。

docker run --name nginx -d nginx

我对任何脚本或语言持开放态度。

【问题讨论】:

    标签: bash docker


    【解决方案1】:

    我肯定会建议调查 docker-compose 和 docker-compose up,如上所述。

    由于您的问题是关于 docker run,我会像这样简化 VonC 的答案

    docker start nginx || docker run --name nginx -d nginx
    

    如果容器已经在运行,docker start 将返回0,因此不会执行docker run。如果容器存在但没有运行,docker start 将启动它,否则docker run 将创建并一次性启动它。

    VonC 的回答中缺少“存在但已停止”部分。

    【讨论】:

    • 您可能希望将 start 的 stderr 指向 dev null ,这样如果容器不存在,您就不会在脚本输出中收到大量错误文本,即docker start nginx 2>/dev/null || docker run --name nginx -d nginx
    【解决方案2】:

    使用过滤器检查某个名称的容器是否存在:
    (见docker ps Filterring)

    #!/bin/bash
    
    name='nginx'
    
    [[ $(docker ps -f "name=$name" --format '{{.Names}}') == $name ]] ||
    docker run --name "$name" -d nginx
    

    docker run 只有在第一部分为 false 时才会执行。

    为了安全起见(docker ps 可能会返回多个名称),您也可以这样做(如果您认为“nginx”这个词不能是任何容器名称的一部分):

    if ! docker ps --format '{{.Names}}' | grep -w nginx &> /dev/null; then
        docker run --name nginx -d nginx
    fi
    

    或者:

    if ! docker ps --format '{{.Names}}' | egrep '^nginx$' &> /dev/null; then
        docker run --name nginx -d nginx
    fi
    

    【讨论】:

    • 由于“名称过滤器匹配容器名称的所有或part”,docker start || docker run 似乎是一个更可行的选择。
    • @x-yuri == $name 应该限制为完全容器名称。但我同意,Eugen Mayer 的回答也很好(并且赞成)
    • 好点,但docker ps -f name=... 可能会返回不止一个名称(nginx\ns1_nginx... 或其他名称),因此使用if docker ps --format '{{.Names}}' | egrep '^nginx$' &> /dev/null; then ...; fi 似乎是一个更安全的选择。
    • @x-yuri 是,或者grep -w "nginx"
    • @x-yuri 顺便说一下,随意编辑答案并添加更安全的替代方案:我(和任何其他读者)将不胜感激:)
    【解决方案3】:

    如果您对任何语言持开放态度,我建议您使用 docker-compose 来完成此任务。安装后,使用以下内容创建一个名为 docker-compose.yml 的文件:

    version: '2'
    services:
      nginx:
        image: 'nginx' 
    

    然后使用:

    docker-compose up -d
    

    它会一直检查容器是否已经在运行。如果容器不存在,它将创建并运行。如果容器停止,它只是运行它。

    最好的是,如果您更改 docker-compose.yml 或拉取新版本的映像,它将自动重新创建容器,保留所有卷,即使是未命名的卷。

    问候

    【讨论】:

    • 如果使用不同的网络,情况似乎并非如此。我专门为我的 CI 服务器创建了一个网络,并运行了一个带有别名的容器。在我的撰写文件中引用了相同的容器/别名,它抱怨冲突。网络是我唯一能做到的。
    【解决方案4】:

    如果目的是幂等性并且有问题的容器是可替代的(如您的示例中的情况),那么系统的当前状态(是否正在运行)并不重要。

    在一张白纸上。

    $ docker ps -a --format '{{.Names}}' | wc -l
    0
    

    在容器存在时执行强制删除和创建。

    $ docker run --name=hello -d alpine sleep inf
    0f6175804d69d48cdada66de57cb62c2855d1085c08a69f21e782c433be2c6a2
    $ docker ps --format '{{.Names}}'
    hello
    $ docker rm -f hello ||:
    hello
    $ docker run --name=hello -d alpine sleep inf 
    ...
    

    和没有的时候完全一样。

    $ docker ps -a --format '{{.Names}}' | wc -l
    0
    $ docker rm -f hello 2>/dev/null ||:
    $ docker run --name=hello -d alpine sleep inf
    d0210fefc7e934fea6d669615538596cf372f15e9095edae81c35965ff021898
    

    执行条件检查时完全一样。

    $ docker ps -a --format '{{.Names}}'
    hello
    $ if ! docker ps -a --format '{{.Names}}' | grep hello >/dev/null ;then 
    > docker run --name=hello -d alpine sleep inf 
    > fi
    $ docker rm -f hello
    hello
    $ if ! docker ps -a --format '{{.Names}}' | grep hello >/dev/null ;then 
    > docker run --name=hello -d alpine sleep inf 
    > fi
    1edcbba0c01979edbe05072bd3c15b6ecfb129d9e20d45a33eff0921cc5f2ed3
    

    这使得 force-remove/create 成为幂等操作,而我们对状态、后操作的保证使条件变得毫无意义和笨拙。

    如果你的容器必须观察一些底层状态,那么就忘记这一切吧。

    【讨论】:

      猜你喜欢
      • 2015-06-18
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多