docker打tar包命令使用小结
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、打印内容说明</a></li><li><a href="#_label1">二、镜像名称 vs 容器名称:核心区别</a></li><li><a href="#_label2">一、命令是打包「镜像」,不是容器</a></li><li><a href="#_label3">二、先理清:各服务的「镜像完整名称」(打包的核心前提)</a></li><li><a href="#_label4">三、各服务镜像打包成tar包的正确命令(逐个说明)</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_0">通用规则:</a></li><li><a href="#_lab2_4_1">逐个服务的打包命令:</a></li></ul><li><a href="#_label5">四、补充说明</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">一、打包耗时:没有固定值,核心看2个因素</a></li><ul class="second_class_ul"></ul><li><a href="#_label7">二、怎么看是否在打包?3种方法确认状态</a></li><ul class="second_class_ul"><li><a href="#_lab2_7_2">方法1:新开终端,查进程(最直接)</a></li><li><a href="#_lab2_7_3">方法2:看磁盘写入(判断是否在干活)</a></li><li><a href="#_lab2_7_4">方法3:查Docker守护进程日志(可选)</a></li></ul><li><a href="#_label8">三、关于“命令执行完没输出”:必须等打包完成!</a></li><ul class="second_class_ul"></ul><li><a href="#_label9">四、打包完成/失败的判断</a></li><ul class="second_class_ul"><li><a href="#_lab2_9_5">1. 打包成功</a></li><li><a href="#_lab2_9_6">2. 打包失败</a></li></ul><li><a href="#_label10">五、补充:避免打包卡住的小技巧</a></li><ul class="second_class_ul"></ul></ul></div><p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202512/2025121009182433.jpg" /></p><p class="maodian"><a name="_label0"></a></p><h2>一、打印内容说明</h2>
<p><code>docker ps</code>默认输出的核心列是:<code>容器ID(CONTAINER ID)</code> → <code>镜像名称(IMAGE)</code> → <code>命令(COMMAND)</code> → <code>创建时间(CREATED)</code> → <code>状态(STATUS)</code> → <code>容器名称(NAMES)</code>。</p>
<p>对应到输出内容,每个服务的信息是:</p>
<table><thead><tr><th>容器ID</th><th>镜像名称(IMAGE)</th><th>容器名称(NAMES)</th></tr></thead><tbody><tr><td>lb91183ebbc59(注:实际是1b9183ebbc59)</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-knowledge:V1.0_1111</td><td>spark-knowledge</td></tr><tr><td>b7a640493d8e</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-search:V1.0_1014</td><td>spark-ai-search</td></tr><tr><td>3a63f64ae584</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-user:V1.0_1013</td><td>spark-user</td></tr><tr><td>7815490ddc9d</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-collect:V1.0_1036</td><td>spark-ai-collect</td></tr><tr><td>a5d617d29284</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-elasticsearch:V1.0_2</td><td>spark-elasticsearch</td></tr><tr><td>522c186756d1</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-gateway:V1.0_7</td><td>spark-gateway</td></tr></tbody></table>
<p class="maodian"><a name="_label1"></a></p><h2>二、镜像名称 vs 容器名称:核心区别</h2>
<p>可以类比成“安装包”和“正在运行的软件”:</p>
<ul><li><strong>镜像名称(IMAGE)</strong>:是一个<strong>静态的“模板/安装包”</strong>,里面包含了服务运行需要的代码、依赖、配置等所有内容(比如上面的<code>spark-knowledge:V1.0_1111</code>就是带版本的镜像)。它是“死的”,不能直接运行,只能用来创建容器。</li><li><strong>容器名称(NAMES)</strong>:是<strong>基于镜像启动的“动态运行实例”</strong>(比如<code>spark-knowledge</code>)。它是“活的”,可以启动、停止、修改里面的内容,每个容器都是独立的(哪怕用同一个镜像,也能启动多个不同的容器)。</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>一、命令是打包「镜像」,不是容器</h2>
<p><code>docker save</code> 是专门用于将<strong>Docker镜像</strong>打包成tar文件的命令,而容器是镜像的运行实例,打包容器需要用 <code>docker export</code>(但业务场景中一般优先打包镜像,因为镜像包含完整运行环境)。</p>
<p>你原命令里 <code>spark-knowledge:backup_$(date +%Y%m%d)</code> 是「镜像名称:标签」的格式,但这里有个小问题:你的镜像实际名称不是 <code>spark-knowledge</code>(<code>spark-knowledge</code> 是容器名),直接用这个会提示找不到镜像,需要先修正镜像名称。</p>
<p class="maodian"><a name="_label3"></a></p><h2>二、先理清:各服务的「镜像完整名称」(打包的核心前提)</h2>
<p>先从你之前的 <code>docker ps</code> 输出里提取每个服务的<strong>完整镜像名</strong>(镜像名带仓库地址+版本标签),整理如下:</p>
<table><thead><tr><th>容器名称(NAMES)</th><th>完整镜像名称(IMAGE,打包时必须用这个)</th></tr></thead><tbody><tr><td>spark-knowledge</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-knowledge:V1.0_1111</td></tr><tr><td>spark-ai-search</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-search:V1.0_1014</td></tr><tr><td>spark-user</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-user:V1.0_1013</td></tr><tr><td>spark-ai-collect</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-collect:V1.0_1036</td></tr><tr><td>spark-elasticsearch</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-elasticsearch:V1.0_2</td></tr><tr><td>spark-gateway</td><td>artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-gateway:V1.0_7</td></tr></tbody></table>
<p class="maodian"><a name="_label4"></a></p><h2>三、各服务镜像打包成tar包的正确命令(逐个说明)</h2>
<p class="maodian"><a name="_lab2_4_0"></a></p><h3>通用规则:</h3>
<p><code>docker save -o 【输出的tar包路径/名称】 【完整镜像名称】</code></p>
<ul><li><code>-o</code>:指定打包后的tar包保存路径和名称(建议包含服务名+日期,方便区分);</li><li>镜像名称必须和上面表格里的「完整镜像名称」完全一致(包括仓库地址、版本标签)。</li></ul>
<p class="maodian"><a name="_lab2_4_1"></a></p><h3>逐个服务的打包命令:</h3>
<h6>1. spark-knowledge 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;"># 打包后tar包名:spark-knowledge_20251203.tar(日期自动取当天)
docker save -o ./spark-knowledge_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-knowledge:V1.0_1111
</pre></div>
<h6>2. spark-ai-search 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;">docker save -o ./spark-ai-search_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-search:V1.0_1014
</pre></div>
<h6>3. spark-user 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;">docker save -o ./spark-user_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-user:V1.0_1013
</pre></div>
<h6>4. spark-ai-collect 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;">docker save -o ./spark-ai-collect_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-collect:V1.0_1036
</pre></div>
<h6>5. spark-elasticsearch 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;">docker save -o ./spark-elasticsearch_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-elasticsearch:V1.0_2
</pre></div>
<h6>6. spark-gateway 镜像打包</h6>
<div class="jb51code"><pre class="brush:bash;">docker save -o ./spark-gateway_$(date +%Y%m%d).tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-gateway:V1.0_7
</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>四、补充说明</h2>
<ol><li><p><strong>为什么不能用容器名打包?</strong><br /><code>docker save</code> 只认「镜像名」,不认「容器名」。比如你原命令里写 <code>spark-knowledge:backup_xxx</code>,但 <code>spark-knowledge</code> 是容器名,不是镜像名,执行会报错 <code>no such image</code>,必须替换成表格里的完整镜像名。</p></li><li><p><strong>打包后验证:</strong><br />执行完打包命令后,用 <code>ls -lh</code> 查看当前目录,能看到对应tar包(比如 <code>spark-knowledge_20251203.tar</code>),说明打包成功。</p></li><li><p><strong>如果想打包容器(极少用,仅作补充):</strong><br />若非要打包容器(容器是运行实例,打包后丢失镜像的分层、历史等信息),命令是:</p>
<div class="jb51code"><pre class="brush:bash;"># 以spark-knowledge容器为例
docker export -o ./spark-knowledge_container_$(date +%Y%m%d).tar spark-knowledge
</pre></div>
<p>业务场景中优先用 <code>docker save</code> 打包镜像,因为镜像可直接重新创建容器,而容器打包的文件仅能导入为镜像(且不完整)。</p></li><li><p><strong>批量打包(可选,简化操作):</strong><br />若想一次性打包所有服务,可写个简单脚本:</p>
<div class="jb51code"><pre class="brush:bash;">#!/bin/bash
# 定义所有服务的镜像名和对应输出文件名
declare -A images=(
["spark-knowledge"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-knowledge:V1.0_1111"
["spark-ai-search"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-search:V1.0_1014"
["spark-user"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-user:V1.0_1013"
["spark-ai-collect"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-ai-collect:V1.0_1036"
["spark-elasticsearch"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-elasticsearch:V1.0_2"
["spark-gateway"]="artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-gateway:V1.0_7"
)
# 循环打包
for name in "${!images[@]}"; do
docker save -o ./${name}_$(date +%Y%m%d).tar ${images[$name]}
echo "✅ 已打包 ${name} 镜像:./${name}_$(date +%Y%m%d).tar"
done
</pre></div>
<p>保存为 <code>backup_spark_images.sh</code>,执行 <code>chmod +x backup_spark_images.sh && ./backup_spark_images.sh</code> 即可批量打包。</p></li></ol>
<p class="maodian"><a name="_label6"></a></p><h2>一、打包耗时:没有固定值,核心看2个因素</h2>
<p>Docker镜像打包(<code>docker save</code>)的耗时主要取决于<strong>镜像大小</strong> + <strong>服务器磁盘IO/网络(如果镜像有远程层)</strong>:</p>
<ul><li>小镜像(几十MB):几秒到十几秒;</li><li>中大型镜像(几百MB<sub>几GB):几分钟甚至更久(比如你的spark相关镜像,大概率是几百MB级别,通常1</sub>5分钟居多)。</li></ul>
<p>你可以先执行 <code>docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep spark</code> 查看每个镜像的大小,能大致判断耗时:</p>
<div class="jb51code"><pre class="brush:bash;"># 执行这个命令看镜像大小
docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" | grep spark
</pre></div>
<p class="maodian"><a name="_label7"></a></p><h2>二、怎么看是否在打包?3种方法确认状态</h2>
<p><code>docker save</code> 命令执行时默认<strong>没有实时输出</strong>(属于“静默执行”),但可以通过以下方式判断是否在运行:</p>
<p class="maodian"><a name="_lab2_7_2"></a></p><h3>方法1:新开终端,查进程(最直接)</h3>
<p>登录服务器新开一个终端,执行以下命令,能看到 <code>docker save</code> 进程就说明还在打包:</p>
<div class="jb51code"><pre class="brush:bash;"># 查找docker save相关进程
ps -ef | grep "docker save"
# 或更精准:只看正在运行的docker save进程(排除grep自身)
ps -ef | grep "docker save" | grep -v grep
</pre></div>
<ul><li>输出类似这样,说明进程还在(打包中):<div class="jb51code"><pre class="brush:bash;">root 12345120002 10:00 pts/0 00:00:10 docker save -o ./spark-knowledge_20251203.tar artifacts.iflytek.com/znfw-docker-repo/znzt2024qyzskv10cpg hxm/ckb/spark-knowledge:V1.0_1111
</pre></div></li><li>若没有输出,说明进程已结束(要么打包完成,要么报错退出)。</li></ul>
<p class="maodian"><a name="_lab2_7_3"></a></p><h3>方法2:看磁盘写入(判断是否在干活)</h3>
<p><code>docker save</code> 会往本地写tar文件,可通过 <code>du</code> 或 <code>ls -lh</code> 实时看文件大小变化:</p>
<ol><li>先执行 <code>ls -lh | grep .tar</code> 看目标tar文件的大小(刚执行命令时,文件可能是0字节或很小);</li><li>隔几秒再执行一次,如果文件大小在持续增长,说明还在打包;</li><li>若大小长时间不变,且进程也消失了,说明打包完成/失败。</li></ol>
<p>示例:</p>
<div class="jb51code"><pre class="brush:bash;"># 实时监控tar包大小(替换成你的包名)
watch -n 1 "ls -lh spark-knowledge_$(date +%Y%m%d).tar"
</pre></div>
<ul><li><code>watch -n 1</code> 表示每秒刷新一次,能直观看到文件从0→逐渐增大→停止增长(完成)。</li></ul>
<p class="maodian"><a name="_lab2_7_4"></a></p><h3>方法3:查Docker守护进程日志(可选)</h3>
<p>如果怀疑命令卡住,可查看Docker日志(不同系统路径略有差异):</p>
<div class="jb51code"><pre class="brush:bash;"># CentOS/RHEL系统
journalctl -fu docker.service | grep save
# Ubuntu系统
tail -f /var/log/docker.log | grep save
</pre></div>
<ul><li>若有 <code>save</code> 相关的日志输出,能看到打包的进度/错误;若无异常日志,说明命令在正常执行。</li></ul>
<p class="maodian"><a name="_label8"></a></p><h2>三、关于“命令执行完没输出”:必须等打包完成!</h2>
<p><code>docker save</code> 是<strong>阻塞式命令</strong>——执行后会一直运行,直到打包完成(或报错)才会返回终端提示符(比如 <code>#</code>):</p>
<ul><li>终端没有回到提示符 → 还在打包中,千万别中断(Ctrl+C会导致打包失败,tar包损坏);</li><li>终端回到提示符 → 打包完成(无论成功/失败,都会退出)。</li></ul>
<p class="maodian"><a name="_label9"></a></p><h2>四、打包完成/失败的判断</h2>
<p class="maodian"><a name="_lab2_9_5"></a></p><h3>1. 打包成功</h3>
<ul><li>终端回到提示符;</li><li><code>ls -lh</code> 能看到tar包,且大小和镜像大小匹配(比如镜像500MB,tar包大概450~500MB,因为tar会轻微压缩);</li><li>执行 <code>docker load -i 你的tar包名.tar</code> 能正常加载(可选验证,确保包没问题)。</li></ul>
<p class="maodian"><a name="_lab2_9_6"></a></p><h3>2. 打包失败</h3>
<ul><li>终端回到提示符,但tar包大小为0字节/远小于镜像大小;</li><li>终端会输出错误提示(比如 <code>no such image</code>、权限不足、磁盘满等);</li><li>常见失败原因:镜像名写错、磁盘空间不足(执行 <code>df -h</code> 看磁盘使用率)、权限不够(加sudo)。</li></ul>
<p class="maodian"><a name="_label10"></a></p><h2>五、补充:避免打包卡住的小技巧</h2>
<ol><li>先检查磁盘空间:<code>df -h</code> 确保当前目录所在磁盘有足够空间(至少是镜像大小的1.5倍);</li><li>打包时别做高IO操作(比如拷贝大文件、跑其他任务),避免拖慢速度;</li><li>若单个镜像打包太久,可分批打包(比如先打1个,确认耗时后再批量)。</li></ol>
<p>如果等了很久(比如超过10分钟)还没完成,先通过方法1查进程是否还在,再查磁盘IO(<code>iostat -x 1</code>)和Docker日志,大概率是磁盘慢或镜像太大导致的,耐心等即可。</p>
<p>到此这篇关于docker打tar包命令使用小结的文章就介绍到这了,更多相关docker打tar包内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
頁:
[1]