Docker 常用命令全梳理:从镜像拉取到容器编排

7 阅读10分钟

一句话本质:Docker 把应用和它依赖的运行环境一起"打包"成一个可移植的镜像,镜像跑起来就是容器。掌握 pull / run / stop / exec / build / compose 这一条命令主线,就能覆盖 90% 的日常操作。

核心要点

  1. 镜像(Image)是模板,容器(Container)是镜像运行起来的实例,一个镜像可启动多个容器。
  2. 仓库(Registry)存镜像,Docker Hub 是默认官方仓库,docker pull 时很多路径可以省略。
  3. run 是一切的起点,它的 -d / -p / -v / --name / -it / --rm / --restart 参数决定了容器怎么跑。
  4. 调试靠三板斧logs 看日志、inspect 看配置、exec 进容器。
  5. Dockerfile 定制镜像,compose 编排多容器

一、先搞懂三个核心概念

在敲命令之前,先把这三个名词分清,后面所有命令都是围绕它们转:

概念是什么类比
容器化技术给应用封装一层独立的运行环境(进程、网络、文件系统相互隔离)给每个应用发一个独立的"集装箱"
镜像 Image容器的只读模板,包含运行应用所需的一切集装箱的"设计图纸"
容器 Container镜像运行起来的实例按图纸造出来的"实体箱子"
镜像仓库 Registry存放和分发镜像的地方图纸的"图书馆"

默认的官方仓库是 Docker Hub(hub.docker.com。平时我们用的 nginxmysql 镜像都来自这里。

镜像地址的"四段式"结构

很多人被 docker pull docker.io/library/nginx:latest 这种长串吓到,其实它是一个标准结构:

[registry]/[namespace]/[repository]:[tag]
   ↓            ↓              ↓          ↓
docker.io   /  library   /     nginx   :  latest
 仓库地址      命名空间        镜像名      标签版本
  • registry:仓库地址。docker.io 是官方默认,可省略。
  • namespace:命名空间,类似 GitHub 的用户名。library 是官方镜像的命名空间,可省略。
  • repository:镜像名,例如 nginxmysql
  • tag:版本标签。latest 表示最新版;也可以指定具体版本如 1.28.0不写 tag 默认就是 latest

所以下面三条命令拉的是同一个镜像:

docker pull docker.io/library/nginx:latest   # 全写
docker pull library/nginx                     # 省略 registry
docker pull nginx                             # 连 namespace 一起省略(最常用)

二、镜像操作:拉取、查看、删除

1. 拉取镜像 docker pull

# 拉取最新版 nginx
docker pull nginx

# 指定架构拉取(交叉编译 / 跨平台调试常用)
docker pull --platform=linux/amd64 nginx
docker pull --platform=linux/arm64 nginx

--platform 用于指定目标 CPU 架构。Docker 一般会自动匹配宿主机架构,但在 Apple Silicon(arm64)机器上跑 amd64 镜像、或反过来时,显式指定能避免运行时崩溃。常用取值:linux/amd64linux/arm64linux/arm/v7linux/arm/v6

2. 查看本地镜像 docker images

sudo docker images
# 输出:
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# nginx        latest    1e5f3dc5b981   2 weeks ago    192MB

IMAGE ID 是镜像的唯一指纹,删除镜像时既可以用名字(nginx:latest)也可以用这个短 ID。

3. 删除镜像 docker rmi

rmi = rm(remove)+ i(images 缩写),即"删除镜像"。

sudo docker rmi 1e5f3dc5b981a     # 用 IMAGE ID 删除
sudo docker rmi nginx:latest      # 用 名字:tag 删除

如果镜像正在被某个容器使用,删除会失败,需要先删容器(见第三节)。


三、容器生命周期:run 的 N 种姿势

docker run 是最高频的命令,它内部其实做了两件事:create 创建容器,再 start 启动。理解了这一点,后面 create / start / stop 就好懂了。

3.1 最常用的启动参数

参数全称 / 含义说明
-ddetached后台运行(分离模式),不阻塞当前终端
-pport端口映射,格式 主机端口:容器端口
-vvolume挂载数据卷,格式 宿主机目录:容器目录
--namename给容器起名(必须唯一,不能重复)
-itinteractive + tty进入容器交互终端
--rmremove容器停止后自动删除(适合临时调试)
--restartrestart policy容器退出后的重启策略

逐个看例子:

# 后台启动 nginx(镜像不存在会自动先 pull)
docker run -d nginx

# 端口映射:把宿主机的 80 端口转发到容器的 80 端口
docker run -d -p 80:80 nginx

# 命名容器(名字唯一,重复会报错)
docker run -d --name my_nginx nginx

# 挂载卷:把宿主机 /data 目录挂进容器的 /app/data,实现数据持久化
docker run -d -v /data:/app/data nginx

# 交互式进入一个临时 alpine 容器,退出即销毁
docker run -it --rm alpine

# 容器挂掉自动重启
docker run -d --restart always nginx

3.2 重启策略对比

--restart 的取值是面试和运维都常考的点:

策略行为适用场景
no默认,不自动重启临时任务
always无论退出原因都重启,包括 Docker 守护进程重启后核心常驻服务
unless-stopped除非手动 docker stop,否则一直重启(守护进程重启也会拉起)大多数生产服务
on-failure[:max]仅当非 0 退出码(异常崩溃)时重启,可限制最大次数批处理任务

3.3 容器的"生老病死"命令

# 只创建容器,不立即运行(适合先配好网络/卷再启动)
docker create -p 27017:27017 mongo

# 启动一个已创建或已停止的容器
docker start c1e13n1ba1

# 停止运行中的容器
docker stop c1e13n1ba1

# 查看正在运行的容器
docker ps
# 查看所有容器(含已停止)
docker ps -a

四、调试三板斧:logs / inspect / exec

容器跑起来了但行为不对?这三招必会。

1. 看日志 docker logs

docker logs x29afbe41ce1        # 查看历史日志
docker logs -f x29afbe41ce1    # -f = follow,实时滚动查看(类似 tail -f)

2. 看配置 docker inspect

docker inspect c1e13n1ba1

返回容器的完整 JSON 配置(挂载、网络、环境变量、重启策略等),排查"为什么端口没映射上""卷挂载路径对不对"时非常好用。通常配合 grepjq 提取字段。

3. 进容器 docker exec

exec = 在已运行的容器里执行命令,是调试利器:

# 不进交互,直接看容器内进程
docker exec x29afbe41ce1 ps -ef

# 进交互终端,查看文件系统 / 调试(alpine 用 /bin/sh,ubuntu 用 /bin/bash)
docker exec -it x29afbe41ce1 /bin/sh

五、数据与网络:端口映射与挂载

这部分在第三节已经用参数带过,单独拎出来强调两个面试常问点:

端口映射 -p:容器有自己独立的网络命名空间,外界默认访问不到。-p 8080:80 意思是"宿主机的 8080 端口流量,转发给容器的 80 端口"。冒号前是宿主机,后是容器

数据卷 -v:容器本身是临时的,删掉容器里面的数据就没了。-v /宿主机目录:/容器目录 把宿主机目录"挂"进容器,容器内写入的数据实际落在宿主机硬盘上,实现数据持久化。数据库类容器(MySQL、MongoDB)必挂卷。


六、用 Dockerfile 把应用打包成镜像

前面都是用现成镜像,要让自己的项目也能 docker run,需要写一个 DockerfileD 必须大写)来描述"怎么造这个镜像":

# 1. 基础镜像(FROM 必须放第一行)
FROM python:3.11-slim

# 2. 设置工作目录
WORKDIR /app

# 3. 复制文件:第一个点=宿主机当前目录,第二个点=镜像内的工作目录(/app)
COPY . .

# 4. 构建时执行的命令(装依赖)
RUN pip install -r requirements.txt

# 5. 声明服务端口(仅文档作用,不自动映射)
EXPOSE 8000

# 6. 容器启动时默认执行的命令
CMD ["python", "main.py"]

关键指令对比:

指令作用注意点
FROM指定基础镜像必须第一行
WORKDIR设置后续命令的工作目录不存在会自动创建
COPY . .复制文件进镜像第一个点是构建上下文目录
RUN构建阶段执行的命令每一条会生成一个镜像层
EXPOSE声明端口只是"说明",不自动 -p 映射
CMD容器启动默认命令可被 docker run 后面的命令覆盖
ENTRYPOINT容器启动入口优先级比 CMD 高,不易被覆盖(参数会追加在其后)

CMD vs ENTRYPOINT 的区别一句话:CMD 是"默认命令,可被覆盖",ENTRYPOINT 是"固定入口,难被覆盖"。例如 ENTRYPOINT ["python"]CMD ["main.py"],运行时你写 docker run img test.py 实际执行的是 python test.py

构建命令:

docker build -t my-app:1.0 .
# -t 给镜像打 tag,最后的 . 表示构建上下文为当前目录

七、多容器协作:network 与 compose

当应用需要"前端 + 后端 + 数据库"一起跑,就需要网络互联和编排。

1. 自定义网络 docker network

# 创建子网
docker network create network1

# 启动时加入网络(同一网络内的容器可用容器名互相访问)
docker run -d --name db --network network1 mongo
docker run -d --name web --network network1 my-app
# web 容器里直接 `ping db` 就能连通,无需暴露端口给宿主机

2. 容器编排 docker compose

compose 用一份 docker-compose.yml 管理多个容器,告别手写一长串 docker run。注意:新版是 docker compose(空格),旧版是 docker-compose(横线)。

docker compose up      # 按 yml 创建并启动所有容器(-d 可后台)
docker compose down    # 停止并删除所有容器、网络
docker compose stop    # 仅停止,不删除
docker compose start   # 启动已停止的

docker-compose.yml 示例:

version: "3.8"
services:
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db
  db:
    image: mongo:latest
    volumes:
      - ./data:/data/db

compose 子命令与单容器命令对照:

目标单容器命令compose 命令
启动docker run -ddocker compose up -d
停止docker stopdocker compose stop
启动已停docker startdocker compose start
删除docker rm + docker rmidocker compose down

八、可视化图解:命令全景与容器生命周期

下面这张图把本文所有命令按"镜像 / 容器生命周期 / 调试 / 网络编排"归类,并标出容器的状态流转。

(图见下方 Visualizer 图解)

Docker命令全景图.svg

九、完整流程串联:从零跑起一个 nginx

用一个最小可运行示例走通"输入 → 中间过程 → 输出"全链路:

# ① 拉取镜像(省略了 docker.io/library/ 前缀)
docker pull nginx

# ② 后台启动,命名 + 端口映射 + 自动重启
docker run -d --name my_nginx -p 8080:80 --restart unless-stopped nginx

# ③ 确认容器在跑
docker ps
# => 看到 my_nginx 状态 Up,8080->80

# ④ 浏览器访问 http://localhost:8080 看到 nginx 欢迎页

# ⑤ 想进容器改配置?
docker exec -it my_nginx /bin/sh

# ⑥ 不想跑了?
docker stop my_nginx      # 停止
docker rm my_nginx        # 删除(--restart 策略失效)
docker rmi nginx          # 镜像也不要了就删

ASCII 流程:

docker pull nginx
       │
       ▼
docker run -d --name my_nginx -p 8080:80 nginx
       │
       ▼
  ┌─────────────┐     docker ps     ┌─────────────┐
  │   Container  │ ───────────────► │  Status: Up  │
  │  my_nginx    │                  │ 8080 -> 80   │
  └─────────────┘                  └─────────────┘
       │                                      │
       │ docker exec -it my_nginx /bin/sh     │ 浏览器访问
       ▼                                      ▼
  进入容器调试                            看到 nginx 欢迎页
       │
       ▼
  docker stop → docker rm → docker rmi  (清理)

十、记忆口诀

一拉二查三删除pull 拉镜像,images 查,rmi 删镜像。 run 起容器,参数记心上-d 后台、-p 映射、-v 挂载、--name 起名。 stop 停、start 起,create 只建不跑:生命周期三兄弟。 调试三板斧logs 看日志、inspect 看配置、exec -it 进终端。 打包用 Dockerfile,编排用 compose:FROM 打底 CMD 收,多容器靠 yml 管。