
授权与合规声明本文全部操作对象均为自建隔离靶场本机容器或隔离虚拟机涉及安全测试的环节必须以取得合法授权为前提。未经授权的渗透测试违反《中华人民共和国网络安全法》与《刑法》相关条款须承担相应法律责任。本文只讲环境配置、版本对照与靶场隔离不含任何攻击步骤、利用载荷与绕过手法请勿将文中环境指向任何非自有系统。一、现象三个画面其实是两个问题1.1 画面一昨天还在的靶场今天开机就没了这个画面大概是跑靶场的人最先遇到的昨天你还在浏览器里打开过靶场首页电脑没有重装、镜像也没有删今天开机回来一看容器不见了——不是被删掉而是不在运行状态。你的第一反应通常有两个方向一是我是不是误删了二是是不是 Docker 出问题了。可你去确认一下镜像还在容器记录也还在唯一的变化是它没有被启动起来。于是真正的问题就浮出来了它为什么没有自己起来是它本来就不会自己起来还是我少给了什么东西这个问题有一个明确答案会不会自己起来不是随机的是你在启动它时给的一个选项决定的。本文第二章到第四章就讲这个选项。1.2 画面二容器明明在跑页面就是打不开第二个画面更让人困惑。打开终端一看容器好好地躺在列表里、状态写着运行中可浏览器那个页面就是打不开你把容器重启一下好了过一阵子又不行。它和画面一乍看很像其实是两件不同的事。画面一是进程不在了画面二是进程还在但它要提供的服务已经不正常了。进程还在和服务可用从来不是同一句话。这一点由另一个开关决定本文第五章、第六章专门讲它。1.3 画面三重启一次 Docker有的起来了、有的没起来第三个画面最容易让人怀疑人生你为了换配置重启了一次 Docker回来发现有的容器自己起来了有的还躺着一动不动。同一台机器、看起来差不多的启动方式为什么结果不一样答案还是那句话——不是随机的。你给它们设的选项不一样结果自然不一样。这类结果不同但原因相同的困惑只要把选项读明白一次就能解释清楚。1.4 把两个问题分开三个画面归到两个开关把上面三个画面并排放在一起你会发现它们其实只对应两个问题你看到的现象真正要问的问题由什么决定容器不在了、没有被拉起来进程退出后会不会被自动启动启动它时给的重启策略容器在跑但页面打不开进程在服务是否真的可用有没有配置健康检查、检查结果是什么重启 Docker 后有的起来有的没有同上第一条只是取值不同重启策略的具体取值这张表就是全文的地图。本章可以带走的一句容器不见了先问重启策略容器在跑却打不开先问健康检查。二、第一个开关它会不会自己起来2.1 重启策略是什么Docker 把容器退出时、或 Docker 重启时是否自动启动这件事交给了**重启策略restart policies**来管。这不是第三方的偏方而是 Docker 官方提供、并在官方文档里明确建议使用的一种机制。官方在这一页上有一句逐字的建议「Dockerrecommendsthat you use restart policies, andavoid using process managersto start containers.」这句话的意思是官方建议你使用重启策略而建议避免用进程管理器去启动容器。顺带说清一个边界重启策略管的是要不要把它重新启动它并不负责判断这个容器该不该停。2.2 它不是修复只是拉起这是本文最想先钉住的一点重启策略能做的只是把容器再拉起来它不解决容器为什么会停。一个容器如果因为配置不对、依赖缺失、资源不足之类的原因反复退出你给它设了自动重启结果是它会一次又一次地起来、又一次又一次地退出。表面看它有在自动恢复可真正的毛病一点没动。选了自动重启不等于问题被修好了它只是把停下来了没人管变成了停下来了有人把它再拉一次。所以正确的心态是重启策略是可用性的一层保险不是故障的原因分析工具。它负责让服务尽快回到运行状态至于为什么它会退出仍然要你另外去查。2.3 别和--live-restore混为一谈初学者经常把两个东西混起来一个是重启策略另一个是dockerd的--live-restore标志。它们都跟重启有关但管的事情完全不同。按官方文档--live-restore的作用是让你在 Docker 升级期间保持容器继续运行代价是这期间容器的网络与用户输入会中断。把它们摆在一起看差别就清楚了对比项重启策略restart policy--live-restore管什么容器退出时、或 Docker 重启时是否自动启动在Docker 升级期间让容器继续运行谁在起作用容器这一层的一个选项Docker 守护进程的一个启动标志关键代价无它只是决定起不起来网络与用户输入会中断常见误解“它能修好崩溃的原因”“它等于容器不会因为重启而停”本章可以带走的一句重启策略只决定它起不起来不负责修好它为什么停--live-restore管的是升级期间别把它停掉两者不是一回事。三、四档取值怎么读3.1 一张表看全四档重启策略一共四档取值。它们的差别几乎全部集中在两个场景上一个是你手动把它停了另一个是Docker 守护进程重启了。把这两列看懂四档就全懂了。取值什么时候会重启手动停止后会不会回来Docker 重启daemon 重启后会不会回来no不自动重启容器默认值不会不会on-failure[:max-retries]容器因错误退出表现为非零退出码时可用:max-retries限制 daemon 尝试重启的次数不会不会always容器只要停止就总是重启只在 Docker daemon 重启、或容器本身被手动重启时才重启会unless-stopped与always类似不会被停止后即使 Docker daemon 重启也不再回来只有在此前没被停过的前提下才会表里有两点要单独点出来。第一no是默认值——也就是说你不写这个选项时容器就是不会自己起来的画面一里昨天还在、今天没了的容器多半就是没给这一项。第二on-failure的重启触发条件是因错误退出官方同时明确on-failure只在容器以失败退出时才提示重启daemon 重启不会导致它重启。3.2no与on-failure什么时候不该自动起来no最简单就是不做任何自动启动。它适合那些你就是要它停在那里的场景比如一次性任务、临时排查用的容器。on-failure更细一点。它只在容器因错误退出时才把它拉起来——判断依据是退出码非零。它还可以带一个:max-retries用来限制 daemon 尝试重启的次数。这个上限的意义在于如果容器是坏在一个不会自己好的问题上那么反复重启只是消耗资源设一个上限能让它停在一个可以观察的状态。需要留意的是on-failure不是停了就起。正常退出不是因错误退出的容器它不会管而且它在daemon 重启后也不会重启。3.3always与unless-stopped初学最常踩的那个坑这两档的文档描述非常接近很多人扫一眼就以为它们一样结果就撞上了最典型的困惑——“我明明手动停掉过的容器重启一次 Docker 它自己又回来了。”把官方对两者的说法逐条对照差别只有一处但这一处正是关键always容器只要停止就总是重启若被手动停止则只在 Docker daemon 重启、或容器本身被手动重启时才重启。unless-stopped与always类似区别是——当容器被停止手动或其他方式后即使 Docker daemon 重启也不会重启。把它翻成一句人话always是只要它不在跑我就想办法让它跑起来连你手动停过的也不例外daemon 重启时会一并拉起来“unless-stopped是只要它不在跑我就让它跑起来但你要是亲手停了它我就认你这个决定之后连 daemon 重启也不帮你拉”。所以那句为什么我停过的容器自己回来了答案往往就是它被设成了always。你想要的是我停过就别再回来应该在启动时就选unless-stopped。⚠️ 代码待验证# 启动时就给定重启策略⚠️ 代码待验证本机无 docker 环境未实际运行# 想让手动停掉之后就别再自己回来用 unless-stoppeddockerrun-d--namelab--restartunless-stopped镜像名# 只想让它因错误退出时才被拉起并最多重试若干次dockerrun-d--namelab--restarton-failure:3镜像名# 不写 --restart 时等价于默认的 no它不会自己起来dockerrun-d--namelab镜像名本章可以带走的一句四档的差别基本只在手动停过没有和daemon 重启过没有这两个场景上想我停了就别回来选unless-stopped别选always。四、已经在跑的容器怎么改4.1 不用删了重建docker update前面讲的是启动时给策略。可现实里更常见的是容器已经在跑了我当初没写这个选项现在想补上。这时候你不需要把容器删掉重建Docker 提供了直接改的办法。官方给出的写法是⚠️ 代码待验证# 给一个已经在运行的容器改重启策略⚠️ 代码待验证本机无 docker 环境未实际运行dockerupdate--restartunless-stopped容器名# 改完想确认它当前记的是什么策略可以看这个容器的重启策略字段dockerinspect--format{{.HostConfig.RestartPolicy.Name}}容器名这两条都在容器运行中就能执行不必先停掉它——原有的容器和名字都保留着只是把那一项设置补上。4.2 改之前先想清楚一件事你手动停之后它该不该回来在敲上面那条命令之前先回答一个问题这个靶场容器如果你哪天手动把它停了你希望它下次开机或 Docker 重启时自己回来吗如果你的答案是希望它永远在——比如这是你天天要用的练习环境那always或unless-stopped都行差别只在你手动停过之后的表现。如果你的答案是我停它就是为了让它别再起来——那就一定要选unless-stopped。选always的话你那次手动停止会在下一次 daemon 重启时被撤销。这个判断必须在动手前做因为策略是在你启动或更新的那一刻定下的它不会读你的心思。你事后觉得怎么又起来了多半只是当初那个选项没选对而不是 Docker 擅作主张。4.3 改完别只看它起来了没有最后一层提醒改完策略之后看到容器起来了这只是第一个开关生效了不代表第二个开关也没问题。它可能起来了但里面的服务并没有真正可用——那就轮到第五章的健康检查出场了。本章可以带走的一句本章解决的是当初没设对、现在想补它管不了起来了但服务是坏的。五、第二个开关起来了但它到底能不能用5.1 从容器在跑、页面打不开说起回到第一章的画面二。有人一看容器在跑就认定问题不在容器这一层转头去查别的东西。这里要先立一条容器处于运行状态只说明那个进程还在不等于它提供的服务是正常的。关于容器在跑、端口和地址却对不上这一类排查那是另一篇文章的范围本文不重写那套从镜像到地址的排查流程。本文要补的是一个新的维度容器自己知不知道我还能不能干活这个维度就叫健康状态它由健康检查决定。5.2HEALTHCHECK的两种形式在 Dockerfile 里这个开关叫HEALTHCHECK。官方给了两种形式HEALTHCHECK [OPTIONS] CMD command—— 在容器内运行一条命令来检查健康状况HEALTHCHECK NONE——禁用从基础镜像继承来的任何健康检查。第二种形式存在本身就说明了一件事健康检查是会继承的。你用的基础镜像如果自己带了健康检查它会跟着继承下来如果你不想要它就显式写HEALTHCHECK NONE关掉。5.3 它能检出进程还在、但已经不正常这种情况HEALTHCHECK要回答的问题是这个容器是不是还在正常工作官方给了一个很典型的例子来说明它能覆盖到什么程度它能检出web 服务器陷入死循环、无法处理新连接但服务器进程仍在运行这种情况。这句话值得反复读进程仍在运行可它已经接不了新连接了。这正是第一个开关永远做不到的事——重启策略只认进程的生死它看不见进程活着但服务瘫了。⚠️ 代码待验证# Dockerfile 片段⚠️ 代码待验证本机无 docker 环境未实际构建验证# 形式一在容器内运行一条命令来检查健康HEALTHCHECK--interval30s--timeout30s--retries3\CMDcurl-fhttp://localhost/||exit1# 形式二禁用从基础镜像继承来的任何健康检查HEALTHCHECK NONE5.4 三个状态starting、healthy、unhealthy配置了健康检查的容器除了正常之外还多了一个健康状态。官方对这三个状态的描述是初始状态是starting每当一次健康检查通过它就变为healthy无论此前是什么状态连续失败达到一定次数后变为unhealthy。健康状态含义什么时候切进来starting初始状态还在观察容器刚起来、检查还没通过时healthy检查通过了只要有一次检查通过就从任何状态切过来unhealthy连续失败达到次数连续失败累积到阈值之后这张表里有一个容易被忽略的细节从任何状态切到healthy只需要一次检查通过。也就是说unhealthy不是判了死刑——后面只要有一次检查过了它立刻回到healthy。本章可以带走的一句容器在跑不等于服务可用unhealthy也不是死刑一次通过就回到healthy。完整版环境对照表这份对照表把 Docker 容器的启动状态、健康状态与对应的排查入口整理在一起正好和本章的三个状态互为参照。放在资料包里扫码即可获取六、健康检查的五个旋钮与默认值6.1 五个选项和它们的默认值HEALTHCHECK在CMD之前可以带几个选项每一个都有一个官方给定的默认值。把它们列成一张表最清楚选项默认值它管什么--intervalDURATION30s两次检查之间隔多久--timeoutDURATION30s单次检查最多允许跑多久--start-periodDURATION0s给容器启动预留的观察期--start-intervalDURATION5s观察期内的检查频率--retriesN3连续失败几次才判unhealthy看这张表时有一个习惯要养成默认值是default不是建议值。官方给的是缺省设定具体调成多少取决于你这个服务启动有多慢、单次检查有多重。⚠️ 代码待验证# 把五个旋钮一次写全的样子⚠️ 代码待验证本机无 docker 环境未实际构建验证HEALTHCHECK--interval30s--timeout30s --start-period0s\--start-interval5s--retries3CMD检查命令6.2 时序第一次检查什么时候做这五个值不是各自孤立的官方给了一条明确的时序容器启动后先等 interval 秒才运行第一次检查之后在每一次上一次检查完成之后再等 interval 秒运行下一次。而在start period 期间检查是按start interval的频率在跑。这里有两层容易读错的地方。第一第一次检查不是立刻而是先等一个 interval——默认就是先等三十秒。第二start period 期间用的是另一套频率--start-interval所以它不是什么都不查而是用更密的节奏查但结果按下文的口径处理。6.3 超时判失败以及检查进程会被 SIGKILL单次检查如果运行超过了 timeout 秒这一次检查就算失败。官方对超时的处理有一句很具体的话执行检查的进程会被 SIGKILL 突然停止。这里只照抄官方这个事实不多展开——关于信号本身、前台进程与中断的处理那是另一篇文章的范围。你只需要记住timeout 是一个硬上限超了就按失败算并且那条检查命令会被强制结束。6.4 连续失败几次才算retries与 start period 的关系--retries决定的是要连续失败多少次才判定unhealthy——官方口径是需要 retries 次连续失败。默认3也就是连续三次都没过才判它不健康。start period 的作用是给需要时间引导的容器留出初始化时间它和 retries 的配合有一处特别值得记在 start period 期间检查失败是不计入最大重试次数的但如果在这个期间有一次检查成功容器就被视为已启动此后所有的连续失败都会被计入。第二条是很多人忽略的只要你观察期内成功过一次之后就不再豁免了。所以别把 start period 理解成一个永远宽容的缓冲期——它是给启动慢的容器留的时间一旦确认启动完成就按正常规则算账。6.5 三条容易踩的边界最后补三条边界都是官方明说的一个 Dockerfile 里只能有一条HEALTHCHECK指令如果你写了多条只有最后一条生效。--start-interval需要 Docker Engine 25.0 或更高版本截至 2026-10-06用不了这一项的环境就只能按固定的间隔走。检查命令的退出状态是有含义的0 success容器健康、可用1 unhealthy容器工作不正常2 reserved官方明确不要用这个退出码。第三条尤其要小心2是官方留作保留的不要拿它当另一种失败来用。写检查脚本时让它在正常时返回0、不正常时返回1就够了。本章可以带走的一句五个旋钮各有默认值30s / 30s / 0s / 5s / 3第一次检查是先等一个 interval退出码只用0和12不要用。七、跑靶场两个开关怎么配合7.1 一套给靶场场景的选择把前面几章落回跑靶场这个具体场景两个开关可以这样配你的诉求第一个开关重启策略怎么选第二个开关健康检查要不要配天天用的靶场希望它一直在unless-stopped我手动停过就别回来或always建议配能发现进程在但页面打不开一次性任务、临时排查用的容器no默认不起就起不来一般不必配只在它因错误退出时才想拉起on-failure并可带:max-retries视情况配容器已在运行当初没设用docker update --restart补上需改 Dockerfile 重新构建镜像改运行中容器不生效一句话概括这套配合重启策略负责让它待在运行状态健康检查负责告诉你它到底能不能干活。两者是先后关系不是替代关系——配了健康检查也不能反过来替你把没起来的容器拉起来。7.2 本文不涉及的两块有两块内容本文刻意没有展开写清楚是为了不让你误以为没写就是没有compose 那一层本文未核此处不展开。本文只核到docker run --restart与docker update --restart这两种用法至于它在 compose 文件里对应怎么写属于另一层规范、本次未核不做推断。各平台的 Docker Engine 版本对照本文未核。关于--start-interval本文只能照抄官方的口径——需要 Docker Engine 25.0 或更高版本至于各个平台发行版分别对应哪个版本本次没有核对不做对照表。把这两条边界说清楚比含含糊糊地大概是这样要可靠。凡是本次没有核到的就写未核这是本文留下的一条可回溯线索。7.3 收束它只是让容器起来不解决为什么停回到标题。容器停了不会自己起来是因为默认的重启策略就是no你不在启动时给它一个选项它就不会自作主张。想让它在退出或 Docker 重启后回来就给对那一档取值想让你手动停掉的容器别再回来就选unless-stopped。但请把最后这句话记住重启策略只是让容器起来它不解决为什么停。它把停止之后没人管变成了停止之后自动再拉一次至于那个让容器反复退出、或者让服务卡死不响应新连接的原因仍然要你另外去查。健康检查也只是把进程还在但服务已经不正常这件事显式地报出来它同样不负责修好它。两个开关的正确用法是让它们各自守住自己的边界重启策略守住起不起来健康检查守住能不能用剩下为什么出问题交给专门的排查。分开之后你的靶场环境就稳了。完整版环境对照表这套两个开关的配合选择连同重启策略四档对照、健康检查五旋钮默认值一起收进资料包扫码即可获取本章可以带走的一句重启策略只负责让它起来、健康检查只负责报出它能不能用两者都不解决为什么会停。附表 A本文引用事实与官方出处对照表#事实陈述一手出处核验日期本文位置R01Docker 提供重启策略控制容器退出时、或 Docker 重启时是否自动启动官方逐字「Dockerrecommendsthat you use restart policies, andavoid using process managersto start containers.」Docker 官方文档 · start-containers-automatically2026-10-06第二、七章R02重启策略与dockerd的--live-restore不同后者可在Docker 升级期间保持容器继续运行但网络与用户输入会中断同 R012026-10-06第二章R03--restart四档no不自动重启默认值on-failure[:max-retries]因错误退出、非零退出码时重启:max-retries限制 daemon 尝试次数且 daemon 重启不会导致重启always停止就总是重启被手动停止后只在 daemon 重启或容器被手动重启时才重启unless-stopped与 always 类似被停止后即使 daemon 重启也不重启同 R012026-10-06第三章R04已在运行的容器也可改策略docker update --restart unless-stopped 容器名同 R012026-10-06第四章R05HEALTHCHECK两种形式HEALTHCHECK [OPTIONS] CMD command与HEALTHCHECK NONE禁用从基础镜像继承的任何 healthcheckDockerfile 参考页2026-10-06第五章R06HEALTHCHECK告诉 Docker 如何测试容器是否仍在工作官方说明它能检出web 服务器陷入死循环、无法处理新连接但服务器进程仍在运行同 R052026-10-06第五章R07指定了 healthcheck 的容器除正常状态外还有健康状态初始为starting每次检查通过变为healthy连续失败一定次数后变为unhealthy同 R052026-10-06第五章R08选项与默认值--interval30s、--timeout30s、--start-period0s、--start-interval5s、--retries3同 R052026-10-06第六章R09时序启动后先等 interval 才第一次检查之后每次上一次完成后再 interval 一次start period 期间按 start interval 的频率运行同 R052026-10-06第六章R10单次检查超过 timeout 即视为失败执行检查的进程被SIGKILL突然停止同 R052026-10-06第六章R11需要retries 次连续失败才判unhealthystart period 期间失败不计入但该期间若有一次成功此后所有连续失败都会计入同 R052026-10-06第六章R12--start-interval需要Docker Engine 25.0 或更高版本截至 2026-10-06同 R052026-10-06第六章R13一个 Dockerfile 里只能有一条HEALTHCHECK写多条只有最后一条生效同 R052026-10-06第六章R14检查命令退出状态0 success、1 unhealthy、2 reserved不要用同 R052026-10-06第六章待验证 BX06--restart与compose 文件restart:字段的对应关系本次未核本文不展开未核2026-10-06第七章待验证待验证 BX07各平台 Docker Engine 版本与--start-interval支持情况的对照本次未核本文只照抄 R12未核2026-10-06第七章待验证附表 B术语速查表术语一句话解释重启策略restart policy决定容器退出时、或 Docker 重启时是否自动启动的选项docker run --restart指定no重启策略默认值不自动重启容器on-failure仅在容器**因错误退出非零退出码**时重启daemon 重启不会触发它always只要停止就总是重启被手动停止后只在 daemon 重启或容器被手动重启时才回来unless-stopped与always类似区别是被停止后即使 daemon 重启也不回来--live-restoredockerd的启动标志可在Docker 升级期间保持容器运行但网络与用户输入会中断健康检查HEALTHCHECK在 Dockerfile 里定义如何测试容器是否仍在工作的指令两种形式CMD与NONEstarting/healthy/unhealthy配置健康检查后容器的健康状态一次检查通过即变为healthy连续失败达阈值变为unhealthy--interval/--timeout检查间隔与单次检查的超时上限默认都是30s--start-period/--start-interval启动观察期与其内的检查频率默认0s与5s后者需要 Docker Engine 25.0 或更高截至 2026-10-06--retries连续失败多少次才判unhealthy默认3SIGKILL单次检查超过 timeout 时官方说明执行检查的进程被突然停止所对应的信号本文不展开信号体系代码待验证 / 待验证两类标记前者指该命令未在本机实际运行后者指该项未核到官方口径本文不做结论写在最后这篇用到的资料写这篇文章时我把容器昨天还在、今天没了和容器在跑、页面打不开这两个画面并排放在一起看了很久最后确认它们其实是两个开关一个管它起不起来一个管它能不能用顺手也整理了几份配套的东西靶场环境对照表DVWA、upload-labs 在 Windows / macOS / Linux 三平台的可行性与推荐路径Web 安全学习路线图从基础打牢到安全管理四个阶段各学什么常用靶场清单每个靶场练什么、适合哪个阶段资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「靶场」优先通过。拿到之后建议先看环境对照表那一份再回头把本文的四档取值表和五旋钮默认值表对照着过一遍下次容器没自己起来就知道该先去看哪一个开关。