news 2026/10/1 3:49:17

Docker常用命令实战指南:从镜像管理到容器排障的完整闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker常用命令实战指南:从镜像管理到容器排障的完整闭环

做容器和K8s相关工作这几年,"docker常用命令"这个问题我至少被问过几百次。每次团队来了新人,第一件事就是丢给我一份命令速查表去背,结果往往是背了一个礼拜,真到了部署项目的时候照样两眼一抹黑。原因很简单:docker命令加起来几百条,但日常开发、测试、生产维护真正高频用到的不超过四十条,剩下的属于"知道有这个东西、用到的时候能查就行"。这篇东西我不是按手册帮你翻译一遍,而是按我实际排查问题、部署服务、带新人的工作路径把命令重新组织了一遍,每条命令都附带"为什么这么用"和"我在真实环境里踩过的坑"。目标是让你看完之后,能独立完成"拉镜像、起容器、看日志、排故障、配网络、清磁盘"这一整个闭环。

1. 别急着背命令,先想清楚docker到底在管理哪三类对象

1.1 镜像、容器、数据卷、网络:四个对象一条主线

docker的学习曲线之所以陡峭,一大半原因在于它同时引入了几个容易混淆的概念。镜像就是打包好的"安装包",里面包含了运行一个程序所需要的代码、运行时、系统库和配置,它是只读的。容器是镜像运行起来之后的"实例",你可以理解成从同一个镜像模板复制出来的多个运行中的机器,每个实例之间互相隔离。仓库是存放镜像的地方,Docker Hub是官方仓库,企业内部还能搭私有仓库。数据卷和网络则是容器与外界的桥梁,一个负责持久化数据,一个负责让容器之间互相通信。

刚开始学docker的人最常犯的错误是试图一条命令解决所有事。实际上只要抓住一条主线就够了:拉取镜像 -> 创建容器 -> 查看状态 -> 进入容器排查 -> 清理删除。这条主镇上用得上的命令不超过二十条,把这条主镇走顺了,剩下的命令都是在这条主镇上的补充和拓展。

1.2 建立一条从拉取到删除的命令主线

我建议新手画一张这样的路径图,超简单:

  • 镜像阶段:docker pull拉镜像 ->docker images查看本地有哪些镜像 ->docker rmi删除镜像。
  • 容器阶段:docker run创建并启动容器 ->docker ps查看运行中的容器 ->docker exec进入容器 ->docker logs看日志 ->docker stop/docker rm停止和删除容器。
  • 扩展阶段:docker volume管理持久化数据 ->docker network管理网络 ->docker compose管理一组服务的集合。

当你在大脑里建立了这样的主线,再去看网上各种"docker命令大全",你会发现它们其实都是在讲这三件事的细节。

1.3 最快的学习方式不是背,是敲三遍

很多初学者迷信"速查表"。我的建议恰恰相反:速查表只能用来查,不能用来背。真正有效的方式是找一个简单的项目,比如部署一个Nginx或者MySQL,把上面那条主线完整走三遍。第一遍跟着教程敲,第二遍不看教程凭记忆敲,第三遍故意制造错误再修复。三遍之后这些命令就变成了肌肉记忆,比任何背诵都牢靠。

还有一个我自己一直在用的技巧:docker命令的help信息本身就是很好的手册。docker --help列出所有命令分类,docker run --help列出run的全部参数,而且每条参数都带默认值说明。遇到不确定的写法,先敲docker xxx --help,大部分问题当场就解决了,比搜网页快得多。

2. 镜像管理:从拉取、查询到离线传输的完整闭环

2.1 拉取镜像时最容易被忽略的两个参数

拉取镜像的命令是docker pull,比如docker pull nginx:latest。这里有两个细节值得留意。

第一个是tag的选择。很多人看见latest就拉,实际上下生产环境的项目最好别用latest。原因很简单:latest是个会变动的引用,你今天拉的和下周拉的可能不是一个版本,等到排查线上问题的时候,镜像内容和你本地能复现的对不上,排查成本会非常高。我一般习惯指定明确的版本号,比如nginx:1.25.5或者mysql:8.0.36。

第二个是--platform参数。如果你的宿主机是ARM架构(比如苹果M系列芯片),而镜像仓库里默认给的是x86架构的版本,直接pull可能拉到错误的版本,或者拉下来之后启动不了。加上--platform linux/amd64可以强制拉取指定平台的镜像。不少新手在Mac上拉镜像到Linux服务器上部署,结果发现镜像架构对不上,就是这个原因。另外,假如你在国内网络环境下拉取镜像经常超时,可以在/etc/docker/daemon.json里配置registry-mirrors指向可用的镜像加速源。

2.2 查看本地镜像与空间的正确姿势

docker images是查看本地镜像最经典的命令,但实际工作中我更推荐docker image ls,因为它是docker命令体系里更规范的建议命令。两者的显示内容基本一致:REPOSITORY(镜像名)、TAG(标签)、IMAGE ID(镜像ID)、SIZE(大小)。

这里需要搞清楚一个容易混淆的点:IMAGE ID和镜像名加标签的区别。一个镜像ID可以对应多个仓库标签,比如你给同一个镜像打了三个tag,它们显示的IMAGE ID是同一个。删除镜像的时候,如果只删某个tag,镜像并不会被立即清理,只有当最后一个tag也被删掉时,镜像数据才会真正释放。

查询本地空间占用我推荐docker system df,这条命令会分门别类告诉你镜像、容器、数据卷、构建缓存分别占用了多少磁盘空间。排障的时候这命令很救命。

2.3 镜像的离线传输:save和load的实战价值

很多时候,你面临的环境是内网或者隔离网络,不能直接访问外部的镜像仓库。这时候就需要把镜像从一台机器传到另一台机器,用到的就是docker save和docker load。

具体做法是:在有网环境的机器上执行docker save -o nginx.tar nginx:1.25.5,把镜像打包成一个tar文件,然后通过U盘、内网传输工具等方式把这个tar文件拷贝到离线机器上,再执行docker load -i nginx.tar把镜像导入到本地镜像列表。这套操作在军工、金融、政务等隔离环境中非常常用,几乎是必备技能。

需要注意一个细节:save导出的tar文件包含了完整的镜像历史层和元数据,文件体积往往比镜像压缩包大不少。如果你只想传输某个镜像的压缩版本,可以使用docker image ls --format "{{.Repository}}:{{.Tag}}"查看所有镜像列表,再决定要打包哪几个。还有一个细节是load之后要检查导入的镜像名和tag是否还保持原样。

2.4 删除镜像和"悬空镜像"的处理

删除镜像使用docker rmi 镜像ID或名称,比如docker rmi nginx:1.25.5。但实际使用中,你可能不知道这个镜像正在被某个容器使用。docker会给出错误提示,告诉你这个镜像被哪个容器依赖。这时候要么先停止并删除那个容器,要么使用docker rmi -f强制删除(不建议,会留下无法正常启动的容器)。

悬空镜像是指那些已经没有tag引用的镜像层,通常出现在你反复构建新镜像、覆盖同名tag之后。它们用docker images正常看不到,用docker images -f "dangling=true"才能看到。清理它们可以用docker image prune,它会自动把悬空镜像删除。我一般会定期跑一遍,释放不少磁盘空间。

3. 容器生命周期:run这条命令浓缩了docker设计的全部精髓

3.1 从docker run的参数看容器的几大属性

docker run是docker里最核心、最复杂的一条命令,可以说理解了run的参数,就理解了docker容器设计的绝大部分。

先看最基础的启动Nginx的案例:

docker run -d \ --name web-server \ -p 8080:80 \ -v /opt/nginx/html:/usr/share/nginx/html \ -e NGINX_HOST=example.com \ --restart unless-stopped \ nginx:1.25.5

这条命令的参数看起来多,其实拆开就没那么难懂了:

  • -d:后台运行容器,容器启动后返回容器ID,不会卡住当前终端。
  • --name:给容器起名字。如果不指定,docker会给容器随机生成一个名字,这对后续日志、进入容器、停止删除都很不友好。养成习惯,每个容器都起名字。
  • -p 8080:80:端口映射,把宿主机8080端口映射到容器的80端口。访客访问宿主机8080端口就能到达容器内的Nginx服务。
  • -v /opt/nginx/html:/usr/share/nginx/html:数据卷挂载,把宿主机的目录挂载到容器内。容器内对挂载目录的读写,直接对应到宿主机目录上。
  • -e:设置环境变量,用于向容器内部程序传递配置。
  • --restart unless-stopped:重启策略,容器挂掉之后自动重启,除非手动停止。生产环境这个参数非常重要。

顺便提一个新手容易踩的坑:-p 8080:80方向别反了。左边是宿主机端口,右边是容器端口。如果你写成-p 80:8080而容器内nginx监听的是80端口,那访问宿主机80端口肯定会连不上。排查端口映射问题时候,用docker port 容器名可以快速查看当前端口映射关系。

3.2 前台运行与交互式运行:-it参数的真实含义

很多新手分不清-i和-t。-i表示保持标准输入打开(interactive),-t表示分配一个伪终端(pseudo-TTY)。实际使用时通常合写成-it,用于启动一个需要交互输入的容器,比如进入一个Ubuntu镜像的shell环境:

docker run -it ubuntu:22.04 /bin/bash

这样你会直接进入到一个Ubuntu环境的bash终端,可以像操作虚拟机一样敲命令。退出时输入exit即可。

与之相对的是-d后台运行。如果你在后台运行的容器进程直接退出(比如容器里跑了一个短暂的脚本),容器会立即变成Exited状态。看到容器一启动就秒退,第一反应应该是去看日志,而不是反复重启。

3.3 stop、kill、rm的区别:优雅停止和强行杀掉的边界

docker stop会先给容器主进程发送SIGTERM信号,给程序几秒钟时间来做收尾工作(保存数据、关闭连接等),超时之后如果进程还没退出,docker才会发送SIGKILL强行杀掉。

docker kill则是直接发送SIGKILL,立刻终止容器进程。什么时候用kill?当容器卡死、无响应,stop命令等很久都停不下来的时候,才需要上kill。

docker rm是删除容器。注意:删除容器默认只能删除已停止的容器,如果要删除运行中的容器,必须加-f强制删除。删除容器时还有一个小习惯值得养成:docker rm -f -v 容器名。加了-v会在删除容器的同时把关联的匿名数据卷一起清理掉,避免时间一长残留一堆无用的无名卷占用磁盘。

另外,如果你只是临时用某个容器跑个测试,不想每次用完还要手动清理,可以用docker run --rm -it ubuntu:22.04 /bin/bash。--rm参数会在容器退出后自动删除容器,非常适合一次性任务。

3.4 查看容器的状态机:ps和ps -a的区别

docker ps只显示运行中的容器,docker ps -a显示所有容器,包括已停止的。很多新人的通病是:容器启动失败后用docker ps看不到容器,就以为容器没了或者镜像有问题。其实容器明明还在,只是处于Exited状态。用docker ps -a就能看到,状态字段会显示Exited (0) 2 minutes ago或者Exited (137)之类的信息。

退出码是个很有用的信号。退出码0表示正常退出,非0表示异常。常见的137表示进程被SIGKILL杀死,通常是因为内存资源限制或docker kill造成的;139表示段错误,通常是程序自身崩溃;143表示SIGTERM终止,一般是执行了docker stop。学会看退出码,排查容器崩溃问题会快很多。

另外强烈建议在查看容器列表时使用--format参数定制输出。比如docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"可以只显示你关心的列,多个容器时信息更清晰。这条命令对日常运维很实用,特别是在一台机器上跑了几十个容器之后。

4. exec、logs、cp:日常调试三板斧

4.1 用exec进入运行中的容器,而不是想办法在里面装ssh

很多人一提到"进入容器排查问题",第一反应是"要不要在镜像里装个sshd然后SSH进去"。这是完全错误的方向。容器本身就是进程隔离,没必要也不应该在里面装SSH服务。正确的方式是用docker exec。

docker exec -it 容器名 /bin/bash可以进入一个运行中的容器的shell。如果容器里的基础镜像是最小化的(比如alpine系列),里面可能没有bash,只有sh,那就要换成/bin/sh。遇到exec: "/bin/bash": stat /bin/bash: no such file or directory这个报错时,不用怀疑,就是这个原因。

还有一个从容器里退出的细节:按exit退出shell时,如果这个容器是以-it(前台交互方式)运行的,那退出会直接导致容器停止。但如果容器是-d后台运行的,你用exec进去再退出,容器进程不会受影响,继续后台运行。这条区别我经常跟团队强调,因为不少人用exec进容器排查,敲完exit出来发现服务没了,误以为是自己操作导致的,实际上是因为当初容器就是以交互方式跑的。

4.2 看日志别瞎翻,先学会tail和follow

docker logs是排查容器问题的第一工具。常用形式是docker logs -f 容器名,-f表示实时跟踪输出,类似tail -f。加上--tail 200可以只看最后200行,避免刷屏。-t可以给每行日志加上时间戳,对判断时序很有帮助。

实际操作中我经常用的组合是:docker logs -f --tail 200 容器名。先看最近两百行日志,再实时盯着输出,既能了解当前进展,又不会输出太多无关信息。

这里的坑在于:docker logs只能看到容器内进程写到标准输出(stdout)和标准错误(stderr)的内容。如果你的程序配置的是把日志写到文件里而不是直接输出到控制台,docker logs是看不到的。很多设置完日志怎么都不显示的新手,问题就出在这里:程序没往标准输出打日志。尤其是Java应用的logback、log4j这类日志框架,默认配置经常是输出到文件,需要专门配置一个ConsoleAppender才能让docker logs看到日志。

4.3 用cp在容器和宿主机之间搬运文件

docker cp用于在宿主机和容器之间复制文件。常见场景有两个:一个是从容器里把配置文件、日志文件拿出来分析;另一个是把宿主机上的新配置覆盖进容器里临时测试。

用法很简单:docker cp 容器名:/etc/nginx/nginx.conf ./nginx.conf把容器里的配置文件复制到当前目录;docker cp ./nginx.conf 容器名:/etc/nginx/nginx.conf反向复制。

使用cp有个大前提要记住:容器必须存在(不需要运行),cp操作的是容器的文件系统。如果改完配置文件,最好进容器里验证一下再重启容器。但需要注意,如果容器启动时使用了-v挂载目录,挂载目录的文件修改优先通过宿主机操作,直接用cp覆盖容器内文件往往不是正解,因为容器内看到的挂载目录文件就是宿主机目录的文件,cp进去反而容易搞混。

5. 容器体检:inspect、stats、top、port都是"现场取证"工具

5.1 inspect:容器的完整体检报告

docker inspect 容器名会输出容器所有底层配置信息的JSON结果,包括容器的完整ID、创建时间、状态、PID、网络配置、挂载信息、环境变量、日志配置、重启策略等。输出内容很长,通常配合过滤或格式化来读。

最实用的几个信息提取方式:

# 获取容器IP地址 docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器名 # 获取容器当前状态 docker inspect -f '{{.State.Status}}' 容器名 # 获取容器的挂载信息 docker inspect -f '{{json .Mounts}}' 容器名 | python3 -m json.tool # 获取启动命令 docker inspect -f '{{.Config.Cmd}}' 容器名

Go模板语法刚接触会觉得陌生,但这是docker inspect最核心的用法,值得花十分钟看一遍语法。实际排查问题时,一条inspect格式化命令往往能替代半小时的人工排查。

5.2 stats:实时看容器的算力消耗

docker stats可以实时查看各容器的CPU、内存、网络I/O、磁盘I/O使用情况,格式和top命令有点类似。但默认情况下它会持续输出刷新,在脚本里并不友好。加上--no-stream参数可以让它只显示当前这一帧的数据后退出:

docker stats --no-stream

遇到容器CPU飙升或者内存疑似泄漏,用这条命令可以快速锁定是哪个容器在占用资源。生产环境如果我需要连续观察,常见做法是把输出重定向到文件:docker stats --no-stream >> /tmp/docker_stats.log,然后用脚本定时追加。

5.3 top和port:看容器里到底跑了什么进程、端口映射到了哪里

docker top 容器名会列出容器内正在运行的进程列表,类似宿主机上的ps aux。这个命令在排查容器的子进程、僵尸进程问题时特别好使。

docker port 容器名可以查看容器的端口映射关系,输出形式是8080/tcp -> 0.0.0.0:80。当你不确定某个端口是否映射正确时,直接用这条命令比翻配置文件快。

6. 数据持久化和网络:让容器不怕删、能找到彼此

6.1 容器为什么不能存数据,数据卷的三种形态

容器本质上是基于镜像创建的临时运行环境,镜像的多层结构里,容器运行时新增的数据写在可写层,一旦容器被删除,可写层的数据也会随之消失。这就是"容器不适合存数据"的根本原因。

为了解决这个问题,docker提供了数据卷(volume)和挂载(bind mount)两种持久化方式。用大白话说,就是把容器里的某个目录"链接"到宿主机某个目录,读写容器内目录等于读写宿主机目录。

数据卷的三种形态:

  • 匿名卷:比如docker run -v /data 容器名,docker会在宿主机自动创建一个随机名字的目录,挂载到容器内的/data。匿名卷的问题在于容器删掉后匿名卷本身还在,但不跟任何容器关联,时间久了会成为磁盘垃圾。
  • 命名卷:比如docker run -v mydata:/data 容器名,卷名字是mydata。管理上比匿名卷清晰,推荐使用。
  • 绑定挂载:比如docker run -v /opt/data:/data 容器名,直接把宿主机的绝对路径挂载进容器,直观、易定位,缺点是跨主机迁移不方便。

6.2 数据卷管理常用命令

# 查看所有卷 docker volume ls # 创建卷 docker volume create mydata # 查看某个卷的详细信息,包括挂载点路径 docker volume inspect mydata # 删除一个卷(如果卷正在被容器使用会删除失败) docker volume rm mydata # 清理所有未被容器使用的匿名卷(谨慎使用) docker volume prune

生产环境我几乎不使用匿名卷,一方面无法快速定位卷对应哪个容器,另一方面删除容器时容易遗漏,日积月累占用大量磁盘。前面提到的docker rm -v就是为了防止这种情况。

6.3 默认网络和自定义网络:容器如何通过名字互相通信

docker默认提供了三种网络模式:

  • bridge:默认模式,容器连接到docker0网桥,通过网络地址转换访问宿主机网络。
  • host:容器直接使用宿主机的网络栈。性能好,但端口会直接占用宿主机端口,容易发生冲突。
  • none:容器没有网络配置,完全隔离。

在默认bridge模式下,两个容器之间可以通过IP地址通信,但IP地址是动态的,容器重启后很可能变化,这样非常不方便。因此docker提供了一种更优雅的方式:自定义bridge网络 + 容器名DNS解析。

操作方式:

# 创建一个自定义bridge网络 docker network create mynetwork # 把两个容器都接到这个网络 docker run -d --name app-server --network mynetwork nginx:1.25.5 docker run -d --name app-client --network mynetwork alpine:3.18 sleep 1d

在自定义网络中,app-client容器里可以直接通过app-server这个名字去访问app-server容器,docker内置的DNS服务会自动解析容器名到对应IP。这样容器重启后IP怎么变都不影响通信,是微服务之间互相访问的首选方案。

6.4 网络问题排查的基本步骤

遇到容器网络不通,我一般按这个顺序排查:

  1. docker network ls查看有哪些网络。
  2. docker inspect 容器名 | grep -A 10 "Networks"确认容器到底在哪个网络里。
  3. 如果两个容器不在同一个自定义网络,互相肯定不通。最简单的办法是docker network connect mynetwork 容器名把一个容器动态加入另一个网络。
  4. 确认宿主机的防火墙、端口映射是否正确。
  5. 在容器里ping或curl测试具体通信。

这里要特别提醒:默认bridge网络里的容器,跟自定义bridge网络里的容器有一点重要区别——默认bridge网络不提供基于容器名的DNS自动解析,你需要用--link参数或借助其他工具才能通过容器名互相访问。所以,凡是多容器协作的场景,一律建自定义网络,不要在默认bridge里硬撑。

7. compose:把一长串run命令固化成文件,告别复制粘贴

7.1 什么时候必须上compose

如果只是跑一个单容器,比如临时起一个MySQL做本地开发,直接docker run就够了。但一旦你开始部署"前端+Nginx+后端API+MySQL+Redis"这种多服务组合,还靠一条条run命令去敲,不仅命令行写起来复杂,还容易记错参数、漏配网络,二次部署时更是一场灾难。

Docker Compose的价值在于把这些命令参数固化成一个docker-compose.yml文件,在文件里描述服务、镜像、端口、环境变量、数据卷、网络依赖,然后在目录里执行一行docker compose up -d就能把整套服务拉起来。

7.2 一份可直接改的MySQL+Redis示例

我贴一份我在开发环境用的最简示例,方便你直接改:

version: "3.8" services: mysql8: image: mysql:8.0.36 container_name: dev-mysql restart: unless-stopped ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: root123 MYSQL_DATABASE: appdb TZ: Asia/Shanghai volumes: - mysql-data:/var/lib/mysql command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-proot123"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7.2-alpine container_name: dev-redis restart: unless-stopped ports: - "6379:6379" command: redis-server --appendonly yes volumes: - redis-data:/data volumes: mysql-data: redis-data:

这里有两个值得说明的设计:

一是healthcheck。它让compose能够知道MySQL是否真正启动完成(很多情况下MySQL容器起来了,但内部初始化还没完成),后续服务如果依赖MySQL就能用depends_on.condition来控制启动顺序。开发环境不怎么需要,生产环境几乎必须有。

二是给MySQL配置了--character-set-server=utf8mb4。原因很简单:MySQL默认字符集不是utf8mb4,存不了emoji和一些中文特殊字符。这个坑我踩过太多次,部署时没设字符集,后面程序写入中文报错,还要重建库,代价很大。

7.3 compose高频命令清单

启动一个编排:

docker compose up -d

-d表示后台运行。第一次执行会自动拉取镜像,后面执行则复用已有镜像。停止并删除编排中的全部容器:

docker compose down

注意:down默认会删除容器,但不会删除卷。如果你的数据卷不想保留,需要加上-v。这个-v是核弹级操作,会把编排里定义的所有卷删掉,数据彻底没救。别问我怎么知道的。

查看编排里的服务和日志:

docker compose ps docker compose logs -f --tail 200

进入某个服务容器:

docker compose exec mysql8 /bin/bash

重新构建并启动(改过镜像或者Dockerfile之后):

docker compose up -d --build

查看配置是否正确:

docker compose config

我个人的使用习惯是:任何包含两个及以上容器的项目,一律用compose管理,哪怕只是本地开发。因为文件本身是代码化的,提交到Git仓库后,任何同事拉下来都能复现一套一模一样的环境,这就是踩坑最少、协作最舒服的方式。

8. 资源清理和日常保养:磁盘被吃光的那些元凶

8.1 先看清磁盘到底被什么吃了

用docker system df查看docker相关的磁盘占用详情。输出会分为四块:Images(镜像)、Containers(容器可写层)、Local Volumes(数据卷)、Build Cache(构建缓存)。每个类型都会显示总大小和可回收大小。

这张表一下子就能暴露问题:是镜像太多、容器积压,还是日志太大、卷没人要。我见过不少服务器磁盘报警,排查了一圈最后发现是几十个停止状态的容器加一堆匿名卷占了几十G。

8.2 prune家族的清理力度差异

清理时我是按风险从小到大逐步推进的:

  • docker container prune:删除所有已停止的容器。
  • docker image prune:清理悬空镜像。加-a会删除所有未被容器使用的镜像,风险较高。
  • docker volume prune:删除所有未被容器使用的卷。风险极高,请谨慎。
  • docker system prune:一条命令清理所有停止容器、悬空镜像、未被使用的网络、构建缓存。加-a --volumes会把未被使用的镜像和卷也全删掉。

有一条铁律:不要在不确定卷里藏着重要数据的时候,执行带卷清理的prune命令。生产环境我至少会先跑docker volume ls和docker volume inspect逐个确认,再决定要不要清理。

我自己常用的温和清理方案是:

docker container prune -f docker image prune -f

这两条组合删掉的都是明确没用的对象,安全系数最高,效果通常也不错。

8.3 日志文件无限增长的问题

最后说一个最容易被忽视的磁盘杀手:容器日志。

docker默认的日志驱动是json-file,会以文件形式保存在宿主机上,路径一般在/var/lib/docker/containers/<容器ID>/下。如果容器不断打印日志,而你又从来没设置过日志轮转,那日志文件会不停地膨胀,直到把磁盘撑爆。最极端的情况我曾经见过单个容器的日志文件占了几百G。

解决办法是在/etc/docker/daemon.json里配置日志轮转:

{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" } }

配置后重启docker服务,新容器会按这个策略轮转日志。已有容器的日志需要手动清理:先运行docker inspect 容器名 -f '{{.LogPath}}'找到日志路径,再配合truncate -s 0 日志文件路径清空文件。注意不要直接删除文件,因为容器持有文件句柄,直接删除后句柄空间不会释放,要truncate才能在不停机的状态下把空间释放出来。这个细节在线上环境非常实用。

写了这么多,最后说句掏心窝的话:docker常用命令真不需要精通全部,能把镜像、容器、日志、卷、网络这五块的日常命令用得流畅,就已经超过绝大多数人的水平了。真正让你变强的不是命令本身,而是遇到问题时清楚"该用哪条命令去获取哪条信息"。我到现在还经常用docker inspect去翻配置,用docker logs去定位异常,用docker system df去检查磁盘,这已经成了一种本能反应。你不用特意去记我这篇里的每个参数,操练两三遍,让这套命令流变成自己顺手的工具,就够了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 3:47:52

Utility库鸿蒙化迁移实战:从编译通过到工业级稳定交付

把utility这个库鸿蒙化&#xff0c;听起来应该是整个迁移清单里最不起眼的活儿&#xff1a;不涉及UI渲染、不碰复杂算法&#xff0c;按说无非是换套工具链、改几个依赖版本&#xff0c;编译跑通就交付了。但我真正把一套“工业级基础类增强工具集”从Flutter生态迁到HarmonyOS …

作者头像 李华
网站建设 2026/10/1 3:47:33

线性代数学习笔记:用几何直观理解矩阵、行列式与特征值

1. 先泼盆冷水&#xff1a;你学不会线性代数&#xff0c;问题可能不在智商1.1 八成的人挂在同一个地方&#xff1a;把线性代数当算术学我大一那年学线性代数&#xff0c;最深的印象不是“难”&#xff0c;而是“不知道自己在干嘛”。课本第一章先扔出行列式定义&#xff0c;接着…

作者头像 李华
网站建设 2026/10/1 3:46:13

React Native鸿蒙适配开发:验证码倒计时器与重发逻辑实战

开头先聊点实际的。身边不少前端同事从 2024 年下半年开始关注鸿蒙&#xff0c;理由很直接——招聘岗位变多了&#xff0c;而且待遇不低。但要真的上手&#xff0c;大家普遍卡在同一个问题上&#xff1a;原生 ArkTS 的语法和组件模型跟 React 生态差异太大&#xff0c;熟悉 RN …

作者头像 李华
网站建设 2026/10/1 3:45:58

零基础Android脱壳实战:用frida-dexdump一键还原加固App业务代码

最近有个朋友拿着一个套了360加固的App来找我&#xff0c;问能不能把里面的业务逻辑还原出来看看。我说能&#xff0c;但需要先脱壳&#xff0c;他当时一脸懵&#xff1a;脱壳是什么&#xff1f;难不难&#xff1f;会不会把手机搞坏&#xff1f;我花了大概一个多小时&#xff0…

作者头像 李华
网站建设 2026/10/1 3:45:44

Pi Agent工具提示词优化实战:从12800到1152的降本指南

先说个前阵子踩的坑。我用 Pi Agent 做跨模块重构&#xff0c;会话跑到一半&#xff0c;模型开始频繁丢上下文&#xff0c;回答越来越敷衍。一开始我以为是长会话的老毛病&#xff0c;后来把会话的 token 明细拉出来一看&#xff0c;问题清楚得吓人&#xff1a;系统提示词里光工…

作者头像 李华
网站建设 2026/10/1 3:45:33

ST7701驱动开发实战:MIPI DSI点屏、初始化序列与花屏排查

简介&#xff1a;这份资源面向嵌入式Linux显示驱动开发者&#xff0c;提供ST7701/ST7701S液晶控制器的C/C驱动程序及配套资料&#xff0c;帮助开发者将屏幕快速集成到MTK、展讯等硬件平台。压缩包共6个文件、约5.3MB&#xff0c;以3份PDF规格与应用笔记、2份C语言驱动源码和1份…

作者头像 李华