Docker 入门第二阶段:掌握日常命令

Docker 入门第二阶段:掌握日常命令

系列:Docker 从零到实战

阶段:第二阶段(日常命令)

预计学习时间:3~5 天

前置要求:完成第一阶段(核心概念 + 第一次 docker run

更新时间:2026 年 7 月


写在前面

第一阶段你已经跑通了第一个 Nginx 容器,也区分了镜像和容器。但从「能跑起来」到「能独立管理」,中间还差一组日常命令的熟练度。

第二阶段的目标:

不靠教程,也能完成容器的启动、配置、调试、停止和清理。

学完本文,你将能够:

  • 使用镜像标签(tag)管理版本,理解为什么不推荐 latest
  • 通过环境变量配置容器(以 MySQL 为例)
  • 熟练使用 execlogsinspectstats 进行调试
  • 掌握容器与镜像的清理方法
  • 独立排查常见运行错误

目录

  • [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 rundocker 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 rundocker 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 从零到实战」系列的第二篇。第一篇《基础概念与初体验》请先完成。

相关推荐
qetfw2 小时前
CentOS 7 基础环境配置
linux·运维·centos
随性而行3603 小时前
微信API接口与AI自动化:开发者的实现思路
运维·服务器·开发语言·人工智能·微信·自动化
有毒的教程3 小时前
Kubernetes进阶实战教程(生产落地完整版)
云原生·容器·kubernetes
鱼听禅4 小时前
Ubuntu学习笔记-安装docker容器
学习·ubuntu·docker
胖兔纸25 小时前
OpenStack 1.7.2 & Ceph 9.2.1 运维命令
运维·ceph·openstack
不会C语言的男孩5 小时前
Docker 在嵌入式设备中的常用玩法
运维·docker·容器
ylscode5 小时前
CVE-2026-31694 漏洞深度分析:Linux 内核 FUSE 组件存在本地提权风险,普通用户可直取 root 权限
linux·运维·服务器
智脑API平台6 小时前
Codex CLI 怎么用 .env 配置 API Key?本地项目和自动化脚本接入教程
运维·自动化
weixin_307779136 小时前
Linux下Docker Compose里运行的MySQL数据库故障诊断Shell脚本
linux·运维·mysql·docker·自动化