Java 项目部署之 Docker工具快速入门: 容器命令两个实战案例

📅 发布时间:2026/10/12 5:32:23
Java 项目部署之 Docker工具快速入门: 容器命令两个实战案例
概述容器命令本身只有十来条真正让人卡住的是这几个点-p 8080:80到底哪个是宿主机端口、docker rm为什么删不掉一个正在跑的容器、docker exec为什么提示容器没运行。本文用两个完整案例把run / ps / logs / exec / pause / unpause / stop / start / rm从头串一遍。纲要关键概念容器的三种状态运行、暂停、停止暂停不释放内存停止才回收端口映射-p 宿主机端口:容器端口容器默认对外隔离-d后台运行-it分配交互式终端核心流程docker run背后查本地镜像 → 拉取 → 创建容器 → 启动进程docker exec -it 容器名 bash进入容器内部执行 shell 命令涉及命令与配置docker run --name mn -p 8080:80 -d nginxdocker ps/docker ps -a/docker logs -fdocker exec -it mn bash、docker pause/unpause/stop/start/rm -fnginx 静态页目录/usr/share/nginx/html容器的三种状态容器不是要么活着要么死了两态中间还有一个暂停态状态含义进程内存占用进入 / 退出命令运行进程正常运行正常执行占用docker run/docker start暂停进程被冻结CPU 不再调度挂起不执行不释放docker pause/docker unpause停止进程终止回收内存与 CPU已终止已回收docker stop/docker startpause走的是 cgroup freezer把进程整个冻住内存页原样保留恢复后接着跑stop是先发SIGTERM、默认 10 秒宽限期后补一发SIGKILL进程没了资源也就回收了。想跳过宽限期直接杀用docker kill。docker rundocker pausedocker unpausedocker stopdocker startdocker rmdocker rm -f运行中暂停停止停止态的容器还占着磁盘它的可写层还在只有docker rm才把它彻底清掉。这个区别后面讲数据还在不在时要用到。docker run 背后发生了什么docker run看起来是一条命令实际干了四件事无有执行 docker run --name mn -p 8080:80 -d nginx本地是否已有 nginx 镜像从 Registry 拉取镜像 docker pull创建容器 分配可写层 网络 端口映射启动镜像 CMD 中定义的进程 nginx -g daemon off输出容器 ID 容器进入运行状态理解这一点docker ps里的那些列就有意义了CONTAINER ID 是创建时生成的唯一 IDCOMMAND 是镜像里定义好的启动命令PORTS 是创建时写死的映射关系——这些都不是运行时才决定的。案例一创建并运行一个 nginx 容器需求基于最新版 nginx 镜像创建容器命名为mn把宿主机 8080 映射到容器 80后台运行。课程资料目录day03-Docker/资料里已经备好了后续要用的离线包day03-Docker/资料 ├── cloud-demo/ # 后续 Compose 部署用的微服务工程 ├── mysql.tar # 离线镜像docker load -i 导入 ├── redis.tar.gz ├── jdk8.tar.gz ├── docker-demo.jar ├── Dockerfile ├── nginx.conf └── docker-composenginx 可以直接联网拉不用离线包# 创建并运行容器命名为 mn宿主机 8080 映射到容器 80后台运行dockerrm-fmn2/dev/null# 清掉上一篇残留的同名容器dockerrun--namemn-p8080:80-dnginx参数逐个说清楚参数作用说明--name mn指定容器名称必须全局唯一重名会直接报错后面所有命令都用这个名字指代容器-p 8080:80端口映射冒号左侧 8080 是宿主机端口右侧 80 是容器端口顺序写反就访问不通-d后台运行detach 模式命令立即返回容器 ID不加-d就是前台运行CtrlC 或关闭终端容器就停了nginx镜像名称不写 tag 等价于nginx:latest执行成功后返回一长串十六进制字符串那就是容器 IDdocker ps里显示的只是它的前 12 位。端口映射为什么必须有容器默认是对外隔离的网络环境直接访问宿主机 80 端口根本到不了容器里的 nginx。映射之后链路是这样容器 mn:80宿主机 192.168.150.101:8080用户浏览器容器 mn:80宿主机 192.168.150.101:8080用户浏览器GET / HTTP/1.1端口映射转发 8080 到 80返回 index.html响应 200验证三连# 查看运行中的容器默认只显示运行态dockerps# 只想看关键列用 --format 自定义输出dockerps--formattable {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}# 查看容器日志dockerlogs mn# 持续跟踪日志等效于 Linux 的 tail -fCtrlC 退出跟踪不会停掉容器dockerlogs-fmndocker logs后面必须跟容器名或容器 ID直接敲docker logs会报docker logs requires at least 1 argument。加上-ffollow log output后浏览器每刷新一次控制台就多一条GET /的 200 日志调试时比反复敲命令省事得多。访问http://192.168.150.101:8080看到 nginx 欢迎页说明容器起来了。案例二进入容器修改文件需求进入mn容器把 nginx 首页内容改成传智教育欢迎您。容器内部模拟了一套独立的 Linux 文件系统nginx 的环境、配置、静态资源全在里面容器 mn 内部 ├── bin/ etc/ lib/ tmp/ var/ root/ └── usr/ └── share/ └── nginx/ └── html/ # nginx 静态页目录 ├── 50x.html └── index.html # 要改的就是它进入容器的命令# -it 分配标准输入与伪终端进入 mn 容器并执行 bashdockerexec-itmnbash四个部分片段作用docker exec在一个已运行的容器内部执行一条命令-it-i保持标准输入打开-t分配伪终端两个一起用才能交互式敲命令mn目标容器名换成容器 ID 也行bash进入后要执行的命令bash 是 Linux 的终端交互命令进去之后cdlsrmmv这些 shell 命令都能用进去之后提示符会从rootlocalhost变成root容器 ID 前几位这串数字和docker ps里的 CONTAINER ID 完全一致可以用来确认自己确实在容器里。alpine 系的镜像比如redis:alpine、很多自制镜像里没有bash把bash换成sh即可docker exec -it mn sh。改文件这一步有个坑容器内是阉割版文件系统只打包了 nginx 运行必需的依赖vi压根没装cd/usr/share/nginx/htmlviindex.html# bash: vi: command not found用sed直接替换绕过编辑器cd/usr/share/nginx/html# 把 Welcome to nginx 替换为 传智教育欢迎您# 同时在 head 后插入 meta charset避免中文乱码sed-i-es#Welcome to nginx#传智教育欢迎您#g-es#head#headmeta charsetutf-8#gindex.html# 确认结果catindex.html|head-20浏览器刷新页面就变成了传智教育欢迎您。换 redis 试一次同样的动作命令形态完全一样只是最后的执行命令从bash换成redis-cli# 启动一个 redis 容器dockerrun--namemr-p6379:6379-dredis# 不进 shell直接执行容器内的 redis-cli 并拿到交互端dockerexec-itmr redis-cli# 也可以不交互直接取结果后退出脚本里常用这种写法dockerexecmr redis-cliping最后exit退出容器回到宿主机。注意docker exec起的进程退出不会导致容器停止容器主进程还活着。不过在容器里改文件这事只适合临时验证别当成常规操作。原因有两个一是容器内缺编辑器连vi都没有二是这些修改没有任何记录过几个月你根本想不起来改过什么重建容器时也没法复现。正确做法是用数据卷把目录挂载出来下一篇讲。暂停、停止与删除# 暂停冻结进程内存不释放dockerpause mndockerunpause mn# 停止终止进程回收资源dockerstop mn# docker ps 默认只看运行中的容器停止的要看全量得加 -adockerps-a# 重新启动一个已停止的容器注意是 start不是 runrun 是新建dockerstart mn# 删除运行中的容器删不掉dockerrmmn# Error response from daemon: You cannot remove a running container ...# Stop the container before attempting removal or force remove# 先停再删dockerstop mndockerrmmn# 或者强制删除dockerrm-fmndocker start和docker run的分工要分清run 创建新容器 启动start 启动一个已存在的容器。对同一个容器重复执行docker run --name mn会报The container name /mn is already in use。命令速查表命令作用说明docker run创建并运行容器常用参数--name、-p、-d、-v镜像不存在时会自动拉取docker ps查看运行中的容器加-a看全部含已停止加--format自定义列docker logs查看容器日志加-f持续跟踪加--tail 100只看最后若干行docker exec进入容器执行命令-it 容器 bash进交互终端容器必须是运行态docker pause暂停容器冻结进程CPU 不再调度内存不释放docker unpause恢复暂停的容器从冻结点继续不是重启docker stop停止容器先 SIGTERM默认 10 秒后 SIGKILLdocker kill直接 SIGKILLdocker start启动已停止的容器不会新建容器容器 ID 与配置保持不变docker rm删除容器只能删已停止的加-f强制删除运行中的加-v同时删匿名数据卷实战中的几个坑现象原因处理You cannot remove a running containerdocker rm不允许删运行中的容器先docker stop再删或docker rm -f强制删Container xxx is not runningdocker exec只对运行态容器有效先docker start或docker run新建暂停态同样进不去映射写成-p 80:8080访问不通冒号左侧是宿主机端口右侧是容器端口写反等于把请求转发到容器里没人监听的端口nginx 容器固定写-p 宿主机端口:80Bind for 0.0.0.0:8080 failed: port is already allocated宿主机端口已被占用换宿主机端口如8081:80或docker ps找出占用者并停掉不加-d关掉终端容器就停了前台运行时容器主进程挂在终端上CtrlC 直接终止加-d前台模式仅用于临时看启动日志容器 stop 后数据还在吗在。停止只是终止进程容器的可写层还在磁盘上docker start回来数据原样保留真正会丢数据的是docker rm。需要长期保存和迁移的数据用-v挂数据卷最后一条值得多说一句docker stop不等于数据消失docker rm才是。很多人以为容器停了写进去的文件就没了其实只要没rmstart回来东西都在——但那层可写层和容器生命周期绑定容器一删就跟着没了所以配置文件、上传目录这类东西必须走数据卷。官方文档docker run 命令参考docker exec 命令参考docker rm 命令参考Docker 官方镜像 nginx总结-p的顺序是宿主机在前、容器在后容器端口取决于应用自身nginx 恒定 80可随意改的是宿主机端口。docker ps默认只列运行态停掉的容器要-a才看得见这是容器怎么不见了这类问题的第一排查点。pause冻进程保内存stop终止进程回收资源两者不是一回事。rm删不动运行中的容器exec进不去停止的容器——这两个报错占了新手问题的绝大多数。容器内改文件只能应急缺vi、无记录、不可复现长期方案是数据卷挂载。