当前位置: 首页 > news >正文

【Docker】容器常用命令

目录

一.前置知识

1.1.容器和镜像的关系

1.2.容器的生命周期

1.2.1.容器OOM

1.2.2.容器异常退出与重启机制

1.2.3.容器的暂停

二.常用命令

2.1.docker create

2.2.docker logs

2.3.docker attach

2.4.docker exec

2.5.docker start和docker stop

2.6.docker restart

2.7.docker stop和docker restart的-s参数

2.8.dokcer kill

2.9.docker top

2.10.docker stats

2.11.docker container inspect

2.12.docker port

2.13.docker cp

2.14.docker diff

2.15.docker commit

2.16.docker pause和docker unpause

2.17.docker rm

2.18.docker export和docker import

2.19.docker wait

2.20.docker rename

2.21.docker container prune

2.22.docker update


一.前置知识

1.1.容器和镜像的关系

容器是容器技术的核心概念,我们可以把它通俗地理解为一个“轻量化的运行环境”。

为了更好地理解,我们可以将它与“镜像”对比来看:

  • 镜像(Image) 就像一套装修好的样板房的“设计蓝图”或者“安装包”,它是静态的、只读的。

  • 容器(Container) 则是根据这张蓝图实际启动并运行起来的“房子”——你可以在这个房子里生活、工作,摆放新家具,甚至进行临时改造。

我们必须得知道:容器本质是一个进程。

 容器与镜像的关系

容器是基于镜像创建的。

一个镜像可以同时启动多个容器,每个容器都是独立运行的,互不干扰。

就像你可以用同一张设计蓝图,在不同的地方建造多套一模一样的房子,每套房子住着不同的人,拥有各自的生活状态。

 容器的核心特点

  1. 拥有可写的文件层
    当容器启动时,它会在镜像的只读层之上,添加一个可写的文件层。所有你对容器内部文件的修改、应用的运行数据等,都会保存在这一层。当容器被删除时,这个可写层通常也会随之消失,因此它非常适合做临时性的测试和环境隔离。

  2. 资源隔离与限制
    容器虽然是宿主机(你的电脑或服务器)上的一个进程,但它通过 Linux 的命名空间(Namespace)和控制组(Cgroup)技术,实现了独立的运行环境

    • 网络隔离:容器可以拥有自己独立的 IP、端口和网络栈。

    • 文件系统隔离:容器内看不到宿主机的文件(除非手动关联)。

    • 进程隔离:在容器内部,你只能看到容器自己运行的进程,看不到宿主机上的其他进程。

    这就好比在一个大办公楼里,每个容器就像是一个独立的隔间,里面有独立的电源、网络,你在里面办公,完全感知不到其他隔间和整栋大楼的运行细节。

  3. 生命周期的五种状态
    容器从创建到销毁,会经历一个清晰的生命周期:

    • 初建(Created):容器已被创建,但尚未启动。

    • 运行(Running):容器正在执行你的应用进程。

    • 停止(Stopped):容器内的所有进程已终止。

    • 暂停(Paused):容器的进程被“冻结”,暂停执行,但状态保留在内存中。

    • 删除(Deleted):容器被终止,其占用的资源被释放。

1.2.容器的生命周期

容器的生命周期描述了容器从创建到终止可能经历的各种状态。理解这些状态及其转换关系,对于正确管理和维护容器至关重要。

容器的生命周期主要包括以下五种状态:

  • 1.Created(初建状态):
  • 容器已被创建,但尚未启动。这通常是通过执行 docker create 命令实现的,此时容器文件系统已初始化,但主进程还未运行。
  • 2.Running(运行状态):
  • 容器正在执行其主进程。可以通过 docker run(创建并立即启动)或 docker start(启动已存在的容器)进入该状态。在此状态下,容器正常执行预设任务。
  • 3.Stopped(停止状态):
  • 容器进程已终止。可通过 docker stop 命令正常停止容器,或使用 docker kill 强制终止。需要注意的是,docker kill 类似于“强制断电”,可能导致数据丢失,应谨慎使用。
  • 4.Paused(暂停状态):
  • 容器进程被“冻结”,不再分配 CPU 时间,但内存状态保持不变。可通过 docker pause 实现,适用于临时释放资源而不终止容器的场景。使用 docker unpause 可恢复运行。
  • 5.Deleted(删除状态):
  • 容器已被删除,相关资源被释放。执行 docker rm 后容器将进入此状态,不可恢复。

除了上述基本状态转换,容器还可能因外部因素进入非正常终止状态:

  • 1.因内存不足被终止(OOM)
  • 当宿主机内存耗尽时,系统会终止最消耗内存的容器以释放资源。这是一种非计划性终止,需注意监控宿主机资源使用情况。
  • 2.异常终止后的处理
  • 若容器进程异常退出,Docker 会根据重启策略决定后续操作:若设置为自动重启(yes),容器将重新进入运行状态;若设置为不重启(no),容器将转为停止状态。

1.2.1.容器OOM

容器发生 OOM(Out Of Memory)是指容器在运行过程中内存不足的情况。

Docker 在处理 OOM 事件时,主要有以下三种常见情况:

(1)容器内存使用超过限制,触发 OOM 事件

如果容器中运行的应用占用的内存超过了主机分配给该容器的内存上限,则会触发 OOM 事件。

例如,假设某个容器被分配的内存上限为 1GB,而其中运行的 Web 服务或脚本尝试申请超过 1GB 的内存,此时就会触发 OOM。

在这种情况下,该容器会被强制关闭。

需要注意的是,实际执行关闭操作的不是 Docker 守护进程(Docker Daemon),而是宿主机的操作系统内核。

因为每个容器本质上是一组在宿主机中运行的进程,宿主机内核通过 cgroups 对这些进程设置资源限制。当进程试图申请超过限制的内存时,宿主机内核会触发 OOM Killer 机制,并终止相应进程,从而导致容器退出。

(2)禁用 OOM Killer,但设置内存上限

如果希望容器在内存不足时不被强制关闭,可以在启动容器时使用 --oom-kill-disable 参数来禁用 OOM Killer。

但要注意,如果同时使用 -m 参数设定了内存上限,则当容器内存使用达到上限后,虽然不会被杀死,但系统也不再为其分配更多内存。

此时容器中的进程会处于“hung”(停滞)状态,无法继续执行需要内存的操作。

这种设置适用于你希望将故障控制在容器内部,防止因一个容器内存溢出而影响整个主机或其他容器。

(3)禁用 OOM Killer,且未设置内存上限

如果使用 --oom-kill-disable 禁用了 OOM Killer,但未通过 -m 设定内存上限,则该容器可以无限制地使用主机内存。

这意味着,只要主机有可用内存,该容器就会持续申请,极端情况下可能占满整个主机内存,导致系统整体不稳定或其他进程因内存不足而被杀死。

因此,在生产环境中应谨慎使用该配置,通常建议总是为容器设置合理的内存限制。

1.2.2.容器异常退出与重启机制

容器里面的init进程

容器里确实有一个“Init”进程,但这里的“Init”需要打上引号,因为它和我们传统操作系统里的 /sbin/init(比如 systemd 或 sysvinit)不是同一个东西。

1. 什么是容器中的 “Init 进程”?

  • 它只是第一个进程:在容器这个隔离的环境里,你通过 docker run 命令启动的那个程序(比如 /bin/bash, nginx, python app.py),就是容器内的 第1号进程。
  • 它被内核认为是“Init”:在 Linux 的进程管理体系中,每个命名空间(包括容器使用的 PID 命名空间)内的第一个进程,其 PID 会被分配为 1。内核会特殊对待这个 PID 1 的进程,赋予它一些独特的职责。
  • 所以,我们说的“Init 进程”,准确地说是指“PID 1 进程”。

2. PID 1 进程的特殊职责是什么?

  • 信号传递:当执行 docker stop 时,Docker Daemon 会向容器内的 PID 1 进程发送一个 SIGTERM 信号。一个设计良好的 PID 1 进程应该能捕获这个信号,然后优雅地关闭自己及其子进程。
  • 收养孤儿进程:如果一个父进程先于它的子进程退出,这些子进程就会变成“孤儿进程”。在宿主机上,这些孤儿进程会被 PID 1(即 systemd)接管。在容器内,这个责任就落在了容器自己的 PID 1 进程身上。如果 PID 1 进程不具备回收孤儿进程的能力,它们就会变成僵尸进程,持续占用系统资源。

容器异常退出与重启机制

容器内运行的进程是一个独立的“进程树”,这棵树的树根是一个PID为1的Init进程。容器中所有其他进程都是这个Init进程的直接或间接子进程。

容器退出的根本原因:

一个容器之所以在运行,是因为它的Init进程在运行。容器的生命周期与Init进程完全绑定。如果Init进程的任何一个子进程因为出错、冲突或资源不足等原因异常退出,并且这个异常向上传播,最终导致整个进程树崩溃,Init进程自身也会退出。一旦Init进程退出,容器就会自动停止。

Docker的视角与重启策略:

Docker引擎本身无法智能地判断一个容器的退出是“正常结束”(例如任务完成)还是“异常崩溃”。它只能观察到容器已经停止这一事实。

因此,Docker提供了一种自动重启策略来处理容器停止的情况:

当容器退出后,Docker Daemon会检查该容器是否配置了 --restart(重启)参数。

  • 只有配置了 --restart 参数的容器,Docker Daemon才会根据策略尝试自动重新启动它,让容器从 Stopped 状态恢复到 Running 状态。
  • 如果没有配置 --restart 参数,那么无论容器因何原因退出,它都会保持停止状态,需要人工干预才能重新启动。

重启策略(--restart)的常见选项:

  • no:默认策略,从不自动重启容器。
  • on-failure[:max-retries]:仅在容器非正常退出(即退出状态码非0)时重启,可以设置最大重试次数。
  • unless-stopped:总是重启容器,除非容器是被人工手动停止的。
  • always:总是重启容器。如果容器被手动停止,它会在Docker Daemon重启后或被其他方式重新启动时再次运行。

1.2.3.容器的暂停

Docker的“暂停”功能(技术上基于 cgroups freezer 实现),其效果非常像科幻片里的“时间暂停”。它并不是终止容器的运行,而是将其运行状态瞬间冻结。

1. 核心机制:剥夺CPU时间片

  • 正如您所说,Docker 会“剥夺”此容器的 CPU 资源

  • 在操作系统中,CPU 时间是通过“时间片”轮流分配给各个进程的。Docker 暂停的本质,就是让内核不再将任何 CPU 时间片分配给这个容器内的所有进程。

  • 一个生动的比喻:把CPU看作公司的打印机,各个容器是不同部门的员工。暂停某个容器,就相当于禁止这个部门的所有员工使用打印机。他们手头的工作(进程)并没有被终止,只是无法继续打印(执行计算),所有任务都卡在了当前这一步。

2. 其他资源为何保留?

  • 内存:容器占用的内存被完整地保留在RAM中。这是“暂停”与“停止”最根本的区别。停止容器会释放所有资源,而暂停则保留了完整的运行现场。

  • 网络:网络的连接状态、打开的端口、未发送完的数据包都会被保持。一个被暂停的Web服务器,其建立的TCP连接不会断开,只是不会响应任何请求。

  • 文件系统:所有打开的文件句柄、正在写入的文件状态都会被保持。

3. “冰封”状态的含义

因为失去了CPU调度,容器内的进程代码不会继续执行哪怕一条指令。它们的状态(运行中、睡眠中、可中断/不可中断)被原封不动地冻结起来,就像被冰封了一样。

二.常用命令

2.1.docker create

docker create 命令用于根据指定的镜像创建一个新的容器,但不会立即启动它。这个命令是容器生命周期的第一步,它将一个静态的镜像实例化为一个可配置、待运行的容器实体。

其实这个命令和docker run很像,但是唯一区别就是docker create只是创建但不会启动这个容器,而docker run会创建并且启动这个容器。

语法

docker create [OPTIONS] IMAGE [COMMAND] [ARG...]

IMAGE:用于创建容器的镜像名称或ID。

COMMAND [ARG...]:覆盖镜像中定义的默认启动命令和参数。

别名

docker container create

这是更符合 Docker 命令新规范的写法,功能完全相同。

下面这些核心参数其实和docker run是差不多的。我不会再详细讲解每一个参数。想要了解的,可以去:【Docker】docker run-CSDN博客

以下是用于配置容器属性的核心参数:

  • -i 或 --interactive:以交互模式运行容器。此参数会保持标准输入(stdin)处于打开状态,允许你向容器发送命令。它通常与 -t 参数配对使用。
  • -t 或 --tty:为容器分配一个伪终端。这将创建一个类似于传统终端界面的交互式会话,通常与 -i 参数结合使用,以实现完整的交互式命令行体验。
  • --name:为容器指定一个唯一的、易于识别的名称。如果省略,Docker 将自动生成一个随机名称。
  • -p 或 --publish:建立宿主机与容器之间的端口映射关系,格式为 -p <宿主端口>:<容器端口>。这将容器内部的服务端口暴露给宿主机网络,从而允许外部访问。
  • -P 或 --publish-all:将容器内部暴露的所有端口(在 Dockerfile 中使用 EXPOSE 指令定义的端口)随机映射到宿主机的高位端口上。
  • -e 或 --env:在容器内部设置环境变量。这对于向应用程序传递配置信息(如密码、路径或运行模式)至关重要。
  • -v 或 --volume:创建数据卷,用于在宿主机和容器之间持久化或共享数据。格式通常为 -v <宿主机路径>:<容器路径>。
  • -h 或 --hostname:设置容器内部的主机名,这会覆盖容器内 /etc/hostname 的内容。
  • -m 或 --memory:设定容器所能使用的最大内存上限。这是防止单个容器耗尽主机内存资源的关键限制。
  • --cpuset-cpus:将容器的运行限制在指定的 CPU 核心上。例如,--cpuset-cpus="0,3" 表示容器只能在 CPU 0 和 3 上执行。
  • --network:指定容器的网络模式。最常用的模式包括 bridge(默认的桥接网络)、host(直接使用主机网络栈)和 none(禁用网络)。
  • --rm:此参数是一个自动化清理选项。它指定当容器退出时,Docker 守护进程将自动删除该容器。这主要用于临时性的测试容器,以避免产生大量停止状态的容器,占用磁盘空间。
  • --restart,见下面

--restart 重启策略详解

--restart 参数是 Docker 容器的高可用性核心配置,它定义了当容器退出后,Docker 守护进程是否以及如何尝试自动重新启动它。

工作原理:Docker 守护进程会监控容器的退出状态。一旦检测到容器退出,它会根据 --restart 策略来决定后续动作。只有设置了此参数的容器,Docker 才会尝试自动重启。

策略选项:

  • no:默认策略。容器退出后,无论退出原因是什么,Docker 都不会尝试自动重启它。容器将保持 Exited 状态。
  • on-failure[:max-retries]:按条件重启策略。只有在容器非正常退出时才会重启。所谓“非正常退出”,是指容器的退出状态码(exit code)不为 0(在 Linux 中,0 通常表示成功)。你可以可选地指定一个最大重试次数(例如 on-failure:5),当重启次数超过该值后,Docker 将放弃重启。
  • always:无条件总是重启。只要容器退出(无论是因为程序崩溃、OOM Kill 还是手动 docker stop),Docker 都会无限次地尝试重启它。即使容器是被手动停止的,当 Docker 守护进程本身重启或者容器被其他方式重新启动时,它也会再次运行。
  • unless-stopped:除非手动停止,否则总是重启。这是 always 策略的一个更智能的变体。它与 always 的关键区别在于:如果用户手动执行了 docker stop 来停止容器,那么即使 Docker 守护进程重启,这个容器也不会被自动拉起。只有那些非手动停止的退出,才会触发自动重启。

我们先进行实操

docker create --name mywebsite1 -p 8080:80 nginx:1.23.4-perl

可以看到这个容器的状态是Created

我们可以看看它有没有在监听对应端口,有没有在运行

很显然,这个容器没有启动啊!!

接下来我们就来启动这个容器

docker start mywebsite1

现在我们再去看看

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS          PORTS                                     NAMES
8e41d5482205   nginx:1.23.4-perl   "/docker-entrypoint.…"   5 minutes ago   Up 20 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite1
root@VM-16-14-ubuntu:~# netstat -nltp | grep 8080
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      2587741/docker-prox 
tcp6       0      0 :::8080                 :::*                    LISTEN      2587749/docker-prox 

怎么样?是不是启动了!!

现在我们就用浏览器去访问一下我们的这个服务

http://你的服务器IP地址:8080

怎么样?是不是很完美

2.2.docker logs

什么是容器日志?

你可以把 Docker 容器想象成一个正在运行的、有独立环境的小程序。这个程序在运行时,会向标准输出(stdout)和标准错误(stderr)打印信息,比如程序的运行状态、访问记录、错误信息等。

Docker 引擎会捕获这些输出,并把它们收集起来,这就形成了容器日志。docker logs 命令就是用来查看这些被收集起来的日志的。

基本用法

最基本的命令格式就是:

docker logs [容器名或容器ID]
  • CONTAINER:这里需要替换成你的容器的名字或者容器ID。

你可以通过 docker ps 命令来查看当前正在运行的容器的这些信息。

举个例子:

假设我运行了一个名为 my_web_server 的容器。

我想看看它启动时有没有报错,或者它处理了哪些请求。

我只需要在终端里输入:

docker logs my_web_server

或者,如果我只知道容器ID的前几位(比如 a1b2c3d):

docker logs a1b2c3d

执行后,终端就会打印出这个容器从启动到现在所有的日志内容。

关键参数详解(让你的日志查看更高效)

单单使用基本命令可能会一下子输出太多内容,让人眼花缭乱。下面这些参数能帮你精准地找到你需要的信息。

  • 1. -f 或 --follow (实时跟踪)

这个参数类似于 Linux 下的 tail -f 命令。它会实时地显示日志的最新输出,并且会持续等待新的日志出现。

使用场景:当你正在调试一个服务,想实时监控它的动态时,这个功能非常有用。

例子:

docker logs -f my_web_server

输入这个命令后,终端会“挂起”,并持续显示 my_web_server 容器新产生的每一行日志。按 Ctrl + C 可以退出跟踪模式。

  • 2. -t 或 --timestamps (显示时间戳)

这个参数会在每一行日志的前面加上它被记录下的具体日期和时间。

使用场景:当你需要排查在某个特定时间点发生了什么问题时,这个功能至关重要。

例子:

docker logs -t my_web_server

输出可能类似:

2024-05-27T10:23:45.123Z Server started on port 80
2024-05-27T10:24:01.456Z User connected from 192.168.1.5
2024-05-27T10:24:02.789Z Error: Database connection failed
  • 3. -n 或 --tail (只看最后几行)

这个参数让你只查看日志的最后 N 行,而不是全部历史。

使用场景:容器可能已经运行了几个月,日志量巨大。你只关心最近发生的事情(比如服务刚刚为什么重启了)。

例子:

# 只查看最新的 10 条日志
docker logs --tail 10 my_web_server# 同样只查看最新的 10 条日志(简写)
docker logs -n 10 my_web_server
  • 4. --since (按时间过滤)

这个参数非常强大,它可以只显示从某个时间点之后的日志。

使用场景:你记得问题是今天早上9点后才出现的,那么就没必要看9点之前的日志了。

例子:

# 显示从 2024年5月27日 09:00 之后的所有日志
docker logs --since "2024-05-27T09:00:00" my_web_server# 显示最近10分钟内的日志
docker logs --since "10m" my_web_server# 显示最近1小时内的日志
docker logs --since "1h" my_web_server

时间格式可以是绝对时间(YYYY-MM-DDThh:mm:ss),也可以是相对时间(10m, 1h, 2d30m等)。

  • 组合使用

这些参数可以组合在一起使用,以满足更复杂的需求。

场景1:实时跟踪最近100条日志,并带上时间戳

如果你想先看看最近发生了什么,然后开始实时监控:

docker logs -f -t --tail 100 my_web_server

场景2:查看过去1小时内产生的最后50条日志

你想快速了解过去一小时内的关键事件:

docker logs --since "1h" --tail 50 my_web_server

场景3:实时跟踪从某个特定时间点开始的日志

你想从今天早上8点开始,实时“回放”并跟踪日志:

docker logs -f --since "2024-05-27T08:00:00" my_web_server

话不多说,我们直接看例子

首先我们先启动一个容器

我们看看

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS         PORTS                                     NAMES
f7ceec72d15f   nginx:1.23.4-perl   "/docker-entrypoint.…"   10 seconds ago   Up 9 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

确实是在运行之中

我们现在使用浏览器去连接一下我们这个服务

http://你的服务器IP地址:8080

现在我们执行下面这个命令

docker logs mywebsite

接下来我们执行下面这个命令

docker logs -f mywebsite

……

我们去刷新一下我们的浏览器

发现多了一条日志!!!我们再去刷新,又多了下面这条

这就是实时打印日志。

docker logs --since="2025-08-01" mywebsite

这个没什么好说的,接下来看看-n参数

完全没有问题啊

2.3.docker attach

docker attach 命令允许你连接到正在运行的容器的主进程,就像你直接坐在那台服务器的终端前一样。

想象一下:容器就像一台正在运行的虚拟机,而 docker attach 就是让你"远程登录"到这台虚拟机的命令。

最基本的命令格式:

docker attach [容器名或容器ID]

举个例子:

假设我有一个正在运行的名为 my_app 的容器。

我想连接到它的主进程进行交互:

docker attach my_app

执行后,你的终端就会"进入"到容器内部,可以看到容器主进程的输出,也可以向它输入命令(如果主进程是交互式的话)。

接下来我想讲一个参数

  • --sig-proxy (信号代理)

这是 docker attach 最重要的参数,理解了它就能明白为什么这个命令需要谨慎使用。

  • 默认值:true
  • 作用:控制是否将你在终端中按下的键盘信号(如 Ctrl+C)传递给容器的主进程。

当 --sig-proxy=true(默认)

docker attach my_app
# 或者等价于
docker attach --sig-proxy=true my_app

行为:

  • 如果你在终端中按下 Ctrl+C,这个中断信号会发送给容器的主进程
  • 如果主进程接收到 Ctrl+C 后退出,那么整个容器也会随之停止
  • 同样,按下 Ctrl+Z 会暂停容器的主进程
  • 风险:不小心按了 Ctrl+C 就可能导致你的容器停止运行!

当 --sig-proxy=false(推荐的安全用法)

docker attach --sig-proxy=false my_app

行为:

  • 如果你按下 Ctrl+C,这个信号不会发送给容器的主进程
  • 而是只影响你当前的连接,让你安全地退出连接
  • 容器会在后台继续正常运行

简单示例

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊

我们现在执行下面这个命令

docker attach mywebsite

我们去浏览器刷新一下

现在我们直接ctrl+c

我们特别注意这一句:2025/10/27 11:45:16 [notice] 1#1: signal 2 (SIGINT) received, exiting

这说明容器受到了ctrl+c信号的影响

我们去看看

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS                      PORTS     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   4 minutes ago   Exited (0) 27 seconds ago             mywebsite

这个mywebsite被终止了。

我们浏览器的界面也变成了

我们把它重新启动一下

docker start mywebsite

我们看看运行结果

root@VM-16-14-ubuntu:~# docker start mywebsite
mywebsite
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   8 minutes ago   Up 3 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

一切又都恢复正常了。

docker attach --sig-proxy=false mywebsite

我们在浏览器刷新一下

我们发现日志还是正常打印的,我们现在ctrl+c

我们发现是退出了,那我们那个镜像呢?我们去看看

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS         PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   11 minutes ago   Up 3 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

我们发现还在运行,这个镜像没有退出。

2.4.docker exec

docker exec 命令的核心功能是:在一个已经处于运行状态的容器内部,启动一个新的进程来执行指定的命令。

理解这一点至关重要:

  • 它针对的是 已经运行中的容器,而不是镜像或已停止的容器。
  • 它是在容器内 启动一个新进程。这个进程可以与容器的主进程并行运行。
  • 它的主要目的包括:调试、检查容器状态、修改文件、执行临时任务等。

语法结构解析

docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

我们可以将这条语法分解为四个部分来理解:

docker exec:这是命令本身,告诉 Docker 你要执行“在容器内运行命令”这个操作。

[OPTIONS]:这是可选的参数列表,用于修饰和定制 exec 命令的行为。它决定了新进程如何与你的终端交互、在什么环境下运行等。这是命令最灵活和关键的部分。

CONTAINER:这是目标容器的标识。你必须指定要在哪个容器里运行命令。这个标识可以是:

  • 容器ID:Docker 分配给每个容器的唯一哈希值,通常取前几位就能唯一识别。
  • 容器名称:在创建容器时通过 --name 参数指定的名字。

COMMAND [ARG...]

  • COMMAND:这是你希望在那个容器内部执行的 可执行程序 的路径。例如 /bin/bash, ls, cat, python 等。这个程序必须存在于容器的文件系统中。
  • [ARG...]:这是传递给上述命令的 参数。这是一个可变列表,可以有零个、一个或多个参数。

关键参数详解

这些参数控制着新进程的运行方式。

-i (--interactive)

  • 功能:保持标准输入流打开。
  • 原理:即使你没有通过命令终端附加到容器,-i 选项也会保持这个新进程的 STDIN 处于打开和可用的状态。
  • 使用场景:当你需要与这个新进程进行 交互,比如需要向它输入命令或传递数据时,就必须使用这个参数。

-t (--tty)

  • 功能:分配一个伪终端。
  • 原理:TTY 是 Teletypewriter 的缩写,在这里可以理解为为一个命令分配一个模拟的文本终端。它会格式化输出,并处理一些终端特有的信号和转义序列,让你感觉像是在一个真正的终端里操作。
  • 使用场景:当你希望命令的输出格式良好,并且需要支持像 top, vim 这样的交互式程序时,就需要使用这个参数。

-i 和 -t 的关系:

  • 它们通常被组合使用为 -it。
  • -i 保证了你能输入,-t 保证了输入输出的格式正确且像一个真正的终端。
  • 组合后的 -it 为你提供了一个与容器内新进程进行 “交互式会话” 的标准方式。

-d (--detach)

  • 功能:在后台运行命令(分离模式)。
  • 原理:与 -it 相反,它让这个新进程在容器内 后台运行。Docker 会立即在宿主机上打印出新进程的 ID,然后返回到你的宿主机命令行提示符,而不会等待命令结束或显示其输出。
  • 使用场景:当你需要启动一个长时间运行的后台任务,但又不想让它阻塞当前终端时使用。

-u (--user)

  • 功能:指定运行命令的用户和用户组。
  • 原理:默认情况下,docker exec 会以容器镜像中定义的默认用户(通常是 root)来运行命令。通过 -u,你可以指定一个不同的用户名或UID,以及可选的组名或GID来运行这个新进程。
  • 语法:<name|uid>[:<group|gid>]
  • 使用场景:出于安全考虑,你可能不希望以 root 权限执行操作;或者需要以某个特定用户的身份访问特定文件。

-w (--workdir)

  • 功能:指定命令在容器内的工作目录。
  • 原理:它会在执行你指定的 COMMAND 之前,先切换到 -w 后面给出的目录路径。这相当于在容器内先执行了 cd /some/dir。
  • 使用场景:当你需要在容器的特定目录下执行操作时(如编译代码、操作特定文件),可以避免在命令中输入冗长的绝对路径。

-e (--env)

  • 功能:设置环境变量。
  • 原理:环境变量是操作系统或程序运行时可以读取的键值对。这个参数允许你为这次执行的 新进程 设置一个或多个临时的环境变量。如果变量名与容器内已存在的冲突,则会覆盖它。
  • 使用场景:临时改变程序的行为,比如设置 JAVA_OPTS, NODE_ENV 等,而无需修改容器本身。

简单示例

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

现在我们执行下面这个命令

docker exec -it mywebsite bash

注意:bash是我们想要在容器内部启动的那个新进程的具体命令。

当你按下回车执行这条命令后,会发生以下情况:

  • Docker 客户端会找到正在运行的、名为 mywebsite 的容器。
  • 在该容器内部,Docker 会启动一个新的 bash 进程。
  • 由于你使用了 -it 参数,你的当前终端会附加到这个 bash 进程上。
  • 命令提示符会发生变化,通常会变成容器内部的提示符(例如 root@容器ID:/#)。
  • 此时,你已经进入了容器内部。你在这个提示符下输入的每一条命令(如 ls, pwd),都将在 mywebsite 容器的环境、文件系统和进程空间中执行。
  • 这相当于你“登录”到了这个容器里。

我们执行一些命令

我们可以在里面执行任何命令

好好,我们换着执行另外一个命令

docker exec -it mywebsite nginx -v

这次我们想要在容器内部执行的命令是nginx -v

换一个命令

docker exec -it mywebsite nginx -V

这次我们想要在容器内部执行的命令是nginx -V

我们还能指定环境变量

还能执行各种命令

还能指定初始工作目录

2.5.docker start和docker stop

先看看语法

语法

docker start 目标容器的标识

你必须指定要在哪个容器里运行命令。

这个标识可以是:

  • 容器ID:Docker 分配给每个容器的唯一哈希值,通常取前几位就能唯一识别。
  • 容器名称:在创建容器时通过 --name 参数指定的名字。

语法

docker stop 目标容器的标识

你必须指定要在哪个容器里运行命令。

这个标识可以是:

  • 容器ID:Docker 分配给每个容器的唯一哈希值,通常取前几位就能唯一识别。
  • 容器名称:在创建容器时通过 --name 参数指定的名字。

1. docker stop:让容器“睡眠”

当你用完电脑,不想完全关机,希望所有打开的程序和文件都保持原样,等你回来能立刻接着干活,你会选择 “睡眠”。

docker stop 命令就是这个“睡眠”键。

它做了什么?

  • 它会友好地通知容器里的主程序:“请保存好手头的工作,准备休息了。”
  • 给程序一点时间来完成收尾工作(比如保存文件、关闭连接)。
  • 然后安全地、优雅地停止容器。

结果是什么?

  • 容器不运行了,你无法再通过它提供服务(比如网站访问不了)。
  • 但是,容器本身还存在。你所有对它的修改(比如新创建的文件、安装的软件)都被保留着。
  • 它只是处于“休眠”状态,随时可以被再次“唤醒”。

简单记:docker stop = 让一个正在运行的容器去“睡觉”。

2. docker start:唤醒“睡眠”的容器

当你想再次使用那台处于“睡眠”状态的电脑时,你按下开机键,它就会迅速恢复到睡眠前的状态,所有窗口和程序都在原地。

docker start 命令就是这个“开机”键。

它做了什么?

  • 它会把一个之前已经被 stop 了的、处于停止状态的容器,重新运行起来。

结果是什么?

  • 容器里的程序会按照你之前设置的方式重新启动。
  • 你之前在这个容器里做的所有更改都还在,环境和你上次离开时一模一样。
  • 它不会创建一个新的容器,而是启动那个旧的。

简单记:docker start = 把一个已经存在的(但已停止的)容器“叫醒”。


简单示例

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

现在我们stop一下

我们在浏览器看到的

现在我们进行启动一下

docker start mywebsite

我们看看运行结果

root@VM-16-14-ubuntu:~# docker start mywebsite
mywebsite
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS         PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   40 minutes ago   Up 4 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

我们看看浏览器上面的服务,已经恢复正常了

还行吧!!

2.6.docker restart

先看语法

语法

docker restart 目标容器的标识

你必须指定要在哪个容器里运行命令。

这个标识可以是:

  • 容器ID:Docker 分配给每个容器的唯一哈希值,通常取前几位就能唯一识别。
  • 容器名称:在创建容器时通过 --name 参数指定的名字。

docker restart:重启容器

想象一下,你的电脑(容器)正在运行,但是出现了一些小问题,或者你安装了一个新软件需要重启生效,这时候你会选择重启电脑。

docker restart 命令就是这个“重启”键。

它做了什么?

  • 它实际上相当于先执行了 docker stop(但是以一种相对快速的方式,默认等待时间较短),然后再执行 docker start。
  • 它会先停止容器,然后再立即启动它。

结果是什么?

  • 容器会经历一个停止再启动的过程。
  • 容器内的应用程序会重新启动。
  • 容器本身还是同一个,所有数据和状态都会保留(因为文件系统还在),但是应用程序会重新初始化。注意:如果应用程序本身在启动时会进行一些初始化操作,那么这些操作会重新执行。但是对容器文件系统的修改(比如你之前在里面创建的文件)不会丢失。

简单记:docker restart = 让容器“重启一下”,相当于先“睡眠”再“唤醒”,但目的是为了重新启动容器内的服务。

和stop/start组合的区别

  • 使用 docker stop 然后 docker start 是分两步,你可以控制在停止后等待任意长时间再启动。
  • docker restart 是一个连续的动作,默认情况下,它给容器一个较短的优雅停止时间(默认10秒),然后强制停止(如果还没停掉的话)并重新启动。

什么时候使用?

  • 当你想重新启动容器内的服务而不需要重新创建容器时,使用docker restart。例如,修改了容器的某些配置,需要重启容器来使配置生效。

简单示例

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

接下来我们执行一个命令

docker logs -f -n 5 mywebsite

现在我们换一个终端进行重启

docker restart mywebsite

这个时候原来那个终端就会变成下面这样子

我们现在再去查看一下容器的状态

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   55 minutes ago   Up 10 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

我们看到这个STATUS是10秒前,就说明我们重启成功了.

2.7.docker stop和docker restart的-s参数

在深入 -s 参数之前,你必须先明白 Docker 停止一个容器的标准流程。

这就像你要关闭一台电脑:

  • 正常关机(优雅停止):你点击“开始”菜单 -> “关机”。操作系统会通知所有运行中的程序:“要关机了,请保存数据然后退出。” 给程序一个清理现场的机会。这个过程需要一点时间,但是安全的。
  • 强制关机(强制杀死):你直接长按电源键。电脑“啪”一下就断电了。所有程序不管在干什么,都会立刻终止,没有机会保存任何数据。

Docker 停止容器也遵循类似的逻辑,它通过发送 信号 来与容器内的主进程通信。

  • SIGTERM 信号:就像“正常关机”指令。它是礼貌的请求,告诉主进程:“你该退出了,请处理好后续工作。”
  • SIGKILL 信号:就像“强制关机”指令。它是不容商量的,直接干掉进程。进程收到这个信号会瞬间死亡,没有任何反应机会。

默认行为:

当你使用 docker stop 时,Docker 的默认行为是:

  • 先发送一个 SIGTERM 信号。
  • 然后等待 10秒(默认时间)。
  • 如果10秒后容器的主进程还没有退出,Docker 就会失去耐心,发送 SIGKILL 信号来强制杀死它。

第一部分:docker stop -s

这个 -s 参数的全称是 --signal,意思是“信号”。

它的作用就是:让你改变默认发送的 SIGTERM 信号,换成其他你指定的信号。

语法:

docker stop -s <信号名或数值> <容器名或ID>

为什么需要它?

因为不是所有程序都对 SIGTERM 信号有良好的响应。有些程序可能需要一个特定的信号来优雅关闭。

举个例子:

假设你有一个容器,里面运行着一个非常古老的程序,它只认 SIGINT 这个信号(通常由键盘输入 Ctrl+C 触发)来优雅关闭。

默认方法(可能无效):

docker stop my_container
# Docker 发送 SIGTERM,老程序不理不睬,10秒后被强制杀死。

使用 -s 参数(优雅关闭):

docker stop -s SIGINT my_container
# Docker 发送 SIGINT,老程序认得这个信号,开始保存数据、优雅退出。

另一个例子:直接强制杀死

如果你想跳过“优雅请求”的步骤,直接强制杀死容器,你可以:

docker stop -s SIGKILL my_container
# 或者用信号的数值(9)
docker stop -s 9 my_container

这等价于 docker kill my_container 命令。

第二部分:docker restart -s

docker restart 命令其实是 docker stop 和 docker start 两个动作的合体。

它的 -s 参数,只影响前半段(即停止阶段)的行为,和 docker stop -s 的作用是完全一样的。后半段的“启动”动作不受影响。

语法:

docker restart -s <信号名或数值> <容器名或ID>

举个例子:

你有一个 Web 服务器容器,每次重启时,用 SIGTERM 通知它,它关得很慢,导致重启过程很长。你发现它对 SIGHUP 信号反应更快,能立刻开始优雅关闭。

# 使用默认信号,停止阶段可能很慢
docker restart my_web_server# 使用定制的信号,停止阶段更快,整个重启过程也更快了
docker restart -s SIGHUP my_web_server

重要区别:

  • docker stop -s:停止后,容器状态变为 Exited。
  • docker restart -s:停止后,会立刻再把它启动起来,容器状态最终变为 Up。

话不多说,我们直接看例子

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

接下来我们执行一个命令

docker logs -f -n 5 mywebsite

接下来我们打开另外一个终端,执行下面这个命令

执行完之后,我们立马回到原来的那个终端,发现出现了下面这个

我们发现这个docker stop 默认是向容器主进程发送了SIGQUIT信号。

嗯?不是说好了Docker 的机制:当 docker stop 被调用时,Docker 会向主进程发送一个信号。这个信号默认是 SIGTERM吗?为什么这里却是SIGQUIT信号?

事实上具体信号可能因应用而异:默认的“礼貌请求”信号虽然是 SIGTERM,但最终被应用程序接收并处理的信号,取决于应用程序自身的信号处理设计。Nginx 就是一个典型的例子,它使用 SIGQUIT 来进行优雅关闭。

接下来我们重启容器,然后我们接着执行下面这个命令

接下来我们换一个终端执行下面这个命令

我们回去看看

我们看看容器的状态

root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED        STATUS                     PORTS     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   28 hours ago   Exited (0) 9 minutes ago             mywebsite

怎么样?

2.8.dokcer kill

1. 功能:强制退出容器

“强制”是什么意思?

  • 想象一下,你正在电脑上用一个软件(比如Word)写文档,但没保存。这时如果你直接用“任务管理器”把它强制结束,你未保存的工作就丢失了。
  • docker kill 就是这样的“强制结束”操作。它不会给容器里的应用程序任何准备时间,直接发送一个系统级别的 SIGKILL 信号(默认情况下),命令内核立刻终止这个容器的进程。

和 “正常关机” 的区别

  • Docker 里还有一个命令叫 docker stop。它更像是我们平时用的“开始菜单 -> 关机”。
  • docker stop:会先友好地通知容器里的主进程:“你该退出了”,并给它一点时间(默认10秒)来做一些清理工作(比如保存数据、关闭网络连接等),如果时间到了它还没退出,才会强制杀掉它。它发送的是 SIGTERM 信号。
  • docker kill:不讲武德,直接拔电源。立刻、马上终止。

简单比喻:

  • docker stop -> 礼貌地请客人离开(给时间收拾)
  • docker kill -> 直接把客人推出去(不给任何机会)

2. 语法

docker kill [OPTIONS] CONTAINER [CONTAINER...]

我们来拆解一下这个语法:

  • docker kill:这是命令本身。
  • [OPTIONS]:这是可选的参数,用中括号 [] 表示,意思是可以不写。最常用的选项是 -s 用来指定发送什么样的信号(这个后面说)。
  • CONTAINER:这是必须的。你要告诉 docker kill 到底要杀哪个容器。你不能只说“我要关机”,得说“我要关A电脑”。
  • [CONTAINER...]:后面的三个点 ... 表示你可以同时杀死多个容器。比如 docker kill 容器A 容器B 容器C。

如何指定 CONTAINER(容器)?

你需要提供容器的 “身份证” 。可以是:

  • 容器ID:一串很长的唯一字符串,比如 f56d6c8a3b12。你通常不需要输全,只要输入能唯一区分它的前几位就行,比如 docker kill f56d。
  • 容器名字:在创建容器时用 --name 指定的名字,比如 docker kill my_nginx。

3. 别名

你看到了 docker container kill,它的功能和 docker kill 完全一样。

这是新版本Docker推荐的一种语法,把命令按功能模块化管理了。

  • docker kill 是旧式的、简短的写法。
  • docker container kill 是新式的、更规范的写法。

你可以把它们理解为同一个命令的“小名”和“大名”,用哪个都行。很多有经验的用户会觉得新的写法更清晰。


话不多说,我们直接看例子

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

接下来我们执行一个命令

docker logs -f -n 5 mywebsite

接下来我们换一个终端,执行下面这个命令

回到原来那个终端,发现直接就退出了

2.9.docker top

docker top 命令可以让你从宿主机(你运行Docker的电脑)上,直接查看某个容器内部正在运行的进程,就像在容器内部执行 ps 或 top 命令一样。

为什么需要 docker top?(深入理解“注意事项”)

为了更好地理解,我们先对比一下传统虚拟机和Docker容器的不同。

1. 在传统虚拟机里,我们怎么查看进程?

假设你有一台Ubuntu虚拟机,里面运行着你的网站程序(比如Nginx)和数据库(比如MySQL)。你想看看这个虚拟机里正在运行哪些进程,会怎么做?

你肯定会:

  1. 通过SSH登录到这台虚拟机里。

  2. 然后执行 ps aux 或者 top 命令。

这个过程非常自然,因为这台虚拟机对你来说,就像一台完整的、独立的电脑。

2. 在Docker容器的世界里,情况变了

现在,我们不用虚拟机了,改用Docker容器。我们可能运行了两个容器:

  • my_nginx_container:里面只运行Nginx。

  • my_mysql_container:里面只运行MySQL。

这时,你想看看 my_nginx_container 这个容器里在跑什么进程。你的第一反应可能也是“进入”这个容器,然后执行 ps 或 top 命令。

问题就出在这里!

  • docker top 诞生的原因

原因一:容器里可能根本没有 top 或 ps 命令!

Docker镜像追求的是最小化安全性。一个只用来运行Nginx的官方镜像,它的目标就是完美地运行Nginx,除此之外的东西越少越好。像 toppsbash 这些我们认为是“理所当然”应该存在的工具,在最小化的镜像里是被故意剔除的

  • 好处:镜像体积更小,下载更快,部署更快,潜在的安全漏洞更少(因为攻击面小了)。

  • 坏处:当你执行 docker exec -it my_nginx_container bash 想进入容器时,可能会失败,因为里面根本没有 bash!即使你进去了,想运行 ps 或 top 也会收到 command not found 的错误。

原因二:即使有,进去看也很麻烦

就算你的容器镜像里碰巧有 ps 命令,你需要:

  1. 先 docker exec 进入容器。

  2. 再执行 ps aux

  3. 看完后再 exit 退出。

这个过程对于只是想快速看一眼进程状态这个简单需求来说,太繁琐了。

  • docker top 的完美解决方案

docker top 就是为了解决上述问题而生的。它不需要进入容器,也不依赖容器内部的任何工具

它的工作原理是:

在Linux中,每个进程都有一个唯一的PID(进程ID)。容器内的进程实际上就是宿主机上的进程,只不过通过Linux的命名空间(Namespace)技术,这些进程被隔离在了一个单独的视图里。

在容器内部,进程的PID是重新从1开始的,但在宿主机上,它们拥有真实的PID。

关键点:

  • 容器里的所有进程,在宿主机上都是可见的、有真实PID的进程

  • Docker 使用 Linux 的 Namespace 技术来制造"隔离幻觉",让容器内的进程以为自己是在独立环境里

  • 容器内的 PID 1 进程,在宿主机上可能对应的是 PID 1234

docker top 命令的工作原理就是直接查询宿主机上关于这个容器的进程信息。它不需要进入容器,也不需要容器内有任何工具,因为它直接调用宿主机的 ps 命令来显示与容器相关的进程。

举个例子:

你想查看 my_nginx_container 容器里的进程。

# 不需要进入容器,直接在宿主机上执行:
docker top my_nginx_container

输出结果可能会是:

UID    PID    PPID   C  STIME  TTY  TIME       CMD
root   12345  12340  0  10:30  ?    00:00:00   nginx: master process nginx -g daemon off;
101    12350  12345  0  10:30  ?    00:00:00   nginx: worker process

你立刻就能看到,这个容器里运行着一个Nginx的主进程和一个工作进程。简单、直接、高效!

注意,这些PID是宿主机上的PID。

语法详解

docker top CONTAINER [ps OPTIONS]
  • docker top:命令本身。
  • CONTAINER:容器的名称或ID。这是必须提供的。你可以通过 docker ps 命令来查看当前运行的容器。
  • [ps OPTIONS]:可选的参数。这些参数会直接传递给 Linux 系统经典的 ps 命令,用来定制你想看到的信息。

别名:

docker container top 和 docker top 是完全一样的。docker container top 是更符合新版本 Docker 命令规范的一种写法(比如还有 docker container ls, docker image ls)。


话不多说,我们直接看例子

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

接下来我们执行一个命令

root@VM-16-14-ubuntu:~# docker top mywebsite
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                3234556             3234533             0                   11:13               ?                   00:00:00            nginx: master process nginx -g daemon off;
message+            3234621             3234556             0                   11:13               ?                   00:00:00            nginx: worker process
message+            3234622             3234556             0                   11:13               ?                   00:00:00            nginx: worker process

我们发现里面就1个主进程,两个工作进程。

注意:这里的 PID 和 PPID 都是宿主机的进程ID。

2.10.docker stats

docker stats 就像是 Docker 容器的 “任务管理器” 或 “资源监视器”。它可以让你实时地看到你运行的每个容器“吃了”多少 CPU、“占”了多少内存、“收发了”多少网络数据等等。

1. 为什么要用它?(应用场景)

想象一下,你的电脑上同时运行了好几个容器,比如一个运行网站(Nginx),一个运行数据库(MySQL),一个运行你的后端程序(Python/Java)。

突然,你的电脑变得非常卡顿。你会想知道:

  1. 是哪个容器把 CPU 占满了?
  2. 是哪个容器吃了太多内存?
  3. 网络流量是不是异常的高?

docker stats 就是用来回答这些问题的工具。它帮你快速定位哪个容器是“资源消耗大户”,方便你进行故障排查和性能优化。

2. 基本使用:怎么看?

最简单的用法就是直接在终端里输入:

docker stats

这时,它会实时地、持续地显示所有正在运行的容器的资源使用情况。你会看到一个表格在不断地刷新,就像看股票行情一样。

返回的每一列是什么意思?

CONTAINER ID 与 NAME: 这一列最简单,就是告诉你现在显示的是哪个容器。就像看任务管理器,你得知道哪个程序对应哪个名字。

CPU %: 这是容器使用的 CPU 百分比。如果你的电脑是 4 核 CPU,那么这个值的理论最大值是 400%。如果某个容器一直显示 100%,说明它正在疯狂地计算,独占了一个核心。

MEM USAGE / LIMIT 显示的是 实际用了多少内存 和 最多允许用多少内存。比如 150MiB / 1.5GiB。

MEM % 就是根据上面MEM USAGE / LIMIT 的数据计算出的一个百分比,更直观。比如 (150MiB / 1.5GiB) * 100% ≈ 9.77%。如果 MEM % 接近 100%,说明这个容器可能内存泄漏了,或者你给它分配的内存上限太低了。

NET I/O: 这是网络输入/输出量。NET I 是容器接收了多少数据,NET O 是容器发送了多少数据。如果某个网站容器的 NET O 非常高,说明它正在向外大量传输数据(比如很多人同时在访问)。

BLOCK I/O: 这是磁盘读写量。BLOCK I 是从硬盘读取了多少数据,BLOCK O 是向硬盘写入了多少数据。数据库容器(如 MySQL)的这个值通常会比较高,因为它要频繁读写数据文件。

PIDs: 这是容器内部运行的进程数量。一个正常的容器,进程数通常比较稳定。如果这个数字疯狂增长,可能意味着容器内部有程序在不停地创建新进程(比如遇到了“fork bomb”这类问题)。

3. 关键参数怎么用?(让你的操作更顺手)

提供的那些参数非常有用,我们来一个个看:

-a 或 --all

  • 功能:显示所有容器,包括那些已经停止的。
  • 比喻:默认的 docker stats 只显示“正在上班的员工”。加上 -a 后,你把“在家休息的员工”和“已经下班的员工”也全都叫过来点名了。
  • 用法:docker stats -a

--no-stream

  • 功能:只显示一次当前状态,然后命令就结束了,不再实时更新。
  • 比喻:默认模式是“现场直播”,而 --no-stream 是“拍一张照片”。适合在你只需要看一眼当前状态,或者想把数据记录下来的时候使用。
  • 用法:docker stats --no-stream

--no-trunc

  • 功能:不截断输出信息。
  • 比喻:容器 ID 和名字有时候很长,屏幕上显示不下,默认会用 ... 来截断。这个参数就是告诉命令:“别省地方,把完整信息都给我显示出来!”
  • 用法:docker stats --no-trunc

--format

  • 功能:自定义输出的格式,非常强大!
  • 比喻:默认的表格信息太多,你只关心 CPU 和内存。这个参数就像是一个“报表定制工具”,让你只显示你关心的那几列。
  • 用法举例:
  • docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}"
  • 这会只显示容器名、CPU 百分比和内存百分比,并且以漂亮的表格形式展现。
  • docker stats --format "json"
  • 这会以 JSON 格式输出,非常适合交给其他程序或者脚本去处理。

话不多说,我们直接看例子

docker stats

他会一直刷新

docker stats --no-stream

执行完后立马退出了

docker stats --format "json"

docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}"

2.11.docker container inspect

你可以把一个 Docker 容器想象成一个人。

docker ps 命令就像是看一个花名册,只告诉你这个人的名字(NAMES)、ID(CONTAINER ID)、什么时候来的(创建时间)、在干什么(STATUS)等基本信息。

docker container inspect 命令则像是调出了这个人的完整档案或者做了一次全面的体检。

这份报告里包含了这个人的所有详细信息:

  1. 出生证明(容器是如何创建的,用了哪个镜像)
  2. 家庭住址(IP地址、网络配置)
  3. 社会关系(连接了哪些网络、端口映射)
  4. 身体状况(CPU、内存限制,当前状态)
  5. 工作环境(环境变量、挂载了哪些目录)

简单总结:inspect 命令用于获取 Docker 对象(容器、镜像、网络等)的底层、详细的配置和状态信息,并以 JSON 格式返回。

你学的是 docker container inspect,所以是专门用来查看容器的详细信息的。

二、语法和关键参数详解

docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
  • CONTAINER: 这里你需要填容器的名字或者容器的ID(docker ps 看到的那一串)。你可以一次查一个,也可以一次查多个,用空格隔开。
  • [OPTIONS]: 就是你列出的那些关键参数。

关键参数深入讲解:

  • -f 或 --format:格式化输出(非常有用!)

为什么要用它? 默认情况下,docker container inspect <容器名> 会输出一屏非常长、非常全的 JSON 信息,可能有几百行。你想在里面找到一个特定的信息(比如IP地址),就像大海捞针。

它的作用:就像一把“手术刀”,让你能精确地只取出你关心的那一部分信息。

举例说明:

默认输出(信息太多):

docker container inspect my_nginx
(你会看到一大堆密密麻麻的JSON代码)

只用 -f 提取特定信息(干净利落):

我想只看这个容器的 IP 地址:
docker container inspect -f '{{.NetworkSettings.IPAddress}}' my_nginx
输出可能直接就是:172.17.0.2

我想看这个容器是用哪个镜像创建的:
docker container inspect -f '{{.Config.Image}}' my_nginx
输出可能直接就是:nginx:latest

我想看容器状态(是运行中还是已退出):
docker container inspect -f '{{.State.Status}}' my_nginx
输出可能直接就是:running

  • -s:显示文件大小

为什么要用它? 一个容器运行时,它的文件系统由两部分组成:

  • 只读层:来自它的镜像。
  • 可写层:容器自己产生的数据。

它的作用:加上 -s 后,在输出的 JSON 信息里,会多出一个 SizeRw 和 SizeRootFs 字段,告诉你这个容器的可写层占了多大磁盘空间,以及总的大小。这对于排查磁盘空间不足的问题很有帮助。

举例说明:

docker container inspect -s my_nginx

在输出的庞大 JSON 里,你可以找到类似这样的部分:

...
"SizeRw": 98304,
"SizeRootFs": 255087363,
...

SizeRw (大约98KB) 就是这个容器自己产生的数据大小。

“docker inspect 会自动检查是镜像还是容器然后显示相应信息。”

这句话的意思是,Docker 很聪明。

有一个更通用的命令叫 docker inspect(不带 container)

  • 如果你执行 docker inspect <容器名>,Docker 知道 <容器名> 是一个容器,所以它显示容器的详细信息。
  • 如果你执行 docker inspect <镜像名>,Docker 知道 <镜像名> 是一个镜像,所以它显示镜像的详细信息。

你学的 docker container inspect 是更明确的命令,它专门指定了要查看的对象是容器,所以后面必须跟容器名/ID。而 docker inspect 是通用命令,后面跟容器或镜像都可以。

对于初学者,我建议:

  • 想查容器,就用 docker container inspect。
  • 想查镜像,就用 docker image inspect。

这样更清晰,不容易搞混。


……

有很多数据啊!!

2.12.docker port

docker port 命令就像是你容器的 “端口查询员”。它专门用来告诉你:“你映射的容器内部端口,在宿主机的哪个端口上才能访问到”。

为什么要用它?(功能详解)

当我们运行一个容器时,经常会使用 -p 参数来做端口映射,例如:

docker run -d -p 8080:80 --name my-nginx nginx

这行命令的意思是:

  • 容器内部(Private) 的 80 端口(Nginx默认端口)。
  • 映射到了宿主机(Public) 的 8080 端口。

那么,问题来了:

  • 如果我忘记了当初是怎么映射的,怎么办?
  • 如果一个容器有多个端口映射,我想快速查看全部,怎么办?

docker port 就是回答这些问题的工具。 它用来查询已经存在的容器的端口映射关系。

怎么用它?(语法和别名)

语法

docker port 容器ID [容器内部端口/协议]

我们来拆解一下:

docker port:命令本身。

CONTAINER:容器的名字或者容器的ID。这是必须指定的,你要查哪个容器嘛。

但是,我们也可以指定协议(tcp或udp),不过通常我们使用默认的tcp。

接下来,我们通过一些例子来学习:

例子1:查看容器所有端口映射

docker port my-container

例子2:查看容器内部特定端口的映射

docker port my-container 80

这个是查看容器内部80端口号的映射的到底是宿主机的哪个端口号。

例子3:查看容器内部特定端口和协议的映射(比如udp)

docker port my-container 53/udp

注意:在例子3中,我们指定了端口和协议。但是,大多数情况下我们使用tcp,所以通常可以省略协议。


话不多说,我们试试看

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

接下来我们就来查询一下对应的端口

2.13.docker cp

docker cp,顾名思义,就是 copy 的缩写。它的核心功能就像你的电脑上的“复制粘贴”一样,只不过它是在 Docker 容器 和 本地宿主机 之间进行文件的复制和粘贴。

你可以把它想象成一座桥梁,专门用来在容器内外传递文件。

为什么要用 docker cp?

容器通常被设计成“无状态”的,也就是说,容器本身创建、删除很频繁,里面的数据随着容器的删除也会消失。但在实际使用中,我们经常需要:

把容器里产生的日志、数据文件或处理结果拿到主机上进行分析。

把主机上准备好的配置文件、脚本或代码复制到容器里使用。

这时候,docker cp 就派上了用场。

语法详解

# 从容器复制到宿主机
docker cp [OPTIONS] <容器名>:<容器内路径> <宿主机目标路径># 从宿主机复制到容器
docker cp [OPTIONS] <宿主机路径> <容器名>:<容器内路径>

我们来逐一解释每个部分:

  • [OPTIONS]:可选参数。最常用的是 -a(用于存档,保持文件所有者和权限)和 -L(如果源文件是符号链接,则复制链接指向的文件本身)。对于初学者,大部分情况下可以不用管它。
  • <容器名>:你要与之交换文件的那个容器的名称 或 ID。你可以通过 docker ps 命令来查看正在运行的容器的名称和ID。
  • <容器内路径>:容器内部的文件或目录的路径。
  • <宿主机路径>:你本地电脑(宿主机)上的文件或目录的路径。

特别符号 |- 的解释:

这个符号代表标准输入(stdin) 或标准输出(stdout)。这是一种高级用法,它允许你不经过实体文件,直接通过命令行流来传输数据。对于初学者,可以暂时先了解,等熟悉基础操作后再深入研究。

实际使用场景和例子

假设我们有一个正在运行的容器,它的名字叫 my_nginx_container。

  • 场景一:从容器复制文件到宿主机(非常常用)

你想把容器里 Nginx 的访问日志拿到本地来分析。

  • 容器内路径:假设日志文件在 /var/log/nginx/access.log
  • 宿主机目标路径:你想把它放到你当前目录下的一个叫 logs 的文件夹里。

命令如下:

# 语法:docker cp <容器名>:<容器内路径> <宿主机目标路径>
docker cp my_nginx_container:/var/log/nginx/access.log ./logs/

执行后,你当前目录的 logs 文件夹下就会出现一个 access.log 文件。

  • 场景二:从宿主机复制文件到容器(也很常用)

你写了一个新的网站配置文件 my_site.conf,想把它放进 Nginx 容器的配置目录中。

  • 宿主机路径:当前目录下的 my_site.conf 文件
  • 容器内路径:容器内的 /etc/nginx/conf.d/ 目录

命令如下:

# 语法:docker cp <宿主机路径> <容器名>:<容器内路径>
docker cp ./my_site.conf my_nginx_container:/etc/nginx/conf.d/

执行后,配置文件就被复制到了容器内部。通常复制完后,你需要重启容器内的 Nginx 服务来加载新配置。

  • 场景三:复制整个目录

docker cp 命令和 Linux 的 cp 命令一样,可以递归地复制整个文件夹。

# 把宿主机的 `./my_website` 整个文件夹复制到容器的 `/usr/share/nginx/html/` 目录下
docker cp ./my_website my_nginx_container:/usr/share/nginx/html/

注意事项(非常重要!)

  1. 容器必须存在:容器不一定要在 运行状态,但必须存在(即 docker ps -a 能看到它)。你甚至可以拷贝一个已经停止的容器里的文件。
  2. 路径要写对:容器内的路径是相对于容器根目录的,不是宿主机的目录。
  3. 权限问题:有时候你可能会遇到权限错误,特别是当容器以非 root 用户运行时。这时候可能需要调整文件权限或在宿主机上使用 sudo。
  4. 这只是一个临时方案:docker cp 非常适合临时的、一次性的文件交换。对于需要持久化的数据(比如数据库文件),正确的做法是使用 Docker 数据卷,这才是生产环境推荐的方式。

话不多说,我们直接看例子

首先先启动一个容器

docker run -d --name mywebsite -p 8080:80 nginx:1.23.4-perl

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
e0a2b96a8535   nginx:1.23.4-perl   "/docker-entrypoint.…"   38 seconds ago   Up 38 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

启动成功了啊。

docker exec -it mywebsite bash

等会我们就把这个文件拷贝到宿主机的当前目录里面

docker cp mywebsite:/usr/share/nginx/html/index.html .

现在我们进去修改一下这个文件

vim index.html

接下来我们把这个文件拷贝回去我们的容器里面

docker cp ./index.html mywebsite:/usr/share/nginx/html/

现在我们回去我们的浏览器看看

是不是也跟着变了!!!

2.14.docker diff

docker diff 就像给你的 Docker 容器拍“前后对比照”。它可以告诉你,从创建这个容器开始到现在,容器内部的文件系统发生了哪些变化——新增了哪些文件、修改了哪些文件、删除了哪些文件

1. 为什么会有“变化”?

要理解 docker diff,首先要明白 Docker 容器文件系统的层次结构:

  • 镜像层(只读):你用来创建容器的镜像(比如 ubuntu:latest)是基础,它是只读的。就像一张母盘,不能被修改。

  • 容器层(可写):当你运行一个容器时,Docker 会在镜像层之上添加一个薄薄的可写层。所有你对容器文件系统的修改(创建文件、安装软件、删除配置等)都发生在这个层里。

docker diff 命令查看的就是这个可写容器层相对于只读镜像层的变化。

2. 语法和输出

语法非常简单:

docker diff <容器名或容器ID>

我们看个简单的例子

输出结果由两列组成:

  • 第一列是一个字母,代表变化的类型。

  • 第二列是文件或目录的路径

这三个字母是核心,一定要记住:

字母含义英文简单解释
A添加Add在容器层新增了一个文件或目录。
C修改Change修改了镜像层中已存在的文件或目录的内容。
D删除Delete删除了镜像层中存在的文件或目录。

话不多说,我们直接看例子

我们现在查看一下我们之前已经运行起来的容器mywebsite

我们接着看看

docker exec -it mywebsite bash

接下来我们重新看看

docker diff 的输出通常是按文件路径的字母顺序排序的,而不是按照修改时间排序。

这就是为什么 /test.html 没有出现在最后一行。

2.15.docker commit

你可以把 Docker 镜像想象成一个“软件安装包”或“系统模板”(比如一个干净的 Ubuntu 系统),而容器则是根据这个模板运行起来的一个实例。

那么 docker commit 是做什么的呢?

它的功能是:将一个正在运行的容器,其当前的状态(包括你对它做的所有修改)保存下来,创建一个全新的镜像。

换句话说,docker commit 就像是给一个正在运行的容器“拍一张快照”或“创建一个系统还原点”,然后将这个瞬间的状态保存成一个全新的、永久的镜像。

让我们通过一个故事来理解:

  • 1.拉取“模板”(基础镜像)

你从仓库里拉取了一个干净的 Ubuntu 镜像。这就像你买了一台全新的、什么都没安装的电脑。

docker pull ubuntu:latest
  • 2.启动“实例”(运行容器)

你根据这个镜像启动了一个容器,并进入其中。

docker run -it --name my_web_server ubuntu:bash

现在,你就在这个“干净的 Ubuntu 电脑”里面了。

  • 3.在容器内进行修改

你开始在这台“电脑”里安装你需要的软件:

# 更新软件源
apt-get update# 安装 Nginx (一个流行的 Web 服务器)
apt-get install -y nginx# 创建一个你自己的网页,覆盖默认的
echo “<h1>Hello from My Custom Server!</h1>” > /var/www/html/index.html# 启动 Nginx 服务(在容器内,这只是临时运行)
service nginx start

此时,这个容器已经不是你刚开始的那个“干净 Ubuntu”了。它变成了一个已经安装并配置好 Nginx 和自定义网页的 Web 服务器。

  • 4.关键问题:如何保存你的劳动成果?

如果你直接 exit 退出这个容器,容器会停止。虽然容器本身还存在,但它的可写层是临时的。你最标准的做法是写一个 Dockerfile 来构建镜像。但作为一个初学者,你可能想:“我能不能就直接把我现在这个弄好的环境保存下来?”

答案就是:docker commit

  • 5.“拍快照”——使用 docker commit

你打开一个新的终端窗口(不要关闭容器),执行以下命令:

docker commit my_web_server my_custom_nginx:v1

my_web_server:是你正在运行的容器的名字。

my_custom_nginx:v1:是你想要创建的新镜像的名字和标签。

  • 6.结果

命令执行成功后,你可以通过 docker images 命令看到一个新的镜像,名叫 my_custom_nginx,标签是 v1。

现在,你可以基于这个新的镜像来运行无数个新的容器,每一个新容器都直接是你刚才配置好的状态:

docker run -d -p 8080:80 my_custom_nginx:v1 nginx -g “daemon off;”

访问 http://localhost:8080,你就能立刻看到 “Hello from My Custom Server!” 这个页面,而无需再重复执行 apt-get install 等步骤。


语法

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

CONTAINER:这是最关键的部分,你要指定哪个容器被打包。你需要知道容器的 ID 或 名称。(可以用 docker ps 命令查看)

[REPOSITORY[:TAG]]:为你新创建的镜像起个名字和标签。比如 my-ubuntu:v1。如果不写标签,默认是 latest。

现在我们来详细说说那些 [OPTIONS](选项):

1. -a (作者)

  • 作用:标明这个新镜像的作者是谁,就像在作品上签名。
  • 例子:-a "你的名字 <your.email@example.com>"
  • 使用场景:通常用于标注创作者信息,方便团队协作时知道这个镜像是谁制作的。

2. -m (提交信息)

  • 作用:描述你这次提交干了什么,就像写代码的 git commit -m “...” 一样。
  • 例子:-m “安装了 Vim 编辑器并配置了 Nginx”
  • 使用场景:强烈建议使用! 这能让你和他人以后一看就知道这个镜像和原版相比有什么不同,否则时间一长你自己都忘了改了啥。

3. -p (暂停)

  • 作用:在创建新镜像的过程中,暂停容器。
  • 使用场景:这是为了保证数据的一致性。想象一下,如果你在拷贝一个正在被改写的文件,可能会得到一个不完整的、损坏的文件副本。-p 选项会在提交的瞬间暂停容器,确保文件系统处于一个稳定的状态,提交完成后再自动恢复运行。对于生产环境或数据重要的场景,建议使用。

4. -c (应用 Dockerfile 指令)

  • 作用:这个稍微高级一点。它允许你在创建镜像时,直接写入一些 Dockerfile 的指令。
  • 最常用的指令是修改 CMD 或 ENTRYPOINT,也就是修改容器的启动命令。
  • 例子:假设你原来的镜像启动后默认是 bash,但你希望新的镜像启动后直接运行你装在里面的一个 Web 服务。
  • docker commit -c ‘CMD [“nginx”, “-g”, “daemon off;”]’ 容器id my-nginx
  • 这样,以后从 my-nginx 镜像启动的容器,就会默认运行 nginx 服务,而不是进入 bash。

话不多说,我们直接看例子

先运行起来一个容器

查看一下

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED              STATUS              PORTS                                     NAMES
7b2c06e835b7   nginx:1.23.4-perl   "/docker-entrypoint.…"   About a minute ago   Up About a minute   80/tcp                                    mywebsite1
  • 第一版镜像

接下来我们就把这个容器打包成镜像

docker commit mywebsite1 mywebsite2:v1.0

把当前正在运行的 mywebsite1 这个容器的所有状态(包括文件、配置、已安装的软件等)拍个快照,然后保存为一个叫做 mywebsite2 版本为 v1.0 的新镜像文件。

我们发现果然这个容器被打包成镜像了!!

  • 第二版镜像

接下来我们回到那个mywebsite1容器里面,执行下面这些命令

接下来我们就把它打包成第2版

docker commit mywebsite1 mywebsite2:v2.0

把当前正在运行的 mywebsite1 这个容器的所有状态(包括文件、配置、已安装的软件等)拍个快照,然后保存为一个叫做 mywebsite2 版本为 v2.0 的新镜像文件。

接下来我们就根据这2个镜像来启动容器v2.0版本

怎么样?是不是一运行起来就一这么一个文件。

  • 第三版镜像
docker commit -a 'juegen' -m 'create by juegen' -p mywebsite1 mywebsite2:v3.0

以作者 'juegen' 的身份,将名为 'mywebsite1' 的容器当前状态保存为一个新的镜像。在保存过程中暂停容器以确保数据安全,为新镜像添加描述信息 'create by juegen',并将新镜像命名为 'mywebsite2',版本号为 'v3.0'。

我们可以通过docker image inspect看看

docker image inspect mywebsite:v3.0

  • 第四版镜像

我们去看看我们mywebsite1的基础镜像的启动命令是啥?

……

这个配置的意思是:容器启动时运行 nginx 命令,并传递参数 -g 和 daemon off;。

解释:

  • nginx: 是Nginx服务器的可执行文件。
  • -g: 是Nginx的一个参数,用于设置全局指令。
  • daemon off;: 这个全局指令告诉Nginx以前台方式运行(而不是以守护进程方式运行)。

在Docker中,容器默认设计为运行一个前台进程,如果进程退出(变成后台守护进程),容器就会停止。

因此,通常我们会让Nginx以前台方式运行,这样容器就会一直保持运行状态,直到我们停止它。

我们可以通过docker commit的-c参数来修改这个启动命令

如果你希望新镜像启动时自动做某些事情,就用 -c 来告诉它!

docker commit -c '指令 [参数1, 参数2, ...]' 容器名 新镜像名

常用指令:

1. CMD - 设置容器启动命令(最常用)

# 设置启动时运行 nginx
docker commit -c 'CMD ["nginx", "-g", "daemon off;"]' mywebsite myweb:v1# 设置启动时运行 node.js 应用
docker commit -c 'CMD ["node", "app.js"]' myapp myapp:v1

2. ENV - 设置环境变量

# 设置数据库连接地址
docker commit -c 'ENV DATABASE_URL=mysql://localhost:3306/mydb' myapp myapp:v1

3. EXPOSE - 声明容器端口

# 声明容器会使用 80 端口
docker commit -c 'EXPOSE 80' mywebsite myweb:v1

4. WORKDIR - 设置工作目录

# 设置进入容器后的默认目录
docker commit -c 'WORKDIR /app' myapp myapp:v1

话不多说,我们直接看例子

docker commit -c 'CMD ["tail","-f","/etc/hosts"]' mywebsite1 mywebsite2:v4.0
  • 基于 mywebsite1 容器的当前状态
  • 创建一个名为 mywebsite2:v4.0 的新镜像
  • 关键:新镜像的默认启动命令被设置为 tail -f /etc/hosts

我们现在也可以去看看

docker image inspect mywebsite2:v4.0

我们发现它的启动命令变成了下面这个

当你运行新镜像时:

docker run --name test --rm -d mywebsite2:v4.0

容器会执行 tail -f /etc/hosts,这意味着:

  • 容器启动后会持续监控 /etc/hosts 文件

  • 如果文件内容发生变化,会实时显示变化

  • 这个命令永远不会自动结束,所以容器会一直运行

root@VM-16-14-ubuntu:~# docker ps --no-trunc | grep test
e8794544ff397b601f8646430685ded8797a606c354d96658624ef01c4788f34   mywebsite2:v4.0     "/docker-entrypoint.sh tail -f /etc/hosts"       49 seconds ago   Up 49 seconds   80/tcp                                    test

我们发现它的启动命令也是变了的.

我们换一个终端看看

docker logs -f test

怎么样?是不是就是/etc/hosts的

2.16.docker pause和docker unpause

docker pause 命令就像是给一个正在运行的容器按下了“暂停键”,让容器内部的所有程序瞬间“定格”,但容器本身并没有退出。

docker unpause 就是解除容器的暂停状态,让被"冻结"的容器恢复正常运行,就像按下了电影的"播放"键。

详细解释

我们可以用一个生活中的比喻来理解:

想象一下你在看一部电影:

  • 运行中的容器 = 正在播放的电影。
  • 容器内的进程 = 电影里的人物、声音、画面。
  • docker pause = 你按下了遥控器的 “暂停” 键。
  • docker unpause = 你再次按下 “播放” 键。

当你按下“暂停”(执行 docker pause)时会发生什么:

  • 瞬间冻结:电影画面会立刻定格在某一帧。同样地,容器里所有正在运行的程序(比如一个Web服务器、一个数据库)都会在它们当前的状态下立刻停止执行。
  • 状态保持:电影暂停时,人物的动作、表情、声音都保持着暂停那一刻的样子。容器也是如此,它占用的内存、打开的文件、网络的连接状态等,都会被原封不动地保留下来。
  • 没有消耗CPU:暂停的电影不会消耗播放器的处理能力。同样,被暂停的容器不会消耗任何CPU资源。但它仍然占用着内存和磁盘空间。
  • 快速恢复:当你按“播放”时,电影会从刚才暂停的那一帧无缝继续。同样,使用 docker unpause 命令,容器内的所有进程会立刻从被冻结的状态恢复运行,就像什么都没发生过一样。

基本语法:

docker pause 容器名 [容器名...]

你可以同时暂停多个容器,只需要在后面跟上它们的名字或ID。

docker unpause 容器名 [容器名...]

可以同时恢复多个容器,用空格分隔

实际操作步骤

假设你有一个正在运行的容器,名字叫 my_web_server。

暂停它:

docker pause my_web_server

命令行会直接返回容器名,表示已暂停。

查看状态:

  • 使用 docker ps 查看所有运行中的容器,你会发现 my_web_server 不见了(因为它暂停了,不算“运行中”)。
  • 使用 docker ps -a 查看所有容器,你会看到它的状态是 (Paused)。

恢复它:

docker unpause my_web_server

容器会立刻恢复运行。


话不多说,我们直接看例子

先启动一个容器

我们查看一下它的状态

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                     NAMES
707b63660f94   nginx:1.23.4-perl   "/docker-entrypoint.…"   8 seconds ago   Up 7 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

我们去浏览器看看

接下来我们直接暂停

我们继续看一下这个容器的状态

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS                   PORTS                                     NAMES
707b63660f94   nginx:1.23.4-perl   "/docker-entrypoint.…"   59 seconds ago   Up 58 seconds (Paused)   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

我们去浏览器看看

点击刷新一下,没有任何反应。

我们恢复一下

再去看看

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                     NAMES
707b63660f94   nginx:1.23.4-perl   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

这个时候我们回去这个浏览器看看

点击刷新,没有问题。

2.17.docker rm

docker rm 最核心的功能就是:把一个或多个已经停止运行的容器,从你的电脑上彻底删除掉,释放磁盘空间。

运行中 的容器(使用docker ps能查看到的) -> docker stop -> 已停止 的容器 -> docker rm -> 彻底删除

语法

docker rm [容器名或容器ID]
  • 容器名 / 容器ID: 这是每个容器的唯一标识。就像每个人都有名字和身份证号一样。
  • 你可以通过 docker ps -a 命令来查看所有容器(包括运行中和已停止的)的名字和 ID。

举个例子:

假设你有一个已经停止的容器,它的名字是 my_nginx,容器 ID 是 a1b2c3d4(通常只用前几位就能识别)。

那么,你可以用以下任意一种方式删除它:

# 通过容器名删除
docker rm my_nginx# 通过容器ID删除 (通常不用输全,能唯一识别即可)
docker rm a1b2c3

执行成功后,终端会把你删除的容器名或ID再显示一遍,表示删除成功。

docker rm的-f(强制)参数

现在我们来解决一个常见问题:如果我想删除的容器还在运行,怎么办?

如果你直接对一个正在运行的容器使用 docker rm,Docker 会好心提醒你:“嘿,这个家伙还在干活呢,不能直接删!” 然后报一个错误。

这时候,你有两个选择:

选择一(温和的做法):

  • 先停止它:docker stop my_nginx
  • 再删除它:docker rm my_nginx

选择二(强力的做法):使用 -f 参数

docker rm -f my_nginx

这个 -f 是 --force 的缩写,意思是“强制”。

它做了什么?

  • 它相当于直接走过去,对这个正在运行的容器说:“别干了,立刻消失!”。这个命令会做两件事:
  • 向容器发送一个 SIGKILL 信号(这是最强大的终止信号,无法被程序忽略或捕获),强制停止该容器。
  • 容器停止后,立刻将其删除。

-f 的优缺点:

  • 优点:方便、快捷,一步到位。
  • 缺点:太粗暴了。如果容器正在处理重要任务(比如写入数据库),直接 -f 可能会导致数据丢失或损坏。这就像你直接拔掉电脑电源,而不是从系统里正常关机。

给初学者的建议:

  • 尽量养成先 docker stop 再 docker rm 的好习惯。
  • 只有在确定容器里的工作不重要,或者它卡死了、无法正常停止时,再使用 docker rm -f。
  • 删除所有已停止的容器(非常常用!)

随着学习和测试,你可能会留下很多停止的容器,手动一个个删太麻烦了。

docker container prune 的功能是:删除所有处于停止状态的容器。

可以用这个命令:

docker container prune

它会列出所有将要被删除的停止容器,问你确认吗?输入 y 回车,就全部清空了。(这个命令非常实用,请记住!)

话不多说,我们直接看例子

首先我们现在已经有一个运行的容器了(使用docker ps 能查看到的)

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
707b63660f94   nginx:1.23.4-perl   "/docker-entrypoint.…"   10 minutes ago   Up 10 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite

如果按照正常的删除步骤,我们应该按照下面这个步骤来

docker stop 容器名字/容器ID
docker rm 容器名字/容器ID

我们看看

怎么样,这就是正常的删除容器的过程。

  • 使用-f参数删除容器

我们先运行一个容器

我们直接运行docker rm命令看看

他说不能删除运行中的容器,这个时候我们就使用-f参数即可

这就删除了!!!

2.18.docker export和docker import

在深入讲解之前,我们必须先弄清楚 Docker 里两个最基本的东西:

  • 镜像:一个只读的模板。它就像是一个程序的“安装包”或者“光盘映像”(比如 .iso 文件)。它包含了运行某个软件所需的所有内容:代码、运行时环境、库、环境变量和配置文件。镜像是静态的,不能直接运行。

  • 容器:一个镜像的运行实例。它就像是把“安装包”安装好后,正在运行的那个程序。容器是动态的,你可以启动、停止、删除它。容器在镜像的只读层之上,创建了一个可写的层,你的所有修改都发生在这里。

简单比喻:

镜像 = 盖房子的设计图纸(只读,不能住人)。

容器 = 根据图纸盖好的、正在住人的房子(可读写,有生活痕迹)。

命令一:docker export

它是做什么的?

docker export 命令用于将一个容器的文件系统快照,打包成一个压缩文件(tar 归档文件)。

关键点:

  • 操作对象是容器:你必须指定一个容器的 ID 或名字。
  • 导出的是容器的“当下”:只包含容器当前的文件系统状态,不包含它的历史记录、元数据(如原来的启动命令、环境变量、端口映射等)。
  • 结果是一个文件:通常是一个 .tar 文件。

怎么用?

命令格式很简单:

docker export [容器名或ID] > [导出的文件名].tar
# 或者
docker export --output="[导出的文件名].tar" [容器名或ID]
#或者
docker export -o "[导出的文件名].tar" [容器名或ID]

实际例子:

我们先运行一个容器,并在里面创建一个文件。

# 启动一个名为 my_container 的 nginx 容器
docker run -d --name my_container nginx:1.23.4# 进入这个容器
docker exec -it my_container /bin/bash# 在容器内创建一个新文件,然后退出
echo "Hello, I was created inside the container!" > /my_file.txt
exit

现在,我们把这个容器的当前状态导出来。

docker export my_container > my_container_snapshot.tar

执行完后,你当前目录下就会生成一个 my_container_snapshot.tar 文件。这个文件里就包含了 nginx 的基础文件和那个我们新创建的 my_file.txt。

命令二:docker import

它是做什么的?

docker import 命令与 export 相反,它则是把一个 tar 文件导入,从而创建一个新的镜像。

关键点:

  • 操作对象是 tar 文件。
  • 生成的是一个新的镜像,而不是直接运行容器。
  • 新镜像丢失了大部分历史和元数据。你需要在使用新镜像时,重新指定启动命令、环境变量等。

怎么用?

命令格式:

docker import [tar文件路径或URL] [新镜像名]:[标签]

实际例子(接上面的例子):

我们现在把刚才导出的 my_container_snapshot.tar 文件,导入成一个新的镜像。

docker import my_container_snapshot.tar my_custom_nginx:v1

现在,你可以用 docker images 命令看到一个新的镜像,名叫 my_custom_nginx,标签是 v1。

你可以基于这个新镜像运行一个新的容器:

docker run -it my_custom_nginx /bin/bash

进入这个新容器后,你会发现 /my_file.txt 这个文件安然无恙地在那里。这就完成了容器状态的迁移!


话不多说,我们直接看例子

首先我们先运行一个容器来看看

使用docker ps查看一下状态

很好,我们现在先创建一个目录

现在我们进入这个容器里面

# 进入这个容器
docker exec -it mywebsite bash# 在容器内创建一个新文件,然后退出
echo "Hello, I was created inside the container!" > /my_file.txt
exit

现在我们把这个容器导出为.tar文件

docker export -o mywebsitetest.tar mywebsite

接下来我们就通过这个.tar文件恢复成镜像

docker import ./mywebsitetest.tar mywebsitetest:v1.0

接下来我们就依据这个镜像来生成容器

docker run -it mywebsitetest:v1.0 bash

怎么样?是不是很完美

2.19.docker wait

你可以把“阻塞”想象成 “等待并卡住”。

  • 当你运行 docker wait 命令后,你的命令行终端就好像被“定”住了一样。
  • 它不会像平时那样立刻给你一个新的提示符 $ 或者 > 让你输入下一个命令。
  • 它会一直停在那个地方,耐心地、一动不动地等待某个事件发生。
  • 在这个命令里,它等待的事件就是:你指定的那个容器停止运行。

命令的核心功能:等待并获取结果

想象一个真实的场景:

你派了一个工人(容器)去完成一项任务。docker wait 这个命令的作用就是:

  • 派你去盯着这个工人:你什么都不用干,就站在他旁边,一直看着他工作。
  • 直到他干完活:无论他是正常完工,还是中途出了问题干不下去了,总之,你一直等到他放下工具,停止工作。
  • 然后他告诉你最终结果:他停止后,会递给你一张“结果单”,上面写着一个数字,这个数字就是 退出代码。

什么是“退出代码”?

退出代码是一个数字,它告诉你容器里面的主进程是 如何结束的。这就像上面例子的“结果单”。

  • 0:这几乎总是代表 成功。意思是容器里面的程序顺利地完成了它的任务,没有任何错误地结束了。
  • 非 0 的数字(比如 1, 125, 137 等):这代表 失败 或 出现了某种异常。不同的数字通常代表不同的错误原因。例如,137 通常表示容器因为内存不足而被系统“杀死”了。1 可能表示容器内部的应用程序自己报错了。

所以,docker wait 最终打印出的那个数字,就是你判断容器运行是否成功的核心依据。

语法详解

docker wait CONTAINER [CONTAINER...]
  • docker wait:这是命令本身。
  • CONTAINER:这里你需要替换成 容器的ID或者容器的名字。你怎么知道ID或名字呢?可以用 docker ps 命令来查看正在运行的容器。
  • [CONTAINER...]:方括号 [] 里的内容表示它是“可选的”。意思是,你不仅可以等待一个容器,还可以一次性等待多个容器,只需要把它们的ID或名字一个个写在后面就行了。

举一个完整的例子

假设我们有一个名为 my_web_server 的容器正在运行。

我们打开终端,输入命令:

docker wait my_web_server

按下回车后,你会发现光标在闪烁,但命令行被“卡住”了,你不能输入其他命令。这就是“阻塞”状态。

现在,我们什么都不做,只是等待。也许过了几分钟,也许过了几小时,这个 my_web_server 容器因为某种原因停止了(可能是服务崩溃了,也可能是你手动用 docker stop 停了它)。

就在它停止的那一瞬间,被“卡住”的命令行会立刻“活过来”,并打印出一个数字。比如:

0
#(这行 0 就是命令的输出)

看到这个 0,我们就知道了:my_web_server 容器是正常退出的。


话不多说,我们直接看例子

我们打开另外一个终端看看

现在我们回去看看

这个0就是它的退出码!!

2.20.docker rename

在Docker中,每个容器都有一个名字。

当你创建容器时,你可以通过 --name 参数指定一个名字,如果你不指定,Docker会自动为容器生成一个随机的名字。

给容器起一个有意义的名字,可以帮助我们更好地管理和识别容器。例如,你可能有一个容器运行着MySQL数据库,那么你可以把它命名为 mysql-db,这样一眼就能看出这个容器的用途。

但是,有时候我们可能一开始没有给容器起一个合适的名字,或者后来想改变它的名字,这时候 docker rename 命令就派上用场了。

docker rename 命令的功能非常简单直接:给一个已经存在的容器重新命名。

语法

docker rename CONTAINER NEW_NAME
  • docker rename: 命令本身。
  • CONTAINER: 这是你要重命名的容器的当前标识。它可以是容器的ID或者容器的当前名字。
  • NEW_NAME: 这是你想要为容器设置的新名字。

注意事项

  • 容器必须存在:你要重命名的容器必须存在(可以是正在运行的,也可以是已经停止的)。
  • 新名字必须唯一:新名字在宿主机上必须是唯一的,不能与其他容器或镜像同名。
  • 重命名后,旧名字就不能用了:一旦重命名,你之前使用的旧名字就不再指向这个容器了,以后你需要用新名字来引用这个容器。

举个完整的例子

假设我们有一个容器,它现在的名字是 frosty_gates,我们想把它改成更有意义的 my-mysql-db。

  • 步骤 1:查看当前容器

首先,我们可以用 docker ps -a 命令查看所有容器,确认我们要改名的容器确实存在,并且记住它的当前名字或ID。

docker ps -a

输出可能类似:

CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS       NAMES
a1b2c3d4e5f6   mysql     "docker-entrypoint.s…"   2 hours ago   Up 2 hours   frosty_gates
  • 步骤 2:执行重命名命令

现在,我们使用 docker rename 命令来给它改名。

docker rename frosty_gates my-mysql-db

或者使用容器ID(更精确):

docker rename a1b2c3d4 my-mysql-db

按下回车后,如果命令执行成功,不会有任何输出。在Linux和Docker的世界里,“没有消息就是好消息”。

  • 步骤 3:验证结果

我们再次运行 docker ps -a 来检查改名是否成功。

docker ps -a

输出现在变成了:

CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS       NAMES
a1b2c3d4e5f6   mysql     "docker-entrypoint.s…"   2 hours ago   Up 2 hours   my-mysql-db

看!容器的 NAMES 一栏已经从 frosty_gates 变成了 my-mysql-db。以后你想操作这个容器(比如启动、停止、进入等),就可以直接用新名字 my-mysql-db 来引用它了。


话不多说,我们直接看例子

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED        STATUS         PORTS                                     NAMES
f27e761fc410   nginx:1.23.4-perl   "/docker-entrypoint.…"   26 hours ago   Up 3 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mywebsite
root@VM-16-14-ubuntu:~# docker rename mywebsite mynewwebsite
root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED        STATUS          PORTS                                     NAMES
f27e761fc410   nginx:1.23.4-perl   "/docker-entrypoint.…"   26 hours ago   Up 30 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mynewwebsite

怎么样?是不是很简单

2.21.docker container prune

在使用 Docker 的过程中,我们可能会创建和运行很多容器。这些容器在停止后并不会自动消失,而是会保留在系统中,除非你手动删除它们。时间一长,这些停止的容器会占用磁盘空间,并且让容器列表变得混乱。

docker container prune 命令的作用就是一次性清理所有停止的容器,释放磁盘空间,让环境变得整洁。

简单来说,docker container prune 的功能是:删除所有处于停止状态的容器。

注意:它不会删除正在运行的容器,只删除已经停止的。

语法详解

docker container prune [OPTIONS]

这里的 [OPTIONS] 表示可以附加一些选项,最常用的就是 -f 或 --force。

关键参数

  • -f, --force:跳过确认提示,直接删除。

默认情况下,当你运行 docker container prune 命令时,Docker 会出于安全考虑,询问你是否确认要删除所有停止的容器。

例如,它会显示:

你需要输入 y 或 yes 来确认,否则命令会取消。

如果你使用 -f 或 --force 参数,Docker 将不会询问,直接执行删除操作。这在脚本中非常有用,因为脚本无法交互式地输入确认。

  • 例子1:不带参数(交互式)

在终端输入命令:

docker container prune

然后你会看到警告信息和一个确认提示:

WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N]

如果你确认要删除,输入 y 并按回车。然后 Docker 会删除所有停止的容器,并显示删除的结果,例如:

Deleted Containers:
container_id1
container_id2
...Total reclaimed space: 50MB
  • 例子2:带 -f 参数(非交互式,强制删除)

在终端输入命令:

docker container prune -f

命令会立即执行,没有确认提示,并直接输出删除的结果,例如:

Deleted Containers:
container_id1
container_id2
...Total reclaimed space: 50MB

注意事项

  • 谨慎使用:这个命令会删除所有停止的容器,而且一旦删除,无法恢复。所以在你确定这些停止的容器不再需要时再使用。
  • 不会影响运行中的容器:只有停止的容器会被删除,运行中的容器不会受影响。
  • 其他 prune 命令:Docker 还有类似的 prune 命令,比如 docker image prune(删除未被使用的镜像)、docker volume prune(删除未被使用的数据卷)、docker network prune(删除未被使用的网络)。它们的使用方式类似,都可以用 -f 参数来跳过确认。

话不多说,我们直接看例子

查看一下它们的状态来

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                                     NAMES
171f71f3c5f2   nginx:1.23.4-perl   "/docker-entrypoint.…"   17 seconds ago   Up 17 seconds   0.0.0.0:8084->80/tcp, [::]:8084->80/tcp   test4
4db95040c0e2   nginx:1.23.4-perl   "/docker-entrypoint.…"   25 seconds ago   Up 24 seconds   0.0.0.0:8083->80/tcp, [::]:8083->80/tcp   test3
fc40b1506825   nginx:1.23.4-perl   "/docker-entrypoint.…"   33 seconds ago   Up 32 seconds   0.0.0.0:8082->80/tcp, [::]:8082->80/tcp   test2
1fdcaf5c15a5   nginx:1.23.4-perl   "/docker-entrypoint.…"   44 seconds ago   Up 43 seconds   0.0.0.0:8081->80/tcp, [::]:8081->80/tcp   test1

接下来我们停止2个容器

查看一下它们的状态

root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED              STATUS                      PORTS                                     NAMES
171f71f3c5f2   nginx:1.23.4-perl   "/docker-entrypoint.…"   About a minute ago   Up About a minute           0.0.0.0:8084->80/tcp, [::]:8084->80/tcp   test4
4db95040c0e2   nginx:1.23.4-perl   "/docker-entrypoint.…"   About a minute ago   Up About a minute           0.0.0.0:8083->80/tcp, [::]:8083->80/tcp   test3
fc40b1506825   nginx:1.23.4-perl   "/docker-entrypoint.…"   2 minutes ago        Exited (0) 48 seconds ago                                             test2
1fdcaf5c15a5   nginx:1.23.4-perl   "/docker-entrypoint.…"   2 minutes ago        Exited (0) 48 seconds ago                                             test1

接下来我们执行下面这个命令

输入y即可

我们再次查看一下

root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS          PORTS                                     NAMES
171f71f3c5f2   nginx:1.23.4-perl   "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes    0.0.0.0:8084->80/tcp, [::]:8084->80/tcp   test4
4db95040c0e2   nginx:1.23.4-perl   "/docker-entrypoint.…"   3 minutes ago   Up 3 minutes    0.0.0.0:8083->80/tcp, [::]:8083->80/tcp   test3

这个命令只会删除停止的容器!!!我们发现只有test1和test2被删除了!!

接下来我们测试一下-f参数

查看一下它们的状态啊

root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS                     PORTS                                     NAMES
171f71f3c5f2   nginx:1.23.4-perl   "/docker-entrypoint.…"   4 minutes ago   Exited (0) 4 seconds ago                                             test4
4db95040c0e2   nginx:1.23.4-perl   "/docker-entrypoint.…"   4 minutes ago   Exited (0) 4 seconds ago                                             test3

接下来我们执行下面这个

我们去查看一下

root@VM-16-14-ubuntu:~# docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED        STATUS          PORTS                                     NAMES

什么都没有了!!怎么样?

2.22.docker update

docker update 命令用于动态更新一个或多个容器的配置。这包括资源限制(如CPU、内存)等。这个命令允许你在容器运行时更改这些设置,而无需重新启动容器。

语法

docker update [OPTIONS] CONTAINER [CONTAINER...]

别名:docker container update

关键参数详解

1. --cpus

功能:指定容器可以使用的CPU核心数。可以指定小数,例如1.5表示1个半核心。

工作原理:这实际上是通过设置--cpu-period和--cpu-quota来实现的。例如,--cpus 1.5 相当于设置 --cpu-period=100000 和 --cpu-quota=150000。

示例:

# 限制容器最多使用 1.5 个 CPU 核心
docker update --cpus 1.5 my-container# 限制使用 0.5 个 CPU 核心(半核)
docker update --cpus 0.5 my-container

2. --cpuset-cpus

功能:指定容器可以运行在哪些CPU核心上。CPU核心从0开始编号。

示例:

# 允许容器使用第一个和第二个CPU核心(0和1)
docker update --cpuset-cpus 0,1 my_container# 允许容器使用0到3的核心
docker update --cpuset-cpus 0-3 my_container

3. --memory 或 -m

功能:设置容器可以使用的最大内存。单位可以是b (bytes), k (kilobytes), m (megabytes), g (gigabytes)。

注意:如果容器使用的内存超过这个限制,容器会被OOM(内存不足)杀死。

示例:

# 限制容器最多使用 512MB 内存
docker update --memory 512m my-container# 限制使用 1GB 内存
docker update --memory 1g my-container

4. --memory-swap

功能:设置容器可以使用的内存和交换分区(swap)的总大小。必须与--memory一起使用。

规则:

如果设置为-1,表示不限制交换分区大小(但受主机系统限制)。

如果设置为0,表示禁用交换分区。

通常,--memory-swap 是 --memory 的两倍,但可以自定义。

示例:

# 设置内存为512m,交换分区为1g,那么总内存为1.5g(因为交换分区包括内存部分,所以实际可用的交换分区是1g - 512m = 512m?不对,正确解释如下)
# 实际上,--memory-swap 表示内存和交换分区的总和,所以这里设置 --memory 512m --memory-swap 1g,那么交换分区就是1g - 512m = 512m。
docker update --memory 512m --memory-swap 1g my_container# 设置内存+交换分区总共 2GB(内存1G + 交换1G)
docker update --memory 1g --memory-swap 2g my-container# 禁用交换分区(与内存限制相同)
docker update --memory 1g --memory-swap 1g my-container# 不限制交换分区(危险!)
docker update --memory 1g --memory-swap -1 my-container

在 Docker 中,--memory 和 --memory-swap 有严格的依赖关系:

  • --memory-swap 必须 大于或等于 --memory
  • 如果只设置 --memory 而不设置 --memory-swap,Docker 会默认设置 --memory-swap = 2 × --memory

5. --cpu-period

功能:设置CPU CFS(Completely Fair Scheduler)调度周期。单位是微秒(μs)。默认值是100000。

范围:最小为1000,最大为1000000。

示例:

docker update --cpu-period 50000 my_container

6. --cpu-quota

功能:在一个CPU周期内,容器可以使用的CPU时间。单位是微秒(μs)。默认值是-1,表示没有限制。

这里的CPU周期就是--cpu-period设置的!

示例:

# 设置容器在100000μs的周期内可以使用50000μs的CPU时间,相当于0.5个CPU核心。
docker update --cpu-quota 50000 my_container

注意事项

  • 动态更新:docker update 可以在容器运行时更新配置,但有些更改可能需要容器内应用程序的配合才能生效(例如,应用程序在启动时读取了内存限制,则可能需要重启容器才能识别新的内存限制)。
  • 资源限制:在设置资源限制时,要确保设置的值在合理范围内,避免容器因资源不足而无法正常工作。
  • 查看更新结果:可以使用 docker inspect <container> 来查看容器的当前资源限制。
  • 性能影响:过度分配资源可能导致主机资源竞争,而分配过少则可能影响容器性能。

话不多说,我们直接看个例子

root@VM-16-14-ubuntu:~# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED        STATUS          PORTS                                     NAMES
f27e761fc410   nginx:1.23.4-perl   "/docker-entrypoint.…"   27 hours ago   Up 17 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mynewwebsite

接下来我们执行下面这个

docker stats mynewwebsite

我们发现它的最大内存限制是1.922GB,现在我们动态更新一下

# 设置内存为 500m,内存交换为 1g(500m × 2)
docker update -m 500m --memory-swap 1g mynewwebsite

现在我们回去看看

docker stats mynewwebsite

怎么样?内存限制是不是变成500MB了.

http://www.dtcms.com/a/548897.html

相关文章:

  • Linux《Socket编程UDP》
  • Java IO 流进阶:Buffer 与 Channel 核心概念解析及与传统 IO 的本质区别
  • 【Linux基础开发工具 (一)】详解Linux软件生态与包管理器:从yum / apt原理到镜像源实战
  • 镇江网站营销推广电商怎么做如何从零开始视频
  • opencv 学习: 01 初识图片处理
  • 从 Wot UI 出发谈 VSCode 插件的自动化发布
  • Rust专项——用 Weak 打破引用环:树与图结构实战
  • c#调Lua返回个字符串
  • 单元测试(JUnit、Mockito、PowerMock )
  • 不只是语法糖:解构作为 Rust 安全与清晰度的基石
  • 企业微信消息群发助手(企业微信自建应用)winform.netcore实现(详细配置)
  • 基于Vue的教育学习网站04y8688l(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 移动端网站生成器中国电商平台排行榜前100
  • Excel正则表达式.获取字符
  • K8s 资源管理与操作
  • 如何在 Azure 虚拟机上部署 Elasticsearch
  • Go切片的赋值
  • Go语言设计模式:原型模式详解
  • 泉州网站建设-泉州网站建设石家庄网站建设招聘
  • [MySQL]表——权限控制
  • 把AI“灌”进奶瓶:1KB决策树让婴儿温奶器自己学会「恒温+计时」
  • 视频网站怎么做移动广告联盟
  • 高速DIC技术用于无人机旋翼动态变形与轨迹姿态分析
  • Node.js环境变量配置
  • Docker 部署 Node.js + Playwright 项目,实现浏览器截图、打印和下载
  • 所有权与解构:一次把“拆”与“留”写进类型系统的旅程 ——从语法糖到零拷贝 AST
  • 基于ASM1042通信接口芯片的两轮车充电机性能优化研究
  • hadoop之MapReduce的map工作流程
  • 民治做网站公司门户网站开发要求
  • 设计师网站欣赏企业官网模板图下载