1. 概述
Docker 容器本质上是运行一个进程、应用或脚本的载体。当容器内没有任何进程或脚本运行时,容器会自动停止并退出。像 MySQL 数据库、Spring Boot 应用或 SMTP 邮件服务器这类容器,默认会持续运行直到用户手动停止。但有时我们需要让容器在完成主要任务后仍保持运行状态,比如 Ubuntu 容器。
本文将介绍在 Docker Compose 中实现这一目标的几种方法。
2. Docker Compose 环境准备
Docker Compose 是用于定义和运行多容器服务的工具。只需在支持的操作系统(本教程使用 Linux Ubuntu)上安装 Docker(包括 Docker Server、Client 和 Compose)即可开始。
3. 运行 Ubuntu 容器
我们使用名为 docker-compose.yml
的配置文件定义服务:
services:
demo:
image: ubuntu
3.1. 启动 Docker Compose 服务
使用 -d
选项在后台运行服务容器:
$ docker-compose up -d
命令输出显示容器创建成功:
Creating ubuntu_demo_1 ... done
检查容器运行状态(使用 docker ps -a
列出所有容器):
$ docker ps -a
输出显示容器已退出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a66cec15e72c ubuntu "/bin/bash" 10 seconds ago Exited (0) 9 seconds ago ubuntu_demo_1
Docker Compose 创建的 ubuntu_demo_1
容器启动后立即退出。接下来我们通过以下方法保持容器运行:
✅ 分配伪终端(TTY)
✅ 使用 tail
命令
✅ 使用 sleep
命令
✅ 使用无限循环脚本
3.2. 测试间清理环境
在尝试不同方法前,建议清理环境(使用 docker-compose down
移除容器):
$ docker-compose down
Stopping ubuntu_demo_1 ... done
Removing ubuntu_demo_1 ... done
Removing network ubuntu_default
此命令会同时删除关联的网络和卷。
4. 分配伪终端(TTY)
为 Ubuntu 容器分配伪终端可保持其运行。伪终端(pseudo-TTY)通过软件模拟终端会话,无需物理设备驱动。
在配置文件中添加 tty: true
:
services:
demo:
image: ubuntu
tty: true
启动服务并检查状态:
$ docker-compose up -d
$ docker ps
输出显示容器持续运行:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dcc44f90a9eb ubuntu "/bin/bash" 16 seconds ago Up 13 seconds ubuntu_demo_1
分配 TTY 后,Docker 守护进程会保持主进程运行,从而维持容器状态。
5. 使用 tail
命令
**另一种简单粗暴的方法是使用 tail
命令**:
services:
demo:
image: ubuntu
command: "tail -f /dev/null"
这里利用 tail -f
持续读取输入,/dev/null
作为"永远读不完"的设备,使容器保持运行。
启动服务后验证:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5b293dbf6cc9 ubuntu "tail -f /dev/null" 18 seconds ago Up 17 seconds ubuntu_demo_1
容器成功保持运行状态。
6. 使用 sleep
命令
通过 sleep
命令也能维持容器运行:
services:
demo:
image: ubuntu
command: "sleep infinity"
此方法本质是在容器 bash 中创建 TTY,infinity
参数使命令永不结束。
验证容器状态:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c55a8b1f3839 ubuntu "sleep infinity" 2 minutes ago Up 2 minutes ubuntu_demo_1
容器持续运行中。
7. 使用无限循环脚本
结合 while
和 do
命令创建无限循环脚本:
services:
demo:
image: ubuntu
command: "sh -c 'while true; do sleep 1; done'"
启动服务后检查:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f690849f774 ubuntu "sh -c 'while true; …" 14 seconds ago Up 12 seconds ubuntu_demo_1
while true
条件永远成立,容器持续运行。
⚠️ 相比 sleep infinity
,无限循环的优势在于可在循环中执行其他任务(如输出日志或检查进程状态)。
8. 为何不适用于 hello-world
镜像?
注意:并非所有容器都能用上述方法保持运行。前述方法的前提是容器内能运行 bash 和 Linux 命令,这对 Ubuntu 等基础镜像有效。
但 hello-world
镜像无法保持运行,查看其 Dockerfile:
FROM scratch
COPY hello /
CMD ["/hello"]
scratch
是极简基础镜像,不提供 Linux 环境,因此无法执行 bash 或其他命令。
9. 总结
本文介绍了在 Docker Compose 中保持容器运行的四种方法。需注意:并非所有容器都需要显式配置——像数据库或 Web 应用这类容器,其主进程会自然保持运行状态。
同时,某些容器(如 hello-world
)因缺乏 Linux 环境,无法通过命令维持运行。选择方法时需根据镜像特性判断。
本文涉及的 Docker 命令脚本可在 GitHub 获取。