1. 概述

在 Jenkins 这样的自动化环境中使用 Docker 时,我们常常会遇到一种情况:只有在容器不存在时才创建它。如果不加判断直接运行 docker run 创建容器,可能会导致错误,从而让 Jenkins 任务失败。

为避免这种情况,我们可以使用 Bash 脚本来判断指定名称的 Docker 容器是否已经存在。本文将介绍几种常见的实现方式。

2. 使用 docker ps 配合 grep

最简单的方法是通过 docker ps 命令列出所有容器,并使用 grep 过滤出目标容器名称。示例脚本如下:

if ! docker ps -a --format '{{.Names}}' | grep -wq "container_name"; then
  docker run -d --name container_name container_image
else
  echo "Container exists"
fi

说明:

  • docker ps -a 列出所有容器(包括停止的)
  • --format '{{.Names}}' 只输出容器名称
  • grep -wq 精确匹配名称并静默输出结果
  • 如果未找到容器,则执行创建命令

⚠️ 注意: 名称匹配建议使用 -w 参数确保精确匹配,避免误匹配部分名称。

3. 使用 docker inspect

另一个更直接的方式是使用 docker inspect 命令。如果容器不存在,该命令将返回非零退出码,可以用于判断。

if ! docker inspect container_name > /dev/null 2>&1; then
  docker run -d --name container_name container_image
else
  echo "Container exists"
fi

说明:

  • docker inspect 会返回容器详细信息
  • > /dev/null 2>&1 表示不输出任何信息(包括错误)
  • 如果命令执行失败(即容器不存在),则创建容器

⚠️ 注意: 这种方式虽然简洁,但可能因权限或网络问题误判,建议用于脚本中较稳定的环境。

4. 使用 docker container ls 配合 --filter

我们也可以使用 docker container ls 命令配合 --filter 来精确匹配容器是否存在:

if [ -z "$(docker container ls -a --filter name=^/container_name$ --format '{{.Names}}')" ]; then
  docker run -d --name container_name container_image
else
  echo "Container exists"
fi

说明:

  • --filter name=^/container_name$ 表示精确匹配容器名
  • --format '{{.Names}}' 只输出容器名
  • -z 判断输出是否为空,为空说明容器不存在

5. 使用 Docker Compose 配合条件判断

如果你使用的是 Docker Compose,可以使用如下脚本判断服务是否已启动:

if ! docker-compose ps | grep -wq "container_name"; then
  docker-compose up -d
else
  echo "Container exists"
fi

说明:

  • docker-compose ps 显示当前 compose 项目中所有容器的状态
  • grep -wq 判断是否存在目标容器
  • 如果不存在,则启动服务

⚠️ 注意: 此方法适用于基于 docker-compose.yml 的项目。

6. 使用 Docker API(基于 curl)

虽然复杂一些,但通过调用 Docker 的本地 API 接口,我们可以实现更高级的判断逻辑:

container_name="my_container"
curl --unix-socket /var/run/docker.sock http://localhost/containers/$container_name/json | grep -q '"Id":'
if [ $? -eq 0 ]; then
    echo "Container exists"
else
    docker run -d --name container_name container_image
fi

说明:

  • 通过 curl 向 Docker Daemon 发起请求
  • 返回 JSON 数据,包含容器信息
  • 使用 grep 检查是否存在 "Id": 字段来判断容器是否存在

⚠️ 注意: 此方法需要脚本运行用户有访问 /var/run/docker.sock 的权限。

7. 封装为函数提高复用性

上述方法都可以封装成函数,提升脚本的可维护性和复用性。例如:

container_exists() {
  docker ps -a --format '{{.Names}}' | grep -wq "$1"
}

if ! container_exists "container_name"; then
  docker run -d --name container_name container_image
fi

说明:

  • 将判断逻辑封装为 container_exists 函数
  • 调用函数时传入容器名作为参数
  • 代码更清晰,易于维护

8. 总结

本文介绍了多种在 Bash 脚本中判断 Docker 容器是否存在的方式,包括:

方法 命令 优点 踩坑点
docker ps + grep docker ps -a | grep 简单直观 注意精确匹配
docker inspect docker inspect 精确、简洁 权限问题可能导致误判
docker container ls --filter docker container ls --filter 精确匹配 命令稍复杂
Docker Compose docker-compose ps 适合 compose 项目 仅适用于 compose 项目
Docker API curl + docker.sock 灵活、强大 需要权限支持

在实际使用中,推荐优先使用 docker ps -a + grepdocker inspect,它们简单高效,适合大多数自动化场景,如 Jenkins 任务、部署脚本等。


原始标题:Execute a Bash Command Conditionally Based on Docker Container Existence