Docker 容器重启策略详解:always / unless-stopped / on-failure 怎么选

服务器重启后容器没跟着起来、容器崩了没人拉、或者反过来——你明明 docker stop 了它却又自己活过来。这三个现象背后都是同一个配置在起作用:重启策略(restart policy)。

很多人图省事一律写 restart: always,结果在"手动停止后宿主机重启,容器又自己跑起来"这种场景踩坑。这篇把四种策略的行为差异讲透,给出一张行为对照表和选型建议。

四种策略

策略含义
no默认值。任何情况都不自动重启
on-failure[:次数]仅当容器非 0 退出码退出时重启,可限制最大重试次数
always无论怎么停的都重启;宿主机/Docker 守护进程重启后也拉起
unless-stopped类似 always,但手动 stop 过的容器,守护进程重启后不再拉起

设置方式:

docker run -d --restart unless-stopped --name app myapp:1.0

# on-failure 限制重试 5 次
docker run -d --restart on-failure:5 --name worker myworker:1.0

Compose:

services:
  app:
    image: myapp:1.0
    restart: unless-stopped

行为对照表(核心)

四种策略在三个关键场景下的表现:

场景noon-failurealwaysunless-stopped
容器崩溃(非 0 退出)不重启重启重启重启
容器正常退出(退出码 0)不重启不重启重启重启
手动 docker stop 后保持停保持停保持停保持停
手动 stop 后宿主机重启保持停保持停自动拉起保持停
未手动 stop,宿主机重启保持停保持停自动拉起自动拉起

always 和 unless-stopped 的唯一区别就在第四行:手动 stop 之后宿主机重启,always 会把容器再拉起来(因为它只认"是否被 stop 过"在 daemon 重启时被重置),unless-stopped 会记住"你手动停过",保持停止。

这个差异在运维时很要命:你为了维护手动 stop 了一个容器,重启服务器后发现它又跑起来了(always),可能干扰维护窗口或抢占端口。用 unless-stopped 就不会。

on-failure 的"正常退出不重启":如果容器以退出码 0 结束(比如一个跑完就退的批处理任务),on-failure 不会重启它——这正是批处理想要的行为。而 always 会把它再拉起来无限循环跑,批处理任务用 always 是灾难。

查看和修改现有容器的策略

查看:

docker inspect <容器名> --format '{{.HostConfig.RestartPolicy.Name}} {{.HostConfig.RestartPolicy.MaximumRetryCount}}'
# 输出如:unless-stopped 0
#        on-failure 5

批量看所有容器:

docker ps -a --format "{{.Names}}\t{{.Status}}" 
for c in $(docker ps -aq); do
  echo -n "$(docker inspect $c --format '{{.Name}} ')";
  docker inspect $c --format '{{.HostConfig.RestartPolicy.Name}}';
done

修改运行中的容器(不用重建):

docker update --restart unless-stopped <容器名>

# 取消自动重启
docker update --restart no <容器名>

docker update 对重启策略立即生效,不用重启容器,运维改策略很方便。

选型建议

长期运行的服务(Web、数据库、中间件) → unless-stopped

理由:崩溃要自动拉起,宿主机重启要自动恢复,但尊重运维的手动停止。这是生产环境最稳妥的默认值。

批处理 / 一次性任务(跑完就退) → no 或 on-failure:N

理由:正常退出(码 0)不该重启。失败时希望重试几次就用 on-failure:3,避免无限重试。绝不要用 always。

容易抖动但希望有限重试的服务 → on-failure:N

理由:限制重试次数,避免 crash loop 把资源耗死或把日志刷爆。超过次数后保持停止,等人介入。

开发 / 测试容器 → no

理由:开发时你经常手动 stop/start,自动重启会干扰调试。

重启的退避机制(backoff)

Docker 对自动重启有指数退避:第一次崩溃后等 100ms 重启,再崩等 200ms、400ms、800ms……最长到 1 分钟。目的是避免 crash loop 瞬间打满 CPU 和日志。

这意味着:容器崩溃后不会立刻复活,docker ps 里可能短暂看到 Restarting 状态:

docker ps
# STATUS: Restarting (1) 10 seconds ago

Restarting (1) 里的 1 是退出码。看到这个状态说明容器在反复崩溃-重启循环,用 docker logs 看崩溃原因,而不是怪重启策略。

容器成功运行 10 秒后,退避计数器重置。所以一个稳定跑了很久再崩的容器,重启会很快(从 100ms 重新开始)。

几个常见误区

误区一:restart 能修复崩溃。不能。重启策略只是"崩了再拉起来",崩溃的根因(配置错、OOM、依赖没就绪)还在。容器反复 Restarting 时先查 docker logs,别指望重启策略兜底。

误区二:on-failure 会对任何停止都重试。只对非 0 退出码。正常退出(0)不重试。想"无论如何都拉起"用 always/unless-stopped。

误区三:docker stop 后策略就失效了。stop 之后容器是 stopped 状态,策略不触发(没在崩)。但宿主机重启后,always 会无视你之前的 stop 把容器拉起,unless-stopped 才不会。这是两者关键差异。

误区四:Compose 的 restart 和 deploy.restart_policy 是一回事。单机 docker compose up 用 restart: 字段;swarm 模式用 deploy.restart_policy。非 swarm 场景写 restart: 就够了,两个都写可能冲突。

与依赖顺序的配合

重启策略只管"单个容器崩了拉起来",不管容器之间的启动顺序。如果 app 依赖 mysql,宿主机重启后两者都被拉起,但 mysql 可能还没就绪 app 就启动连库失败。

配合健康检查依赖(Compose)才能解决顺序问题:

services:
  mysql:
    image: mysql:8.4
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      retries: 10
  app:
    image: myapp:1.0
    restart: unless-stopped
    depends_on:
      mysql:
        condition: service_healthy

这样宿主机重启后,app 会等 mysql 健康检查通过才启动,避免"重启后应用连不上库"的经典问题。重启策略 + 健康检查依赖,两者配合才是完整的自愈方案。

小结

四种策略一句话记:no 不管、on-failure 只管崩、always 永远拉、unless-stopped 永远拉但尊重手动停止。

选型:长期服务用 unless-stopped(生产默认),批处理用 no 或 on-failure:N,开发用 no。查看用 docker inspect 的 RestartPolicy 字段,修改用 docker update --restart 不用重建。

记住两个关键点:always 和 unless-stopped 的区别只在"手动 stop 后宿主机重启"这一场景;重启策略不修复崩溃也不管启动顺序,崩溃循环查日志、顺序问题配健康检查依赖。把这两点搞清楚,重启策略就不再是玄学配置。

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值