跳到主要内容

Docker 基本命令

· 阅读需 6 分钟

刚开始用 Docker 的时候,最常见的困惑不是概念,而是"这个操作到底该敲哪条命令"。这篇把日常用得最多的一组基本命令整理出来,每条都给出格式和例子,方便随手查。

在看具体命令之前,先理清一件事:镜像(image)和容器(container)是两个东西。镜像是只读的模板,包含了运行程序所需的文件系统和配置;容器则是镜像的一个运行实例,在镜像之上加了一层可写层。同一个镜像可以启动多个互不干扰的容器。下面的命令基本都是围绕这两个对象展开的——有的操作镜像(pull、images、rmi),有的操作容器(run、ps、rm、kill、restart、start、exec),分清对象,命令就不容易记混。

另外,Docker 守护进程默认以 root 权限运行,普通用户需要加 sudo 才能执行 docker 命令(或者把用户加入 docker 组),所以下面的例子大多带着 sudo

帮助

docker -h

忘记命令或参数时,先看帮助。也可以对具体子命令查帮助,比如 docker run --help,会列出该子命令支持的所有选项。

获取镜像

# 格式:NAME 是镜像名,TAG 是版本标签
sudo docker pull NAME[:TAG]

# 例:拉取 centos 的 latest 标签
sudo docker pull centos:latest

pull 从镜像仓库(默认是 Docker Hub)把镜像下载到本地。如果不写 TAG,默认拉取 latest。镜像是分层存储的,拉取时能看到多个层各自的下载进度,已经存在于本地的层会直接复用,不会重复下载。

启动 Container

# 格式
sudo docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 例:基于镜像启动一个交互式容器(原文镜像名为 contos,应为 centos)
sudo docker run -t -i contos /bin/bash

run 做的事情其实是两步:先基于镜像创建一个新容器,再启动它。几个常用参数:

1)-i:保持标准输入打开,能向容器里输入内容;

2)-t:分配一个伪终端,配合 -i 就能得到一个可交互的 shell;

3)镜像名后面跟的 /bin/bash 是容器启动后执行的命令,这个命令退出,容器也就停止了。

如果本地没有对应镜像,run 会先自动执行一次 pull。

查看镜像列表

列出本地的所有 images:

# 格式
sudo docker images [OPTIONS] [NAME]

# 例:只看 centos 相关的镜像
sudo docker images centos

输出里会显示镜像的仓库名、标签、镜像 ID、创建时间和大小。后面删除镜像时用到的就是这里的名字或 ID。

查看容器列表

可看到我们创建过的所有 container:

# 格式
docker ps [OPTIONS]

# 例:-a 列出所有容器,包括已经停止的
sudo docker ps -a

注意 docker ps 默认只显示正在运行的容器。刚退出的容器用 ps 看不到,很容易误以为容器"消失"了,加上 -a 才能看到全部。输出中的 CONTAINER ID 和 NAMES 都可以用来在后续命令里指定容器。

删除镜像

从本地删除一个已经下载的镜像:

# 格式:可以一次删多个
sudo docker rmi IMAGE [IMAGE...]

# 例
sudo docker rmi centos:latest

如果还有容器(哪怕是停止状态的)基于这个镜像创建,rmi 会报错拒绝删除,需要先把相关容器 rm 掉。

移除容器实例

移除一个或多个容器实例:

# 格式
sudo docker rm [OPTIONS] CONTAINER [CONTAINER...]

移除所有运行的容器:

# 原文写法如下,实际使用时中间的命令要用 $() 或反引号做命令替换:
# sudo docker rm $(sudo docker ps -aq)
sudo docker rm sudo docker ps -aq

这里 docker ps -aq-q 表示只输出容器 ID,把它作为参数传给 docker rm,就实现了批量删除。正在运行的容器不能直接 rm,要先停止,或者加 -f 强制删除。

停止一个正在运行的容器

# 格式
sudo docker kill [OPTIONS] CONTAINER [CONTAINNER...]

# 例:容器 ID 写前几位即可,能唯一定位就行
sudo docker kill 026e

kill 默认向容器内的主进程发送 SIGKILL,进程会被立即杀掉,没有清理的机会。如果希望程序有机会优雅退出,用 docker stop 更合适——它先发 SIGTERM,等待一段时间后才发 SIGKILL。

重启一个正在运行的容器

# 格式
sudo docker restart [OPTIONS] contains[CONTAINER]

# 例
sudo docker restart 026e

restart 相当于先停止再启动,容器可写层里的数据仍然保留。

启动一个已经停止的容器

# 格式
sudo docker start [OPTIONS] CONTAINER [CONTAINER..]

# 例
sudo docker start 026e

注意 startrun 的区别:run 会创建容器,而 start 只是把一个已存在但停止了的容器重新拉起来,之前在容器里做过的修改都还在。

进入指定容器

docker exec -it <容器名称或编号> /bin/bash

exec 在一个正在运行的容器里额外启动一个进程,这里就是再开一个 bash。它比 attach 更常用:从 exec 进去的 shell 里 exit,只是退出这个新开的进程,不会影响容器本身的运行。

踩坑与注意

1)镜像 ID 与容器 ID 不要混用rmi 删镜像、rm 删容器,参数传错了会报"没有该对象"的错误。

2)容器停止不等于删除。停止的容器仍然占着名字和磁盘上的可写层,新容器如果用了相同的名字会创建失败,需要先 rm 掉旧的。

3)优先用 stop 而不是 kill。除非进程卡死不响应,否则给应用一个收到 SIGTERM 后做清理的机会。

4)容器里的数据是易失的。容器被 rm 之后,可写层里的数据一并消失,重要数据应该通过数据卷挂载到宿主机。

小结

这一组命令覆盖了 Docker 的最小工作闭环:pull 拿镜像,run 起容器,images / ps 查看状态,start / stopkill)/ restart 控制生命周期,exec 进入容器排查问题,最后用 rm / rmi 清理容器和镜像。把"镜像是模板、容器是实例"这条主线记住,剩下的就是熟练度问题了。

评论 / COMMENTS