Docker 基础命令速查与实战指南
1. 引言
Docker 作为现代应用开发和部署的基石,其命令行工具是与容器交互的核心。掌握常用 Docker 命令,能极大提升开发、测试和运维效率。本文将以实战为导向,系统梳理并详解一系列高频 Docker 命令,涵盖镜像管理、容器生命周期、日志查看、文件操作等核心场景,助你快速上手 Docker 日常操作。
2. 镜像管理
镜像是容器运行的基础模板,管理镜像是 Docker 操作的第一步。
2.1 删除镜像
使用 docker rmi 命令删除本地镜像。-f 参数用于强制删除,即使有容器正在使用该镜像(慎用)。
镜像名与镜像ID:命令中的 <镜像名或ID> 可以是镜像的完整名称(如 ubuntu:22.04)、仓库名(如 nginx)或镜像ID(如 docker images 列出的短ID或长ID)。通常使用镜像名(带标签)更为直观。如果镜像存在多个标签,删除其中一个标签不会删除镜像层,只有删除最后一个标签或使用镜像ID时才会真正移除镜像数据。
# 删除指定镜像
docker rmi <镜像名或ID>
# 强制删除指定镜像
docker rmi -f <镜像名或ID>
2.2 列出镜像
docker images 用于列出本地镜像,常用组合参数如下:
# 列出所有镜像(包括中间层镜像)
docker images -a
# 只显示镜像ID
docker images -q
# 组合使用:列出所有镜像的ID
docker images -a -q
# 或简写为
docker images -aq
2.3 拉取与搜索镜像
从远程仓库获取镜像是常见操作。
# 从 Docker Hub 拉取指定镜像(默认最新标签)
docker pull <镜像名>[:标签]
# 示例:拉取 Ubuntu 22.04
docker pull ubuntu:22.04
# 在 Docker Hub 中搜索镜像
docker search <关键词>
# 示例:搜索与 Nginx 相关的镜像
docker search nginx
2.4 镜像构建与历史
除了从仓库拉取,我们还可以通过构建或提交容器来创建镜像。
从容器创建镜像 (docker commit):将当前容器的文件系统更改保存为一个新的镜像层,常用于快速保存实验状态或创建自定义镜像。
# 将正在运行的容器提交为新镜像
docker commit <容器名或ID> [新镜像名[:标签]]
# 示例:将容器 myapp 提交为镜像 myapp:v1
docker commit myapp myapp:v1
- 提交时会包含容器的文件系统更改、环境变量、工作目录等,但不包含数据卷中的数据。
- 通常用于临时保存状态,生产环境更推荐使用
docker build和 Dockerfile 进行可重复构建。
从 Dockerfile 构建镜像 (docker build):这是创建自定义镜像的标准方式,通过编写 Dockerfile 定义构建步骤,确保构建过程可重复、可版本化。
# 在当前目录(包含 Dockerfile)构建镜像
docker build -t <镜像名:标签> .
# 示例:构建并标记为 myapp:latest
docker build -t myapp:latest .
# 使用 -f 参数指定 Dockerfile 路径
docker build -f <Dockerfile路径> -t <镜像名:标签> <构建上下文路径>
# 示例:使用子目录中的 Dockerfile 构建
docker build -f ./dockerfiles/Dockerfile.prod -t myapp:custom .
-t:为构建的镜像指定名称和标签。-f:指定 Dockerfile 的路径(默认查找当前目录下的Dockerfile文件)。.:指定构建上下文路径(通常为 Dockerfile 所在目录)。- Dockerfile 中每一条指令(如
FROM、RUN、COPY、CMD)都会生成一个镜像层。
查看镜像构建历史 (docker history):显示镜像的构建层历史,包括每层的大小、创建命令等,有助于调试和优化镜像。
# 查看指定镜像的构建历史
docker history <镜像名或ID>
# 显示完整命令(不截断)
docker history --no-trunc <镜像名或ID>
# 仅显示镜像ID和创建命令
docker history --format "{{.ID}}\t{{.CreatedBy}}" <镜像名或ID>
- 输出按层从最新到最旧排列。
- 可用于检查镜像层内容、排查构建问题或优化 Dockerfile。
3. 容器生命周期管理
容器是镜像的运行实例,管理其创建、运行和停止是核心任务。
3.1 创建并运行容器
docker run 是最重要的命令之一,用于从镜像创建并启动一个新容器。
# 交互式运行一个容器
docker run -it <镜像名> <启动命令>
# 示例:运行 Ubuntu 22.04 容器并进入其 bash shell
docker run -it ubuntu:22.04 /bin/bash
-i:保持标准输入(STDIN)打开,允许交互。-t:分配一个伪终端(pseudo-TTY)。
启动命令 (/bin/bash):/bin/bash 是容器启动后要执行的命令,它启动一个 Bash Shell 会话。-it 参数(交互式终端)与 /bin/bash 结合,使得我们能够立即进入容器的命令行环境进行交互操作。如果省略此命令,容器会使用镜像中定义的默认命令(CMD)启动,可能不会提供交互式 Shell。
数据卷挂载 (-v):-v 参数用于将主机上的目录或文件挂载到容器内部,实现数据持久化和共享。其基本语法为 -v <主机目录>:<容器内目录>。
# 将主机 /home/user/data 目录挂载到容器的 /app/data 目录
docker run -it -v /home/user/data:/app/data ubuntu:22.04 /bin/bash
- 如果容器内目录不存在,Docker 会自动创建。
- 挂载后,数据是双向同步的:在容器内对
/app/data的读写会直接反映到主机的/home/user/data目录,反之亦然。 - 主机目录路径可以是绝对路径(如
/home/user/data)或相对路径(如./data),但建议使用绝对路径以避免混淆。 - 此功能常用于配置文件、日志、数据库文件等需要持久化或与主机共享的场景。
Docker 卷 (docker volume):-v 参数使用的是绑定挂载,直接将主机目录映射到容器。Docker 还提供了更高级的卷(Volume)机制,用于持久化存储和容器间共享数据。卷由 Docker 管理,独立于容器的生命周期,通常存储在 /var/lib/docker/volumes/ 下,比绑定挂载更安全、更易备份和迁移。
# 创建一个名为 mydata 的卷
docker volume create mydata
# 列出所有卷
docker volume ls
# 查看卷详情
docker volume inspect mydata
# 使用卷运行容器(将卷挂载到容器内路径)
docker run -it -v mydata:/app/data ubuntu:22.04 /bin/bash
# 删除未使用的卷
docker volume prune
- 卷 vs 绑定挂载:绑定挂载 (
-v /host/path:/container/path) 依赖主机目录结构,卷 (-v volume_name:/container/path) 由 Docker 管理,不依赖主机路径。 - 卷的优势:跨容器共享、备份恢复更方便(
docker volume create/backup)、更好的性能(某些存储驱动)、更安全(避免主机路径暴露)。 - 常用场景:数据库数据文件(如 MySQL 的
/var/lib/mysql)、应用配置文件、需要持久化的用户上传文件等。
容器间共享卷 (--volumes-from):--volumes-from 参数允许新容器挂载另一个容器已挂载的所有数据卷,实现容器间的数据共享。这在多容器应用(如 Web 应用与数据库)中非常有用,无需重复定义卷或绑定挂载。
# 创建一个使用卷的容器(源容器)
docker run -d --name app-server -v app-data:/data nginx
# 创建另一个容器,共享 app-server 的所有卷
docker run -it --volumes-from app-server ubuntu:22.04 /bin/bash
- 工作原理:新容器会继承源容器(
app-server)的所有卷挂载点,访问相同的卷数据。 - 使用场景:
- 备份容器:创建一个临时容器,使用
--volumes-from挂载数据卷,然后执行备份命令。 - 数据迁移:在两个容器间迁移数据,无需通过主机中转。
- 多服务共享配置:多个服务容器共享同一套配置文件卷。
- 备份容器:创建一个临时容器,使用
- 注意事项:
- 源容器无需运行,只要存在即可。
- 共享的是卷定义,不是文件系统;每个容器对卷的读写是独立的,但数据通过卷同步。
- 删除源容器不会自动删除共享的卷,卷的生命周期由 Docker 管理(除非使用
docker volume rm手动删除)。
后台运行 (-d):-d 参数让容器在后台运行(detached mode),不占用当前终端。这对于运行 Web 服务器、数据库等需要长期运行的服务非常有用。
# 以后台模式运行一个 Nginx 容器
docker run -d nginx
运行后,容器会在后台启动,并返回一个容器 ID。可以使用 docker ps 查看其运行状态,使用 docker logs <容器ID> 查看其输出。
端口映射 (-p):-p 参数将主机的端口映射到容器的端口,使得外部可以通过主机 IP 和端口访问容器内服务。语法为 -p <主机端口>:<容器端口>。
# 将主机的 8080 端口映射到容器的 80 端口
docker run -d -p 8080:80 nginx
运行后,在浏览器中访问 http://localhost:8080 即可看到 Nginx 的欢迎页面。可以指定多个 -p 参数来映射多个端口。
设置环境变量 (-e):-e 参数用于向容器内传递环境变量,这对于配置应用行为(如数据库连接字符串、API密钥、运行模式等)非常有用。可以多次使用 -e 来设置多个变量。
# 运行一个 MySQL 容器,并设置 root 密码和环境变量
docker run -d --name mysql-db \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=myapp \
mysql:8.0
- 环境变量在容器内部通过
echo $变量名或应用代码读取。 - 可以使用
--env-file参数从文件批量加载环境变量。
指定容器名称 (--name):--name 参数为容器指定一个自定义名称,便于后续通过名称(而非随机生成的容器ID)来引用和管理容器。
# 运行一个 Nginx 容器,并命名为 my-web
docker run -d --name my-web -p 8080:80 nginx
- 容器名称在宿主机上必须唯一。
- 指定名称后,可以使用
docker stop my-web、docker logs my-web等命令,比使用容器ID更方便。
3.2 查看容器
docker ps 用于列出容器。
# 查看正在运行的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
3.3 启动、停止与重启容器
对于已存在的容器(无论是已停止还是正在运行),可以使用以下命令管理其运行状态。
启动容器 (docker start):启动一个已停止的容器。
# 启动一个已停止的容器
docker start <容器名或ID>
# 启动并附加到容器的输出(类似 docker run -it 的交互效果)
docker start -a <容器名或ID>
# 启动并在后台运行(默认行为)
docker start <容器名或ID>
- 如果容器之前是以交互式模式(
-it)运行的,docker start默认在后台启动,不会自动附加终端。使用-a(attach)参数可以连接到容器的标准输出/错误流。 - 启动后,容器会以原来的配置(端口映射、卷挂载、环境变量等)运行。
停止容器 (docker stop):优雅地停止一个运行中的容器,发送 SIGTERM 信号,允许容器进行清理操作。
# 停止一个运行中的容器
docker stop <容器名或ID>
# 指定超时时间(秒),超时后强制停止
docker stop -t <秒数> <容器名或ID>
- 默认超时时间为 10 秒。如果容器在超时后仍未停止,Docker 会发送 SIGKILL 强制终止。
强制停止容器 (docker kill):立即强制终止容器,发送 SIGKILL 信号。
# 强制终止容器
docker kill <容器名或ID>
# 发送指定信号
docker kill -s <信号> <容器名或ID>
- 通常用于容器无响应或需要立即终止的场景。
重启容器 (docker restart):先停止再启动容器,相当于 docker stop 后接 docker start。
# 重启容器
docker restart <容器名或ID>
- 适用于应用配置更新后需要重启容器的场景。
暂停/恢复容器 (docker pause / docker unpause):临时冻结容器内所有进程,不释放资源;恢复后进程继续执行。
# 暂停容器
docker pause <容器名或ID>
# 恢复容器
docker unpause <容器名或ID>
- 适用于临时节省资源或调试场景。
3.3 退出容器
在容器内部,有不同的退出方式,对容器状态影响不同:
- 输入
exit或按Ctrl+D:容器内的主进程(如 bash)会终止,容器随之停止。 - 按
Ctrl+P然后Ctrl+Q:从容器终端分离(detach),但容器仍在后台运行。之后可以使用docker attach重新连接。
3.4 查看容器进程与详情
# 查看容器内部运行的进程
docker top <容器名或ID>
# 查看容器的底层详细信息(JSON格式),包括配置、网络、数据卷等
docker inspect <容器名或ID>
3.5 进入运行中的容器
有两种主要方式进入一个正在运行的容器:
# 方式一:docker exec (推荐)
# 在运行中的容器内启动一个新的进程(通常是新的 bash 会话)
docker exec -it <容器名或ID> /bin/bash
关于启动命令:/bin/bash 是常见的交互式 Shell,但并非唯一选择。<启动命令> 可以是容器内任何可执行命令,例如 /bin/sh(Alpine 镜像常用)、/bin/zsh,或直接运行特定程序如 python、node。关键在于容器镜像中必须包含该命令。docker exec 的本质是在容器内启动一个新进程,因此你可以执行任何容器内存在的命令。
exec是“执行”的意思,会新建一个进程。这是与运行中容器交互的首选方式,更安全灵活。
# 方式二:docker attach
# 附着到容器正在运行的主进程(如最初的 bash)
docker attach <容器名或ID>
attach是“附着”的意思,连接到容器启动时创建的那个主进程。如果该进程已结束或阻塞,attach可能无法工作或直接退出导致容器停止。
核心区别:exec 创建新会话,原主进程不受影响;attach 连接现有主进程,退出(如exit)会导致主进程结束,容器停止。
4. 容器与主机间文件操作
4.1 复制文件
docker cp 命令用于在容器和本地文件系统之间复制文件或目录。
# 从容器复制文件或目录到主机
docker cp <容器名或ID>:<容器内路径> <主机目标路径>
# 示例:将容器内的 /app/logs/app.log 复制到主机的 /tmp 目录
docker cp mycontainer:/app/logs/app.log /tmp/
# 从主机复制文件或目录到容器
docker cp <主机文件路径> <容器名或ID>:<容器内路径>
5. 查看容器日志
容器内应用的标准输出(STDOUT)和标准错误(STDERR)会被 Docker 捕获为日志。
# 查看容器日志
docker logs <容器名或ID>
# 实时跟踪日志输出(类似 tail -f)
docker logs -f <容器名或ID>
# 查看最后 N 行日志
docker logs --tail <行数> <容器名或ID>
# 查看特定时间戳之后的日志
docker logs --since <时间戳或时长> <容器名或ID>
# 示例:查看最近10分钟的日志
docker logs --since 10m <容器名或ID>
6. 总结
本文涵盖了从镜像拉取、删除到容器运行、交互、文件管理和日志查看的 Docker 基础命令闭环。理解 docker run、docker exec 与 docker attach 的区别,掌握 docker ps、docker logs 和 docker cp 等命令,是高效使用 Docker 进行日常开发和调试的关键。建议在安全的环境(如测试容器)中多加练习,形成肌肉记忆。
更多推荐
所有评论(0)