ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker核心命令与容器管理实战指南

Docker核心命令与容器管理实战指南 1. 镜像管理一切的起点不管你是刚接触Docker的新手还是已经在开发环境里折腾了一段时间的“半熟手”我相信大部分人对Docker的第一印象都来自镜像。很多教程上来就让你跑一个docker run hello-world但其实日常开发里打交道最多的还是镜像的拉取、查看、删除和导出这类基础操作。我见过不少人把docker images和docker ps搞混也见过有人docker rmi和docker rm分不清结果把镜像删了一堆容器还在跑留下一堆none的悬空镜像越搞越乱。1.1 拉取与推送你必须先搞懂仓库、标签和镜像的关系先说最基本的docker pull。它的完整语法是docker pull [选项] 名字[:标签]这里的“标签”就是tag默认是latest。为什么我一直强调要把标签写完整因为latest不是一种保证它只是一个名字。很多软件的作者会把最新的稳定版打上latest但也有的项目会把最新的预发布版本也标记成latest你拉下来跑起来才发现行为不对。所以生产环境或者要复现问题的时候务必指定具体的版本号比如docker pull mysql:8.0.32。镜像名有时候还会带域名前缀比如docker pull registry.cn-hangzhou.aliyuncs.com/library/nginx:1.24这是从特定镜像仓库服务拉取。默认情况下Docker会去Docker Hub拉但国内网络环境下拉Docker Hub经常慢到让人怀疑人生这时候配置镜像加速器就成了刚需。具体操作是编辑Docker守护进程的daemon.json文件加上registry-mirrors字段然后重启Docker服务。这里我要提醒一句加速器不是万能的有时候拉取大镜像依然会超时好的习惯是尽量拉精简版镜像比如alpine系列体积只有几十兆部署和调试都快得多。和pull对应的是docker push这个命令一般配合docker tag使用。为什么要tag因为推送的镜像名必须包含仓库地址比如你要推到自己公司的私有仓库就得先把本地镜像重新打一个带仓库地址的标签再执行docker push。我见过很多人卡在这一步觉得docker tag和docker cp一样是“复制”操作其实tag只是给镜像增加了一个引用名称并不会复制一份实体数据。同一份镜像可以有多个标签删除其中一个标签不代表镜像被删了只有当最后一个标签被删掉镜像才真正变成待回收状态。1.2 镜像的清理与元数据rmi、prune、history和inspect镜像删不掉是新手最容易遇到的困境之一。docker rmi 镜像ID报错image is being used by stopped container很多人就懵了。这背后其实是一个很合理的保护机制容器创建时可能基于某个镜像写入了数据如果你把镜像删了容器的“底层底座”就没了后续排查问题会很麻烦。解决方案也很直接要么先删容器再删镜像要么用docker rmi -f强制删除。但我并不推荐动不动就加-f尤其是在有数据卷的情况下强制删除可能会让你丢失线索最好是先把关联的容器清理掉。随着镜像越拉越多本地磁盘会被大量无用的中间层镜像占满。这时候docker image prune是真正的救星。docker image prune -a会把所有没有被运行中容器使用的镜像都清理掉注意是“所有”不只是悬空镜像所以执行之前先看一眼列表或者用docker images确认一下哪些镜像你还留着有用。我还习惯搭配docker system df查看当前磁盘占用分布这个命令能很直观地告诉你镜像、容器、数据卷、构建缓存分别吃了多少空间。docker history 镜像名是我调镜像问题时很喜欢用的命令。它能展示镜像的每一层是怎么构建出来的每层的大小是多少。有时候你发现一个镜像异常大用history一查就能看到是不是某条RUN命令把源码、编译中间产物都留在了镜像里。配合docker inspect可以看镜像的配置信息比如环境变量、暴露的端口、入口点。我建议不要只是复制inspect的输出而是养成用docker inspect -f {{.Config.Env}}这种格式化输出的习惯只提取你关心的字段看着方便写脚本也顺手。这里把镜像相关命令整理成一张速查表方便你贴在终端旁边命令作用常用场景docker pull nginx:1.24拉取指定标签镜像部署前获取镜像docker images列出本地所有镜像检查镜像是否已存在docker tag 旧名 新名给镜像增加标签推送到私有仓库前打标docker push 仓库地址/镜像名:标签推送镜像到仓库发布自建镜像docker rmi 镜像名删除镜像清理无用镜像docker image prune -a清理未使用镜像磁盘空间告急时docker history 镜像名查看镜像构建历史排查镜像体积过大docker inspect -f {{.Config.Env}} 镜像名查看镜像配置确认环境变量等docker save -o 文件名.tar 镜像名导出镜像为tar文件内网离线传输docker load -i 文件名.tar导入tar文件为镜像离线环境安装镜像docker save和docker load这对命令在离线环境或者跨机器迁移镜像时特别好用。比如生产环境不能访问外网你就在本机把需要的镜像save成tar包拷贝过去再load。这里有个小坑save出来的tar包是包含所有历史层的所以文件往往比镜像本身看起来“占空间”要大这是正常的。如果有人只想要一层文件系统那就得用export/import但那个会丢失历史层信息我不建议日常使用除非你真的只需要运行时的文件系统。2. 容器生命周期从创建到销毁的完整闭环镜像只是模板真正跑起来的是容器。很多人理解容器时脑子里总想着“容器是不是一个小虚拟机”这么想也不是不行但容易留下一个误区以为容器是持久存在的。实际上容器更像是一个进程只是这个进程拥有独立的文件系统、网络和进程空间。搞清楚这个定位你就能理解为什么容器动不动就“没了”也不再会纠结“容器里改的文件怎么重启就丢了”这类问题。2.1 docker run一篇文章吃透最核心的参数创建容器没法绕开docker run。哪怕你后面用Docker ComposeCompose底层也是调用同样的逻辑。run的参数极多但日常高频使用的就那么几个我一个个说。-d表示后台运行detach不加的话容器会在前台运行直接霸占你的终端CtrlC还会把容器停掉。调试阶段建议不加-d这样日志直接打在终端上看得清楚等确认没问题了再改成-d。--name是给容器起名字如果不起Docker会随机分配一个focused_wing之类的名字做运维的人看到这种名字血压就会上来。-p是端口映射格式是宿主机端口:容器端口比如-p 8080:80表示把宿主机的8080端口映射到容器的80端口。这里有个坑如果你不写-p光靠容器内部的端口外面是访问不到的。Docker默认的网络隔离机制就是这么设计的。-v是数据卷挂载格式是宿主机目录:容器目录比如-v /data/mysql:/var/lib/mysql。这一步的作用是把容器里的数据目录映射到宿主机上这样即使容器被删除、重建数据也不会丢。我见过太多人因为图省事不挂数据卷一rm容器数据库就“失忆”了。--restartalways是设置重启策略表示Docker守护进程启动时自动拉起这个容器或者容器异常退出时自动重启。部署到服务器上这个参数几乎是必加的。还有两个容易被忽略但很实用的参数--rm和--network。--rm表示容器退出时自动删除非常适合跑一次性任务比如临时跑一个脚本、做一次数据库迁移跑完即焚不会在系统里留下一堆死掉的容器。--network用于指定网络模式默认是bridge桥接网络但如果你想容器直接共用宿主机网络栈就用--network host。要注意host模式下-p参数是失效的因为容器根本不会拥有独立的网络命名空间端口直接就是宿主机的端口。很多人第一次用host网络发现端口映射没生效就是这个原因。2.2 日常运维三件套start、stop、restart与rm容器跑起来之后日常操作无非就是启、停、重启、删除。docker stop 容器名和docker start 容器名我都经常用但这里有一个细节值得注意stop是发送SIGTERM信号给进程一个优雅退出的机会默认等待10秒后再发SIGKILL强制杀掉。如果你知道这个容器有比较长的收尾工作可以用-t参数延长超时时间比如docker stop -t 30 容器名。相反如果你想把stop和start合并成一步直接用docker restart也行它内部就是先stop再start。docker rm用于删除容器。删除之前如果容器还在运行需要先stop或者直接docker rm -f强制删除。rm -f本质上是先发SIGKILL再删除所以不推荐在容器有重要状态时使用。还有个命令是docker rename 旧名 新名这个很简单但很多人不知道容器名字起错了不用删除重建直接改名就行。暂停和恢复的命令docker pause和docker unpause也有用它们的机制和stop不同pause是使用cgroups冻结进程进程的内存状态还在只是不再被调度执行。什么时候用得上比如你想对一个容器做文件系统快照或者临时让某个服务“冻结”一下但不想让它彻底退出就可以用pause。不过日常使用频率确实不高知道有这回事就行。2.3 容器运行状态查看与进入容器exec和attach怎么选遇到问题要排查就必须进容器里看。常用的进入容器的方式有两种docker attach和docker exec。很多人刚开始学的时候会把它们搞混其实区别非常明显attach是把你当前的终端连接到容器的主进程上如果你退出比如按CtrlC意味着你向容器主进程发送了中断信号容器可能会跟着退出。而exec是在容器里再启动一个新的进程比如docker exec -it 容器名 /bin/bash这个bash进程是独立的你在这个进程里退出完全不影响容器主进程。所以我强烈建议日常调试一律用exec千万别用attach去“看容器日志”。有人觉得attach能看到实时输出很方便但只要你一退出容器就停了这个代价太大了。exec的-i和-t参数我也解释一下-i保持标准输入打开-t分配一个伪终端。简单说交互式操作比如敲命令、看输出、输入密码需要同时加-i -t也就是我们常说的-it。如果你只是想在容器里执行一条命令并拿到结果比如docker exec 容器名 cat /etc/hosts那不需要-it直接执行就行。另外docker cp是我经常忽略但到关键时刻特别管用的命令。它能在容器和宿主机之间复制文件。比如容器里的应用生成了一个日志文件或导出文件你想拿出来分析又不想进容器里搞什么重定向直接用docker cp 容器名:/app/data.log ./data.log就完事了。反向也一样比如你想把一个本地的压缩包拷进容器里解压docker cp 本地文件 容器名:/目标路径即可。这个命令不要求容器处于运行状态停止的容器照样能拷非常实用。3. 看日志、看状态、看资源调试容器必备的“三看”容器跑起来不等于一切正常。应用启动失败、端口没监听、内存持续上涨……这些都要靠日志和资源命令来判断。我见过很多人在容器出现问题时慌慌张张把容器删了重建结果问题复现时没有任何线索。正确做法是先保留现场看日志、看进程、看资源定位到原因再动手。3.1 docker ps的完整用法别忽略了-a参数docker ps是查看运行中容器列表的命令但真正完整的查看方式是docker ps -a它会列出包括已退出状态在内的所有容器。为什么要看退出的容器因为你可能需要找回之前的容器ID查看它的日志、检查它的配置或者基于它重新起一个容器。很多人在容器退出后找不到原来的容器了其实容器还在只是状态变成了Exited。docker ps的输出里包含一列STATUS它能告诉你容器已经运行了多久、是Up还是Exited、退出状态码是什么。状态码很有价值如果你看到一个容器反复退出状态码是1说明是程序自身的错误状态码是137一般是被OOM Kill或者强制杀掉了143则是被SIGTERM终止。别小看这个细节排查问题的时候能省不少时间。docker ps还有过滤功能。docker ps -a --filter statusexited可以只看已退出的容器--filter namemysql可以根据名字模糊搜索。容器数量多的时候用--last 5只看最近创建的5个比直接ps刷屏要舒服得多。3.2 docker logs查看日志的正确姿势与常见误区日志是排查问题的第一手资料。docker logs 容器名会把容器内主进程的标准输出和标准错误流都打出来。有个常见的误区你启动容器时用了-d然后发现容器好像没起来这时候第一反应应该是去看日志而不是急着看进程列表。docker logs经常能直接告诉你答案比如“port is already allocated”或者“database connection refused”。docker logs的几个参数也是高频使用的。-f用于实时跟踪日志输出类似于tail -f适合观察启动过程--tail 100表示只看最后100行日志量特别大的时候别直接一上来就全量打印先把最后几十行看明白再说。--since和--until可以按时间范围过滤比如docker logs --since 30m 容器名只看最近30分钟的日志。不过这里有个限制只有容器使用标准输出写日志这些命令才有效。如果应用直接把日志写到了容器内的某个文件里docker logs是看不见的你得用exec进去看文件或者把日志文件挂载到宿主机目录里我建议从设计上就做好这个规划别等系统跑起来了再来想着怎么收日志。3.3 docker top和docker stats容器里到底发生了什么当你需要知道容器里现在有哪些进程在跑用docker top 容器名。它的输出和Linux的top命令类似可以看到进程的用户、PID、CPU使用率、启动命令等。排查容器内进程异常、僵尸进程、或者确认某个服务是否还在运行这个命令很直接。docker stats则是查看所有运行中容器资源占用的命令输出包括CPU、内存、网络I/O、磁盘I/O等指标。我不建议长时间挂着看因为它会持续刷新比较消耗性能。我一般用docker stats --no-stream让它只输出一次快照然后分析重点。当你遇到宿主机负载突然飙高用这个命令扫一眼就能定位是哪个容器在“吃”资源。如果需要更细粒度的监控那就是Prometheus那套体系了但日常开发机上stats已经足够。3.4 容器健康检查与系统信息inspect、events、system dfdocker inspect是查看容器和镜像详细配置的瑞士军刀。它的输出是一个巨大的JSON看起来压力很大但只要会用-f格式化输出就能精确拿到你要的东西。比如查看容器的IP地址docker inspect -f {{.NetworkSettings.IPAddress}} 容器名查看容器挂载的数据卷docker inspect -f {{json .Mounts}} 容器名。掌握这些常用模板比你纯靠肉眼在JSON里找要高效得多。docker events是一个常被忽略的命令它以事件流的形式输出Docker守护进程接收到的所有事件比如容器创建、启动、停止、删除、镜像拉取等。我在调试自动化脚本、排查“容器为什么被拉起了”这类问题时非常依赖它。举个例子你发现某个容器总是在半夜被重启docker events配合时间戳就能看是不是定时任务或者外部脚本在操控Docker API。最后再提一下docker system df前面也提到过它会显示Docker在镜像、容器、数据卷、构建缓存四个维度上占用的磁盘空间并统计可回收的量。配合docker system prune使用prune会把停止的容器、未使用的网络、悬空镜像和构建缓存一次性清理干净。但这里我要特别提醒docker system prune -a --volumes是“核弹级”操作它会把所有未使用的数据卷也删掉。数据卷里装的很可能是有用的数据如果你只是想让磁盘干净一点建议先手动确认哪些数据卷要保留再用这个命令。我吃过一次亏清理完之后才发现开发数据库的历史数据全没了从那以后我再也不在prune后面加--volumes。4. 网络与数据卷让容器和外界正常协作容器之间、容器与宿主机之间、容器与外部网络之间这几种通信关系是搞Docker绕不开的内容。很多人遇到“容器访问不了外网”“容器之间互相 ping 不通”“容器重启后IP变了导致连接失败”这类问题根本原因往往出在网络配置上。数据卷则是另一个让人头大的点容器删除、升级、迁移之后数据能不能保得住全靠一开始挂载是否设计正确。4.1 容器网络模式bridge、host、none怎么选Docker默认提供几种网络驱动。bridge是默认的每个容器会拥有一个虚拟网卡通过一个叫docker0的网桥与宿主机通信。这种模式下容器和外界通信是需要NAT的而容器对外提供服务则需要-p做端口映射。host模式则直接让容器使用宿主机的网络栈没有独立的IP性能开销极小适合对网络性能要求高的场景。但代价是隔离性变差你没法用-p做端口控制容器监听什么端口宿主机就监听什么端口。none模式表示容器没有网络接口一般只用于极特殊的离线任务平时基本不用。除了这三种还有一种自定义网络custom bridge network是实际开发中最推荐的模式。用docker network create mynet创建一个网络然后启动容器时用--network mynet接入。自定义网络有一个内置DNS功能容器之间可以直接用容器名互相访问不需要查IP地址。这个特性在做微服务联调时尤其重要你不需要记录服务的IP直接用服务名就能请求到比如A容器访问B容器直接用http://B容器名:8080即使B容器重启导致IP变了连接也不会断。4.2 数据卷与绑定挂载我该把数据放哪里数据卷分两类一种是Docker管理的卷volume另一种是绑定挂载bind mount。用-v挂载宿主机目录的方式就是bind mount它的优点是你知道数据具体在哪可以随时到宿主机路径下查看或备份。而volume则是把数据交给Docker管理存放位置在/var/lib/docker/volumes/下面你想直接进去翻目录比较麻烦但它的好处是跨宿主机迁移更方便卷可以通过docker volume子命令独立管理。这里有一个常见的性能和数据安全细节如果你用bind mount挂了一个空目录到容器的非空目录容器里原有目录的内容会被“遮住”。举个例子你挂载/data到Nginx容器的/usr/share/nginx/html如果/data是空的网页目录就是空的404没商量。很多人在换Nginx、换页面文件时莫名其妙出现404排查半天发现是挂载目录覆盖了镜像里的默认文件。解决方案很简单先把镜像默认目录里的文件复制到宿主机挂载目录再挂载进去。对于数据库这类需要持久化存储的容器我有几个建议第一务必为数据库容器挂载数据卷防止容器重建后数据丢失第二备份时优先使用docker run --rm配合数据卷挂载的方式做逻辑备份而不是盲目地cp整个数据目录第三除非你真的知道自己在做什么否则不要用root用户直接操作/var/lib/docker/volumes下面的原始卷文件很容易因为权限问题搞坏数据。4.3 容器间通信与端口映射的那些坑端口映射是新手最容易踩坑的地方。-p 8080:80的做法是把宿主机8080端口映射到容器80端口。但你有没有遇到过“8080端口明明没被占用Docker启动却报端口冲突”的情况这往往是因为Docker默认的端口绑定地址是0.0.0.0也就是所有网卡接口都监听。如果你的宿主机有多个IP或者同时有内网和公网IP你可能只想让内网访问某个服务但0.0.0.0会把服务暴露在全部接口上包括公网。这时候可以指定绑定地址比如-p 127.0.0.1:8080:80就只允许本机访问。另外容器启动后IP地址是会变的。如果你手动指定了--network bridge容器每次重启IP都可能变。所以绝对不要在代码里写死容器的IP地址。如果两个服务需要通信优先用自定义网络加服务名。如果外部系统需要访问容器内的服务就用端口映射别依赖容器IP。5. Docker Compose把“一串命令”变成“一份配置”随着你接触的项目越来越复杂你会发现单条docker run命令会变得又臭又长端口要映射好几个环境变量要设十几个数据卷要挂几处依赖关系还要理清楚。拿这个命令去部署、去交接效率极低。这就要用到Docker Compose了。它本质上是一个“命令编排工具”把你原本要手敲的docker run参数写进一个docker-compose.yml文件里用一个docker compose up完成所有容器的创建和启动。5.1 从一条命令到一份compose文件Compose文件的语法其实很好理解一个服务对应一个容器服务名就是容器之间的通信名。例如你要跑一个Redis和依赖它的应用写出来的compose文件结构大致是这样的services: redis: image: redis:7.0 container_name: my-redis ports: - 6379:6379 volumes: - redis-data:/data restart: always app: build: . depends_on: - redis environment: - REDIS_HOSTredis - REDIS_PORT6379 ports: - 8080:8080 volumes: redis-data:这里redis这个名字在app服务里可以直接作为主机名使用比如REDIS_HOSTredis。因为Compose默认会为整个项目创建一个自定义网络所有服务都在这个网络里并且以服务名做DNS解析。depends_on表示服务启动顺序但这里要强调depends_on只保证“先启动依赖服务”不保证依赖服务“已经就绪”。比如数据库容器启动了但MySQL可能还需要几秒才能接受连接这时候你的app连接数据库时依然会被拒绝。解决办法是应用层面做重试或者用健康检查来控制真正的就绪状态。5.2 Compose常用命令up和down是主角但不是全部docker compose up -d是启动所有服务的命令-d表示后台运行。如果你修改了compose文件再执行一次up -dCompose会自动识别配置变化并重建对应容器这是非常方便的开发体验。docker compose down则是停止并删除所有容器连同默认创建的网络也会清理掉。注意down不会删除数据卷除非你加了-v所以数据一般还是安全的。查看服务状态用docker compose ps查看日志用docker compose logs -f。进某个特定容器用docker compose exec 服务名 /bin/bash。我经常遇到有人用docker compose logs查看所有服务的日志然后发现日志量大到根本看不清。实际上docker compose logs后面可以跟服务名比如docker compose logs app只看app服务的日志这个筛选能力很实用。docker compose config是一个好用的校验命令它会把compose文件解析成最终的配置并输出如果你写了语法错误、缩进错误它都会报出来。启动失败时别急着到处找原因先跑一下docker compose config很多时候问题就出在YAML格式上。还有一个命令是docker compose pull只拉取镜像而不启动服务适合部署前预先下载镜像避免启动时等太久。5.3 compose项目组织与命名的讲究Compose项目默认以所在目录名命名比如你在/home/user/demo下执行docker compose up那么创建的网络名就是demo_default容器名如果你没显式指定也会带上demo-前缀。如果你同时管理多个项目建议在compose文件顶部用name: myproject指定一个清晰的项目名避免后面排查时搞不清哪个容器属于哪个项目。还有一个很多人没注意的点Compose文件里不仅可以用image指定镜像还可以用build指定Dockerfile路径让Compose在启动前先构建镜像。这句话听起来很平常但我见过不少新手项目Dockerfile改了Compose启动后容器还是旧版本原因就是没用docker compose build重新构建直接up用了上次构建的缓存镜像。所以记住改了Dockerfile先docker compose build再up -d不要跳过构建步骤。6. 开发机上最常遇见的5个坑和排查方法我在文章里讲到不少具体的命令用法也知道命令用得再熟练遇到诡异的环境问题照样会让你卡住半天。接下来这些坑都是我本人以及周围同事在开发机和服务器上真实经历过的每一条都有具体的报错信息和排查思路建议收藏。6.1 Docker Desktop报错virtualization support not detected这个报错基本只出现在Windows上原因是CPU虚拟化没有开启。virtualization support not detected就是说Docker Desktop检测不到你电脑的虚拟化能力启动自然就失败了。排查步骤也很简单打开任务管理器点击“性能”标签页看看“虚拟化”一栏是不是“已启用”。如果是“已禁用”你需要进主板的BIOS/UEFI设置里打开Intel VT-x或AMD-V。不同品牌的主板设置位置不一样但一般都叫“Virtualization Technology”或“SVM Mode”。改完重启电脑再启动Docker Desktop一般就好了。还有一个后续报错也常遇到failed to connect to the docker api at npipe:////./pipe/dockerdesktop-linux。这个报错的意思是Docker Desktop后台没有真正跑起来或者客户端连接不到它的API。常见原因是Docker Desktop服务启动失败或者是用了WSL 2但内核没有更新。这时候先去Windows服务列表里找到com.docker.service确认它是不是运行状态如果不行就打开PowerShell执行wsl --update更新一下WSL内核然后重启Docker Desktop。这类问题九成以上可以通过“开启虚拟化更新WSL”两个步骤解决。6.2 镜像下载慢、拉取超时怎么办镜像下载慢在国内开发机上是个老话题了。除了配置镜像加速器还有一个思路是如果你能访问一台有完整镜像的服务器可以在服务器上docker save导出镜像为tar文件再拷贝到本机docker load。这个方法虽然笨但非常稳定适合那些加速器也救不了的大镜像。如果是在Dockerfile构建过程中下载基础镜像卡住可以考虑把基础镜像换成国内有缓存或更小体积的版本比如把ubuntu:22.04换成ubuntu:22.04的slim版本或者使用alpine。6.3 容器时间是UTC和本地时间对不上容器内部默认使用UTC时区你看到的日志时间会比北京时间晚8个小时。这个问题的表现是“日志时间对不上”排查问题时很容易产生误导。解决方案有两个一是在启动容器时通过环境变量设置时区比如-e TZAsia/Shanghai二是在挂载宿主机时区文件比如-v /etc/localtime:/etc/localtime:ro。使用Compose时直接在环境变量里加TZ: Asia/Shanghai即可。我建议从一开始就统一好时区规范不然日志混在一起排查问题就像破案一样费劲。6.4 端口占用冲突address already in use启动容器时遇到port is already allocated或address already in use说明端口被占用了。先查一下是谁占用的本机服务用lsof -i:端口号或者netstat -tlnp | grep 端口号Docker容器占用的用docker ps看端口映射列表。找到占用方之后要么停掉它要么换个宿主机的映射端口。如果你使用的是Compose并遇到端口冲突我建议不要把宿主机端口配成8080:80这种固定值可以考虑让Docker随机分配宿主机端口比如8080只写容器端口宿主机端口是随机的用docker compose ps查看实际分配端口。这种方式在本地开发时挺实用。6.5 Docker命令权限不足permission denied在没有配置好的Linux环境上装完Docker直接执行docker ps可能会报permission denied while trying to connect to the Docker daemon socket。这是因为当前用户不在docker用户组里。解决方法是把当前用户加入docker组sudo usermod -aG docker $USER执行后注销重新登录让组权限生效。如果没有sudo权限那就没办法了只能每次用sudo docker。不过这里要提醒一句把用户加入docker组等同于授予该用户较高的系统权限因为Docker守护进程是root权限运行的能操作Docker往往也能间接控制系统文件所以只建议在你完全信任的开发机上这么配置生产环境要谨慎管理docker组用户。排查问题时我的经验是先看报错原文提示再定位是命令语法问题、环境问题还是应用本身的问题。Docker的报错信息其实写得比较清晰只要你养成“先看报错、再动操作”的习惯很多坑都能少踩。比如docker run报Unable to find image说明本地没有这个镜像正在去拉取不是错误报exec: bash: executable file not found说明镜像里没有bash换个sh就好。最后再分享一个小技巧终端里把docker ps -a和docker images设置成别名比如alias dpadocker ps -a、alias dimdocker images。平时敲命令快很多也不容易手滑输错。等你把这些高频命令都练熟了再回头看那些动不动就要你“一行命令部署环境”的教程你就不只是会执行而是能真正理解它为什么能跑起来出问题也知道从哪里下手。这大概就是学习Docker最有价值的部分——你不是在背命令而是在掌握一种管理应用运行环境的方法。
返回列表