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 + grep
或 docker inspect
,它们简单高效,适合大多数自动化场景,如 Jenkins 任务、部署脚本等。