news 2026/9/28 5:57:37

Docker镜像与容器命令详解:从拉取到运行的一线实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Docker镜像与容器命令详解:从拉取到运行的一线实践

但凡用过Docker的人,几乎都绕不开两类命令——镜像命令和容器命令。我在一线维护服务器多年,见过不少新手一上来就记命令,背了半天还是对着docker ps和docker images犯迷糊。其实这俩命令只是看上去相似,背后是完全不同的对象和生命周期。这篇内容不搞花活,直接把最常用的镜像命令、容器命令拎出来讲透,再结合真实场景告诉你什么时候用哪个,顺便把我踩过的坑、总结的小习惯一起交代了。适合刚入门 Docker 的朋友,也适合想让命令用得更顺手的老手。

1. Docker 镜像命令:从拉取到构建的完整闭环

1.1 镜像到底是什么?命令操作的对象

先搞明白镜像是什么,后面所有命令才记得住。镜像可以理解成一个打包好的、只读的模板,里面装了运行某个程序需要的操作系统底层、代码、依赖、配置。它没法直接执行,只能被用来创建容器。你可以把它类比成 Java 里的 Class,容器就是 new 出来的具体实例;也可以类比成安装光盘,容器就是启动之后的电脑。

所以镜像命令围绕的核心就两件事:拿到镜像(pull、search、images),管理镜像(rmi、tag、inspect、history、build、push)。掌握了这个逻辑,命令不会乱。

1.2 镜像常用命令清单与记忆逻辑

我把日常用得最多的镜像命令列了个表,每个后面都带一句“为什么用这个”,方便你对应到场景。

命令作用典型使用场景
docker search <名称>搜索公共仓库里的镜像想看看某个镜像有没有官方版,比如docker search mysql
docker pull <镜像:标签>从仓库拉取镜像到本地部署前先拉镜像,docker pull nginx:alpine
docker images查看本地已有镜像列表确认镜像是否拉下来,看镜像大小
docker rmi <镜像ID/名称>删除本地镜像清理不再使用的镜像,释放磁盘
docker tag <源镜像> <仓库/名称:标签>给镜像打标签发布前改成自己仓库的命名格式
docker build -t <名称:标签> <路径>根据 Dockerfile 构建镜像用项目里的 Dockerfile 生成自定义镜像
docker push <镜像:标签>把本地镜像推送到仓库传到公司私有仓库或公共仓库
docker inspect <镜像名>查看镜像的详细配置信息查镜像的环境变量、架构等原始元数据
docker history <镜像名>查看镜像的分层构建历史排查镜像体积时看谁的 layer 最大
docker system df查看镜像/容器/缓存占用的磁盘空间清理前先看空间被谁占了

记忆逻辑很简单,动词就是操作行为:pull 表示拉,push 表示推,rmi 表示删镜像(注意是 rmi 不是 rm,rm 是删容器的),images 是列表,build 是构建。剩下不常用的了解就行,用到再查。

1.3 镜像命令实操:从拉取一个 nginx 到构建自己的镜像

我用 nginx 举个完整流程。假设你要拉一个 nginx 镜像,先跑docker pull nginx:alpine,这是瘦身版,比官方默认的小很多,适合日常测试。

$ docker pull nginx:alpine

看到 Pull complete 就成功了。然后docker images确认一下,输出里能看到仓库名、标签、镜像 ID、大小。注意同一个仓库可以有不同标签,比如nginx:latest和nginx:alpine,ID 可能不同。

接下来我想基于它做一个自定义镜像,往里塞一个自己的 index.html。先建一个目录,写个 Dockerfile:

FROM nginx:alpine COPY index.html /usr/share/nginx/html/

然后执行docker build -t mynginx:v1 .,注意最后那个点代表当前目录,也就是 Dockerfile 所在的上下文路径。构建成功后,再用docker images就能看到mynginx:v1了。

做完自定义镜像,习惯上会用 tag 命令打一个新标签:

docker tag mynginx:v1 registry.example.com/team/mynginx:v1

这样命名规范了,方便推到公司内网仓库。等你不需要测试镜像了,docker rmi mynginx:v1一键删除。如果删除时报“image is being used by container”,意思是有容器还在用,先停掉并删除容器再说。

提示:docker rmi 同时支持名称和 ID 删除,但 ID 只需输前几位,只要唯一即可,比如docker rmi f0e48。

2. 容器命令:管理整个容器生命周期

2.1 容器与镜像的关系:类与实例

前面说容器是镜像的实例,这一节展开讲。容器有生命周期,可以被创建、启动、停止、重启、删除。镜像永远是只读的,容器在运行时会生成一个可写层,所有操作都发生在这层。你改完容器里的文件,如果不 commit、不挂数据卷,容器一删就全没了。

容器命令比镜像命令多一些,但这恰好对应它的生命周期。我把整个流程分阶段:创建运行时、查询状态、执行操作、清理。每个阶段都有固定的几个命令,你按阶段记,就不会漏。

2.2 容器常用命令全景

核心命令是这些:

命令作用常用参数 / 说明
docker run <镜像>创建并启动一个新容器-d后台运行,-it交互模式,-p端口映射,-v数据卷,--name命名,--restart重启策略
docker ps列出正在运行的容器-a显示所有容器(包括已停止的),-q只显示ID
docker start/stop/restart <容器ID/名称>启动/停止/重启一个已存在的容器stop 是优雅停止,kill 是强制停止
docker rm <容器ID/名称>删除已停止的容器需要加-f强制删除运行中的容器
docker logs <容器ID>查看容器日志-f持续跟踪日志输出,--tail只显示最后N行
docker exec -it <容器ID> <命令>进入正在运行的容器内部常用/bin/bash或sh
docker cp <源路径> <容器ID:目标路径>在容器和宿主机之间拷贝文件从宿主机拷入容器,或从容器拷出
docker top <容器ID>查看容器内运行的进程类似宿主机 top,但不是所有环境都支持
docker stats实时查看容器资源占用内存、CPU、网络 IO,压测时很有用
docker inspect <容器ID>查看容器的详细配置和状态能拿到 IP、挂载、重启次数等

所有命令都支持前缀缩写,比如docker ps -aq列出所有容器的 ID,结合删除命令很好用。

2.3 容器命令实操:把 nginx 容器跑起来并进入它

用刚才的mynginx:v1镜像,我一条条演示。

创建并启动容器,命名为web1,把宿主机的 8080 端口映射到容器的 80 端口,挂在后台:

docker run -d --name web1 -p 8080:80 mynginx:v1

过两秒,浏览器访问http://localhost:8080,能看到页面。用docker ps确认容器在运行。这时候我想进容器内部看文件结构:

docker exec -it web1 sh

进去之后是/目录,可以ls /usr/share/nginx/html/看看我 cp 进去的 index.html。退出输入exit。

如果我想把容器里的配置文件拷到本地分析:

docker cp web1:/etc/nginx/nginx.conf ./nginx.conf

反过来也能把本地文件拷进容器。测试过程中想停止容器,就docker stop web1;重新启动docker start web1。日志排查用docker logs --tail 50 web1,看最近 50 行,加-f可以持续盯着日志输出。

注意:docker run 每次都会创建一个新容器,如果你习惯用相同的名称重复运行,会报Conflict. The container name "/web1" is already in use。这时候要么换名字,要么先docker rm -f web1再 run。

3. 组合应用:真实项目中的命令流

3.1 从零拉起一套 Web 应用 + 数据库

镜像命令和容器命令从来不是割裂的,实际部署时一定是先拉镜像,再跑容器,多个容器靠网络协作。我给你走一遍最典型的流程:跑一个 MySQL,再跑一个需要连它的应用。

先拉 MySQL 镜像:

docker pull mysql:8.0

然后跑 MySQL 容器,注意要设 root 密码、建库、挂数据卷防止数据丢:

docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD=root123456 \ -e MYSQL_DATABASE=mydb \ -v /opt/mysql_data:/var/lib/mysql \ -p 3306:3306 \ mysql:8.0

-e表示环境变量,这里告诉 MySQL 初始化时的 root 密码和要自动创建的库名。-v把宿主机的/opt/mysql_data目录挂载到容器里的数据目录,这样容器删了数据还在。

接着跑一个需要连接数据库的后端服务。假设我有个后端镜像叫myapp:latest,启动时需要传数据库地址,我可以用--link(不推荐了)或者直接让容器跑在自定义网络里。更标准的是创建一个网桥网络,让两个容器用容器名互访:

docker network create mynet docker run -d --name mysql8 --network mynet \ -e MYSQL_ROOT_PASSWORD=root123456 \ -e MYSQL_DATABASE=mydb \ mysql:8.0 docker run -d --name backend --network mynet -p 8080:8080 \ -e DB_HOST=mysql8 \ -e DB_USER=root \ -e DB_PASSWORD=root123456 \ myapp:latest

这里--network mynet是关键,之后 backend 容器里访问mysql8这个主机名就能连上数据库,不用关心数据库的 IP 是多少。这一套命令流覆盖了 pull、run、network、logs、ps,你用熟之后,几乎不再碰图形界面。

3.2 多容器协作:docker-compose 还在常用命令范围吗

严格说 compose 不算单条命令,但它是容器命令的编排延伸。当容器多到三五个时,一条条 run 太累,而且启动顺序、网络都难以维护。于是 docker-compose.yml 把镜像、端口的映射、环境变量、数据卷全部声明好,一条docker compose up -d就能拉起整个项目。

虽然本文聚焦常用命令,我还是要提一句:docker compose up -d、docker compose logs -f、docker compose down这三个命令,本质上是对前面说的 run、logs、rm 的批量封装。你理解了单容器的命令,再去看 compose 文件,不会有任何障碍。

经验:我自己判断是否用 compose 的标准是——如果超过两个容器,且它们之间有网络依赖关系,就直接写 compose。别嫌麻烦,后面重启、备份、迁移都会感谢这个决定。

4. 常见问题与避坑技巧

4.1 常见问题速查表

问题现象可能原因解决办法
拉镜像超时默认拉取源在国内网络下不稳定在/etc/docker/daemon.json里配置公共镜像加速器,然后重启 Docker
docker 命令提示权限不足当前用户不在 docker 用户组sudo usermod -aG docker $USER,重登生效;临时用sudo docker
容器启动后马上退出前台进程结束或启动命令出错docker logs <容器ID>查报错;确保镜像里 CMD/ENTRYPOINT 是指令型命令而不是 shell 脚本中断
端口被占用宿主机端口已被其他服务占用换一个宿主机端口映射,比如 8081:80
容器数据丢了没挂数据卷重新 run 时加-v,挂在宿主机目录;别把数据写在容器可写层
容器日志越来越大日志驱动默认不轮转在 daemon.json 设置log-driver: "json-file"和log-opts的 max-size、max-file
镜像越积越多多次 build 产生 dangling 镜像定期执行docker image prune -f清理悬空镜像
Docker 启动失败且报虚拟化未开启宿主机没启用硬件虚拟化或没有 WSL2 环境检查 BIOS 里虚拟化设置;Windows 下确认 Hyper-V/WSL 已启用
容器之间网络不通没放在同一个自定义网络里创建自定义网桥,run 时加--network <网络名>,用容器名互访

其中拉镜像慢是刚接触 Docker 的人最常见的问题。我在国内服务器上测试过,不改加速器直接拉 nginx,断断续续要好几分钟,配置好加速器后秒级完成。方法是在/etc/docker/daemon.json里加registry-mirrors字段,然后sudo systemctl restart docker。注意这个文件在 Linux 上路径固定是/etc/docker/daemon.json,没有就创建。Windows 上的 Docker Desktop 也有图形化配置入口,直接在设置里换镜像源。

提醒:别只图快随便找加速器地址,尽量用可靠的大平台提供的公共镜像服务,配置前先看说明。安全问题别忽视。

4.2 我的几个命令使用习惯

最后分享几个让运维变省心的习惯,都是平时踩坑总结出来的。

第一,所有长用的容器都加--name。无名的容器 ID 是一串随机 hex,logs、exec、inspect 都得复制一长串,有了名字就方便多了。第二,临时测试容器加--rm参数。比如docker run --rm -it nginx:alpine sh,退出容器后自动删除,不会留下一堆垃圾容器。第三,正式服务容器加--restart unless-stopped。重启宿主机或 Docker 服务时,容器会自动拉起,避免服务挂掉没人发现。第四,执行删除类命令前先用查询命令确认。比如删镜像前docker images,删容器前docker ps -a,确认 ID 再动手。第五,定期跑一把docker system prune -f。这命令会把停止的容器、没用到的网络、悬空镜像一并清掉,但注意别加-a,加-a会连未使用的镜像全部清理,可能误删你不想删的缓存镜像。

在真实环境里,我见过不少人在运维时对docker ps -a感到惊讶——为什么我停了容器,docker ps里看不到,但重新跑又提示名字冲突?其实就是因为容器还在,只是没运行,docker ps -a才能看到。这是最容易被忽略的点,记住了就不会发懵。

我自己还有个土办法:把每天要用的命令写成一个速查脚本放在服务器上,用docker images、docker ps -a、docker logs --tail 20 <容器名>各起一个别名,排查问题先看这三个状态,能解决八成问题。你也可以试试。

这个内容后续还可以扩展的方向很多,比如 Dockerfile 的优化、镜像体积瘦身、容器日志集中采集、多节点编排等。不过先把最常用的镜像命令和容器命令练到不用查资料就能跑,后面学啥都快。

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

Flutter鸿蒙适配实战:纯Dart密码强度库password_strength集成与踩坑

1. 鸿蒙适配下的新问题&#xff1a;一个纯逻辑库为什么也要认真对待1.1 从“代码能不能跑”到“集成链路通不通”前阵子接到一个活儿&#xff1a;把公司现有的 Flutter 登录注册模块整体迁到 OpenHarmony 设备上&#xff0c;其中注册页那个密码强度校验条&#xff0c;在 Androi…

作者头像 李华
网站建设 2026/9/28 5:57:33

Spring Boot 3 连接池实战:Druid 与 MyBatis-Plus 集成指南

《Druid 正确使用姿势全解析&#xff1a;Spring Boot 3 MyBatis-Plus 集成实战指南》做 Spring Boot 3 迁移的时候&#xff0c;我把一个老项目的连接池从 Druid 换成了 HikariCP&#xff0c;结果压测阶段又老老实实换了回来。原因很现实&#xff1a;HikariCP 性能确实能打&…

作者头像 李华
网站建设 2026/9/28 5:57:25

SpringBoot+Vue植物销售管理系统实战:从订单库存到权限部署全解析

做植物电商项目时&#xff0c;我一开始想的很简单&#xff1a;SpringBoot写接口&#xff0c;Vue画页面&#xff0c;前后端一拼就完事。等真正把“植物销售管理系统”从零写完&#xff0c;我才意识到这类系统真正考验人的地方&#xff0c;根本不在CRUD&#xff0c;而在订单状态流…

作者头像 李华
网站建设 2026/9/28 5:57:26

普陀集团网站建设避坑:3种方案拆解性能优化与真实报价

普陀集团网站建设避坑:3种方案拆解性能优化与真实报价 网站后台突然弹出一堆乱码广告,或者首页被替换成赌博链接,这种“被黑挂马”的噩梦,很多普陀本地企业主都经历过。别慌,这通常不是你的代码写得烂,而是安全基线没做好,加上服务器配置拖累了 性能优化 ,导致攻击者有机可乘。…

作者头像 李华