停止已运行一段时间的 Docker 容器



我想创建一个 cron 作业,如果 Docker 容器运行超过 2 小时,它将停止它们。

我可以得到他们开始的时间。

$ docker inspect -f '{{ .State.StartedAt }}' $(docker ps -q)

只需要将其与 2 小时前进行比较...

$ date --utc --date="-2 hours" +"%Y-%m-%dT%H:%M:%S.%NZ"

。如果更早停止容器

$ docker stop <<container_id>>

如何使用 bash 脚本执行此操作?

这是一个古老的线程,但如果有人正在寻找答案,它仍然如此。以下命令将停止运行超过 2 小时的容器。

docker ps --format="{{.RunningFor}} {{.Names}}"  | grep hours |  awk -F: '{if($1>2)print$1}' | awk ' {print $4} ' | xargs docker stop

解释:

docker ps --format="{{.RunningFor}} {{.Names}}" 

将打印容器名称和运行周期。

grep hours 

将打印以小时为单位运行的包含。

 awk -F: '{if($1>2)print$1}' 

将仅打印运行超过 2 小时的容器。

awk ' {print $4} ' | xargs docker stop

将打印从先前输出中获取的容器名称,并将其作为参数传递以停止容器。

早在

2013 年第 1905 期中就对此进行了讨论

bash的替代方案是:

#!/bin/bash
set -e
to=$1
shift
cont=$(docker run -d "$@")
code=$(timeout "$to" docker wait "$cont" || true)
docker kill $cont &> /dev/null
echo -n 'status: '
if [ -z "$code" ]; then
    echo timeout
else
    echo exited: $code
fi
echo output:
# pipe to sed simply for pretty nice indentation
docker logs $cont | sed 's/^/t/'

跟:

$ docker-run-timeout.sh 10s busybox sh -c 'echo start && sleep 30 && echo finish'
status: timeout
output:
    start

请注意,在 docker 1.13 中,您可以使用 --rm -d 运行(请参阅 PR 20848)。

来自@Siru的单行代码很棒,但是我不得不更改下面的部分才能正确找到超过两位数天数的容器:

awk -F " " '{if($1>14)print$0}'
我希望

在格式字符串的 Go 模板中执行此操作,但我认为我们没有任何时间解析包含的函数(可能会成为一个不错的 PR)。

相反,下面是一个利用日期命令进行时间解析的版本:

#!/bin/sh
# adjust threshold as needed
threshold="2 hours"
# cutoff is seconds since epoc of the threshold time
cutoff="$(date --date="-$threshold" "+%s")"
# loop through the running containers by id
docker container ls -q | while read cid; do
  # retrieve the start time as a string
  startedat="$(docker container inspect "$cid" --format "{{.State.StartedAt}}")"
  # convert to seconds since epoc
  start="$(date --date="$startedat" "+%s")"
  # then we can do a numeric comparison in shell
  if [ "$start" -lt "$cutoff" ]; then
    docker container stop "$cid"
  fi
done

有关使用日期计算偏移量的其他示例,请参阅 unix.SE 中的这篇文章。

@siru的解决方案启发我寻找一个选项来了解要控制的确切时间,因为 docker ps running for是一个四舍五入的格式化结果,并不精确:

docker ps -q | xargs docker inspect --format='{{.Id}} {{.State.StartedAt}}' |
 awk '{"date -d " $2 " +%s" | getline startedAt
 "date +%s" | getline now
 if((now-startedAt)/(60*60) > 5) print $1}' |
 xargs docker rm -f

说明:

第一行将以 ISO 8601 格式传递容器 ID 及其开始时间的列表。

然后我们将每个日期转换为 UNIX 时间,从当前时间计算增量,并仅传递运行时间超过指定时间的行docker rm -f

在此示例中,将删除运行超过 6 小时的所有容器。

我使用这个简单的方法(源自 Siru 的答案)来阻止任何运行超过 24 小时的内容。

docker ps --format="{{.ID}} {{.RunningFor}}" | grep "day|week|month" | awk '{print $1}' | xargs docker stop

如果您运行了这个以及 Siru 的答案,那么您可以可靠地清理到特定的小时数,但在这一点上,使用 Itiel 的解决方案可能会更好。

最新更新