Docker 入门第二阶段:掌握日常命令
系列:Docker 从零到实战
阶段:第二阶段(日常命令)
预计学习时间:3~5 天
前置要求:完成第一阶段(核心概念 + 第一次
docker run)更新时间:2026 年 7 月
写在前面
第一阶段你已经跑通了第一个 Nginx 容器,也区分了镜像和容器。但从「能跑起来」到「能独立管理」,中间还差一组日常命令的熟练度。
第二阶段的目标:
不靠教程,也能完成容器的启动、配置、调试、停止和清理。
学完本文,你将能够:
- 使用镜像标签(tag)管理版本,理解为什么不推荐
latest - 通过环境变量配置容器(以 MySQL 为例)
- 熟练使用
exec、logs、inspect、stats进行调试 - 掌握容器与镜像的清理方法
- 独立排查常见运行错误
目录
- [1. 本阶段学习地图](#1. 本阶段学习地图)
- [2. 镜像深入:标签与版本管理](#2. 镜像深入:标签与版本管理)
- [3. 环境变量:配置容器行为](#3. 环境变量:配置容器行为)
- [4. 运行有状态服务:MySQL 实战](#4. 运行有状态服务:MySQL 实战)
- [5. 容器生命周期进阶](#5. 容器生命周期进阶)
- [6. 调试三板斧](#6. 调试三板斧)
- [7. 实用技巧](#7. 实用技巧)
- [8. 动手练习](#8. 动手练习)
- [9. 阶段小结与自测](#9. 阶段小结与自测)
- [10. 下一步学什么](#10. 下一步学什么)
1. 本阶段学习地图
第二阶段:日常命令
│
├── 镜像管理
│ ├── docker pull <镜像>:<标签>
│ ├── docker images
│ └── 为什么不推荐 latest
│
├── 运行与配置
│ ├── -e 环境变量
│ ├── -p 端口映射
│ ├── --restart 重启策略
│ └── --rm 退出后自动删除
│
├── 生命周期
│ ├── start / stop / restart
│ ├── rm / rmi
│ └── prune 批量清理
│
└── 调试
├── logs -f
├── exec -it
├── inspect
└── stats
学习建议: 每看完一小节,立刻在终端敲一遍。第二阶段最重要的不是背命令,而是形成「出问题 → 看日志 → 定位原因」的习惯。
2. 镜像深入:标签与版本管理
2.1 什么是 tag(标签)
镜像的完整名称格式为:
仓库地址/命名空间/镜像名:标签
例如:
nginx:latest
redis:7
mysql:8.0
node:20-alpine
其中 : 后面的部分就是 tag(标签),用来标识版本。
2.2 查看本地镜像
bash
docker images
输出示例:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest abc123def456 2 weeks ago 192MB
redis 7 def456abc789 3 weeks ago 117MB
mysql 8.0 789abc123def 1 month ago 573MB
关注这几列:
| 列名 | 含义 |
|---|---|
| REPOSITORY | 镜像名 |
| TAG | 版本标签 |
| IMAGE ID | 镜像唯一 ID(短 ID) |
| SIZE | 镜像大小 |
2.3 拉取指定版本
bash
# 拉取最新版(latest 标签)
docker pull nginx
# 拉取指定版本(推荐)
docker pull nginx:1.25
docker pull redis:7.2
docker pull node:20-alpine
2.4 为什么不推荐在生产环境用 latest
latest 是一个 浮动标签,不代表「最新稳定版」,而是镜像维护者标记的默认版本。问题在于:
| 风险 | 说明 |
|---|---|
| 版本不可预期 | 今天 pull 的 latest 和下周的可能不同 |
| 难以回滚 | 出问题时不确定之前跑的是哪个版本 |
| 团队协作混乱 | 同事和你本地的 latest 可能不一致 |
最佳实践:
bash
# ✅ 推荐:锁定具体版本
docker pull nginx:1.25.4
docker pull mysql:8.0.36
# ❌ 避免:生产环境使用浮动标签
docker pull nginx:latest
2.5 删除镜像
bash
# 按名称和标签删除
docker rmi nginx:1.25
# 按 IMAGE ID 删除
docker rmi abc123def456
# 强制删除(有容器引用时)
docker rmi -f nginx:1.25
注意:如果有容器正在使用该镜像,docker rmi 会失败。需先删除容器。
3. 环境变量:配置容器行为
很多官方镜像通过 环境变量 来配置初始化行为,比如数据库密码、端口、时区等。
3.1 设置环境变量
方式一:命令行 -e(适合临时测试)
bash
docker run -d \
-e MYSQL_ROOT_PASSWORD=123456 \
--name my-mysql \
mysql:8.0
方式二:一次设置多个
bash
docker run -d \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=app_db \
-e TZ=Asia/Shanghai \
--name my-mysql \
mysql:8.0
3.2 查看容器的环境变量
bash
# 方式一:inspect 过滤
docker inspect my-mysql --format='{{range .Config.Env}}{{println .}}{{end}}'
# 方式二:进入容器查看
docker exec my-mysql env | grep MYSQL
3.3 安全提醒
bash
# ❌ 不要把密码写进镜像(Dockerfile 阶段会详细讲)
# ❌ 不要把含密码的脚本提交到 Git
# ✅ 开发环境可以临时用 -e
# ✅ 生产环境用 secrets 或 .env 文件(Compose 阶段会学)
4. 运行有状态服务:MySQL 实战
这一节把镜像版本、环境变量、端口映射和调试命令串起来。
4.1 启动 MySQL
bash
docker run -d \
--name my-mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_DATABASE=testdb \
-p 3306:3306 \
mysql:8.0
参数说明:
| 参数 | 作用 |
|---|---|
-d |
后台运行 |
--name my-mysql |
容器命名 |
-e MYSQL_ROOT_PASSWORD |
设置 root 密码(必填) |
-e MYSQL_DATABASE |
启动时自动创建的数据库 |
-p 3306:3306 |
宿主机 3306 映射到容器 3306 |
mysql:8.0 |
锁定大版本,避免意外升级 |
4.2 确认容器状态
bash
docker ps
如果容器没有出现在 docker ps 中,而是出现在 docker ps -a 且状态为 Exited,说明启动失败了------这很正常,往下看日志。
4.3 查看启动日志
bash
docker logs my-mysql
正常启动后,日志末尾通常会出现类似:
[Server] /usr/sbin/mysqld: ready for connections.
4.4 进入 MySQL 执行命令
bash
docker exec -it my-mysql mysql -uroot -p123456 -e "SHOW DATABASES;"
预期输出包含 testdb。
4.5 用客户端连接
如果你有 Navicat、DBeaver、DataGrip 等工具,连接参数为:
| 参数 | 值 |
|---|---|
| Host | 127.0.0.1 |
| Port | 3306 |
| User | root |
| Password | 123456 |
4.6 停止与清理
bash
docker stop my-mysql
docker rm my-mysql
# 镜像仍在本地:docker images | grep mysql
5. 容器生命周期进阶
5.1 重启策略 --restart
让容器在退出或宿主机重启后自动恢复:
bash
docker run -d \
--name my-redis \
--restart unless-stopped \
-p 6379:6379 \
redis:7
常用策略:
| 策略 | 行为 |
|---|---|
no |
不自动重启(默认) |
on-failure |
仅在非零退出码时重启 |
always |
总是重启(包括手动 stop 后 Docker 守护进程重启时) |
unless-stopped |
除非手动停止,否则总是重启(推荐) |
查看当前策略:
bash
docker inspect my-redis --format='{{.HostConfig.RestartPolicy.Name}}'
5.2 退出后自动删除 --rm
适合一次性任务(跑完就扔):
bash
docker run --rm -it ubuntu:22.04 bash
# exit 后容器自动删除,不会残留
对比:
bash
# 不加 --rm:退出后容器变成 Exited 状态,需要手动 docker rm
docker run -it ubuntu:22.04 bash
5.3 强制操作
bash
# 强制停止(等同 kill)
docker kill my-nginx
# 强制删除运行中的容器
docker rm -f my-nginx
5.4 批量清理
bash
# 删除所有已停止的容器
docker container prune
# 删除未被使用的镜像
docker image prune
# 删除所有未使用的资源(容器、镜像、网络、缓存)
docker system prune
# 连同未使用的镜像一起清理(更彻底)
docker system prune -a
⚠️
prune命令会删除数据,执行前确认没有需要保留的已停止容器。
6. 调试三板斧
容器出了问题,按这个顺序排查:logs → inspect → exec。
6.1 第一斧:看日志 docker logs
bash
# 查看全部日志
docker logs my-mysql
# 实时跟踪(最常用)
docker logs -f my-mysql
# 查看最近 50 行
docker logs --tail 50 my-mysql
# 带时间戳
docker logs -t my-mysql
典型场景:
- 容器启动后立即退出 →
docker logs看报错 - 服务运行中异常 →
docker logs -f实时观察
6.2 第二斧:看详情 docker inspect
bash
# 查看完整 JSON(信息很多)
docker inspect my-mysql
# 按需提取关键信息
docker inspect my-mysql --format='{{.State.Status}}'
docker inspect my-mysql --format='{{.NetworkSettings.IPAddress}}'
docker inspect my-mysql --format='{{range .NetworkSettings.Ports}}{{.}}{{end}}'
常用提取字段:
| 命令 | 获取信息 |
|---|---|
{``{.State.Status}} |
运行状态 |
{``{.State.ExitCode}} |
退出码 |
{``{.Config.Image}} |
使用的镜像 |
{``{.NetworkSettings.Ports}} |
端口映射 |
6.3 第三斧:进容器 docker exec
bash
# 进入容器 shell
docker exec -it my-mysql bash
# 直接执行单条命令(不进入交互)
docker exec my-mysql mysql -uroot -p123456 -e "SELECT 1;"
docker exec my-redis redis-cli ping
区分 docker run 和 docker exec:
| 命令 | 作用 |
|---|---|
docker run |
基于镜像 创建并启动 新容器 |
docker exec |
在 已有容器 中执行命令 |
6.4 补充:资源监控 docker stats
bash
# 实时查看所有运行中容器的 CPU、内存、网络 IO
docker stats
# 查看指定容器
docker stats my-mysql my-redis
输出示例:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O
a1b2c3d4e5f6 my-mysql 0.50% 380MiB / 7.765GiB 4.78% 1.2kB / 0B
适合判断容器是否内存溢出、CPU 异常等。
7. 实用技巧
7.1 容器命名与 ID
每个容器有两个标识:
bash
docker ps
# CONTAINER ID NAMES
# a1b2c3d4e5f6 my-mysql
- CONTAINER ID:唯一标识,短 ID 通常 12 位
- NAMES:自定义名称,操作时两者都可以:
bash
docker stop a1b2c3d4e5f6
docker stop my-mysql # 效果一样,名字更直观
7.2 文件复制 docker cp
在宿主机和容器之间传文件,无需进入容器:
bash
# 从容器复制到宿主机
docker cp my-mysql:/etc/mysql/my.cnf ./my.cnf.bak
# 从宿主机复制到容器
docker cp ./init.sql my-mysql:/tmp/init.sql
7.3 查看容器内进程
bash
docker top my-mysql
7.4 端口占用排查
如果启动时报 port is already allocated:
bash
# Windows
netstat -ano | findstr :3306
# Linux
ss -tlnp | grep 3306
解决方案:换一个宿主机端口。
bash
docker run -d -p 3307:3306 --name my-mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
# 连接时用 3307
7.5 查看镜像构建历史
bash
docker history nginx:1.25
这能帮你理解镜像的每一层(为第三阶段 Dockerfile 做准备)。
8. 动手练习
练习 1:Redis 完整流程
目标: 启动 → 验证 → 查看日志 → 监控资源 → 清理
bash
# 1. 拉取指定版本
docker pull redis:7
# 2. 启动(带重启策略和端口)
docker run -d \
--name my-redis \
--restart unless-stopped \
-p 6379:6379 \
redis:7
# 3. 验证
docker exec my-redis redis-cli ping
# 预期:PONG
# 4. 写入和读取数据
docker exec my-redis redis-cli SET name Docker
docker exec my-redis redis-cli GET name
# 预期:Docker
# 5. 查看日志
docker logs --tail 10 my-redis
# 6. 查看资源占用
docker stats my-redis --no-stream
# 7. 清理
docker stop my-redis
docker rm my-redis
练习 2:MySQL 启动失败排查
目标: 故意制造错误,练习 logs 排错
bash
# 1. 故意不写密码(MySQL 要求必须设置 root 密码)
docker run -d --name bad-mysql mysql:8.0
# 2. 查看状态------应该是 Exited
docker ps -a | grep bad-mysql
# 3. 看日志找原因
docker logs bad-mysql
# 你会看到关于 MYSQL_ROOT_PASSWORD 的报错
# 4. 删除失败的容器
docker rm bad-mysql
# 5. 正确启动
docker run -d \
--name my-mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
mysql:8.0
# 6. 确认运行中
docker ps
收获: 容器启动失败不要慌,三步走:
docker ps -a → docker logs → 修复后重新 run
练习 3:一次性容器 vs 长期服务
目标: 理解 --rm 和 -d 的配合使用场景
bash
# 场景 A:临时任务,用完即删
docker run --rm -it ubuntu:22.04 bash
# 在容器内执行:cat /etc/os-release
# exit 后执行:docker ps -a | grep ubuntu
# 预期:找不到,因为 --rm 自动删除了
# 场景 B:长期后台服务
docker run -d --name web -p 8080:80 nginx:1.25
docker ps
# 预期:web 容器在运行
# 访问 http://localhost:8080 验证
练习 4:镜像清理
目标: 熟悉镜像和容器的清理操作
bash
# 1. 拉取两个版本的 nginx
docker pull nginx:1.25
docker pull nginx:1.24
# 2. 查看本地镜像
docker images | grep nginx
# 3. 删除旧版本
docker rmi nginx:1.24
# 4. 确认
docker images | grep nginx
# 预期:只剩 nginx:1.25
# 5. 清理所有悬空镜像(<none> 标签)
docker image prune
9. 阶段小结与自测
9.1 命令速查表
| 分类 | 命令 | 用途 |
|---|---|---|
| 镜像 | docker pull <名>:<标签> |
拉取指定版本 |
| 镜像 | docker images |
查看本地镜像 |
| 镜像 | docker rmi <名>:<标签> |
删除镜像 |
| 运行 | docker run -d -e KEY=VAL |
后台运行并设环境变量 |
| 运行 | docker run --rm -it |
一次性交互容器 |
| 运行 | --restart unless-stopped |
自动重启策略 |
| 管理 | docker start/stop/restart |
启停控制 |
| 管理 | docker rm -f |
强制删除容器 |
| 管理 | docker system prune |
批量清理 |
| 调试 | docker logs -f |
实时日志 |
| 调试 | docker exec -it |
进入容器 / 执行命令 |
| 调试 | docker inspect --format |
提取容器信息 |
| 调试 | docker stats |
资源监控 |
| 文件 | docker cp |
宿主机与容器间传文件 |
9.2 自测清单
- 能解释为什么不推荐生产环境使用
latest标签? - 能用
-e配置 MySQL 的 root 密码并成功连接? - 容器启动失败时,知道先看
docker ps -a再看docker logs? - 能区分
docker run和docker exec的使用场景? - 知道
--rm和--restart分别解决什么问题? - 能使用
docker stats查看容器资源占用? - 端口被占用时,知道换宿主机端口而不是容器端口?
- 能独立清理不再使用的容器和镜像?
9.3 常见错误速查
| 报错 | 原因 | 解决 |
|---|---|---|
port is already allocated |
宿主机端口被占用 | 换 -p 的宿主机端口 |
容器状态 Exited (1) |
启动命令失败 | docker logs <容器名> 查看原因 |
Conflict. The container name is already in use |
容器名重复 | docker rm 删除旧容器或换名 |
Error response from daemon: conflict |
同名容器已存在 | docker rm -f <名> 后重试 |
Cannot connect to MySQL |
密码错 / 端口错 / 容器未就绪 | 检查 -e、-p,等日志出现 ready |
image is being used by running container |
有容器引用该镜像 | 先 docker rm 容器再 docker rmi |
10. 下一步学什么
完成第二阶段后,进入 第三阶段:Dockerfile 与自定义镜像。
你将学习:
- 编写自己的 Dockerfile
- 把应用打包成镜像
- 理解镜像分层与构建缓存
- 使用
.dockerignore优化构建
预习:第三阶段核心概念
dockerfile
FROM node:20-alpine # 基础镜像
WORKDIR /app # 工作目录
COPY package*.json ./ # 复制依赖文件
RUN npm install # 构建时执行
COPY . . # 复制源码
EXPOSE 3000 # 声明端口
CMD ["npm", "start"] # 启动命令
bash
docker build -t my-app:1.0 .
docker run -p 3000:3000 my-app:1.0
附录:第二阶段命令速查卡
bash
# ── 镜像管理 ──
docker pull <镜像>:<标签>
docker images
docker rmi <镜像>:<标签>
docker image prune
# ── 运行容器 ──
docker run -d --name <名> -e KEY=VAL -p <宿主>:<容器> --restart unless-stopped <镜像>
docker run --rm -it <镜像> bash
# ── 生命周期 ──
docker ps / docker ps -a
docker start / stop / restart / kill <名>
docker rm <名>
docker rm -f <名>
docker system prune
# ── 调试 ──
docker logs <名>
docker logs -f --tail 50 <名>
docker exec -it <名> bash
docker exec <名> <命令>
docker inspect <名>
docker inspect <名> --format='{{.State.Status}}'
docker stats
docker top <名>
# ── 文件操作 ──
docker cp <名>:/容器路径 ./本地路径
docker cp ./本地路径 <名>:/容器路径
学习建议: 第二阶段的核心是「肌肉记忆」。把 MySQL 和 Redis 的启动、调试、清理流程各走三遍,遇到报错先
logs再看inspect,这个习惯会让你在后续 Compose 和 Dockerfile 阶段少走很多弯路。第三阶段见!
本文是「Docker 从零到实战」系列的第二篇。第一篇《基础概念与初体验》请先完成。