Docker 基本命令
刚开始用 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
注意 start 和 run 的区别: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 / stop(kill)/ restart 控制生命周期,exec 进入容器排查问题,最后用 rm / rmi 清理容器和镜像。把"镜像是模板、容器是实例"这条主线记住,剩下的就是熟练度问题了。
评论 / COMMENTS