1. Docker自动化运维概述

Docker自动化运维是基于Docker容器技术构建的自动化运维平台,具有快速部署、弹性扩展、资源隔离、环境一致性等特点,广泛应用于微服务架构、CI/CD流水线、云原生应用等场景。本文将详细介绍Docker容器化、自动化部署、容器编排、监控告警和运维管理的完整解决方案。

1.1 核心功能

  1. 容器化部署: Docker镜像构建和容器部署
  2. 自动化运维: 自动化部署、扩缩容、故障恢复
  3. 容器编排: Docker Compose和Kubernetes编排
  4. 监控告警: 容器监控和智能告警
  5. 运维管理: 日志管理、配置管理、备份恢复

1.2 技术架构

1
2
3
4
5
应用代码 → Docker镜像 → 容器部署 → 服务编排
↓ ↓ ↓ ↓
版本管理 → 镜像仓库 → 容器运行 → 负载均衡
↓ ↓ ↓ ↓
CI/CD → 自动化部署 → 监控告警 → 运维管理

2. Docker配置

2.1 Docker配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* Docker配置类
*/
@Configuration
public class DockerConfig {

@Value("${docker.host}")
private String dockerHost;

@Value("${docker.registry}")
private String dockerRegistry;

@Value("${docker.namespace}")
private String dockerNamespace;

@Value("${docker.network}")
private String dockerNetwork;

/**
* Docker配置属性
*/
@Bean
public DockerProperties dockerProperties() {
return DockerProperties.builder()
.host(dockerHost)
.registry(dockerRegistry)
.namespace(dockerNamespace)
.network(dockerNetwork)
.build();
}

/**
* Docker客户端
*/
@Bean
public DockerClient dockerClient() {
return DockerClientBuilder.getInstance()
.withDockerHost(dockerHost)
.build();
}

/**
* Docker服务
*/
@Bean
public DockerService dockerService() {
return new DockerService(dockerClient(), dockerProperties());
}

/**
* Docker编排服务
*/
@Bean
public DockerOrchestrationService dockerOrchestrationService() {
return new DockerOrchestrationService(dockerService());
}
}

/**
* Docker配置属性
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerProperties {
private String host;
private String registry;
private String namespace;
private String network;

// 容器配置
private int defaultMemory = 512;
private int defaultCpu = 1;
private int defaultPort = 8080;
private String defaultImage = "openjdk:8-jre-alpine";

// 部署配置
private int maxInstances = 10;
private int minInstances = 1;
private int healthCheckInterval = 30;
private int healthCheckTimeout = 10;

// 监控配置
private boolean enableMetrics = true;
private boolean enableLogging = true;
private String logDriver = "json-file";
private int logMaxSize = 100;
private int logMaxFiles = 3;
}

2.2 应用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# application.yml
docker:
host: unix:///var/run/docker.sock
registry: registry.example.com
namespace: myapp
network: myapp-network

# Docker部署配置
docker:
deployment:
max-instances: 10
min-instances: 1
health-check-interval: 30
health-check-timeout: 10
monitoring:
enable-metrics: true
enable-logging: true
log-driver: json-file
log-max-size: 100
log-max-files: 3

3. Docker服务

3.1 Docker服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
/**
* Docker服务
*/
@Service
public class DockerService {

private final DockerClient dockerClient;
private final DockerProperties properties;

public DockerService(DockerClient dockerClient, DockerProperties properties) {
this.dockerClient = dockerClient;
this.properties = properties;
}

/**
* 构建Docker镜像
* @param buildRequest 构建请求
* @return 构建结果
*/
public DockerBuildResult buildImage(DockerBuildRequest buildRequest) {
try {
// 1. 创建构建上下文
File dockerfile = createDockerfile(buildRequest);
File buildContext = createBuildContext(buildRequest, dockerfile);

// 2. 构建镜像
String imageName = buildRequest.getImageName();
String tag = buildRequest.getTag();
String fullImageName = String.format("%s:%s", imageName, tag);

BuildImageCmd buildCmd = dockerClient.buildImageCmd()
.withDockerfile(dockerfile)
.withBaseDirectory(buildContext)
.withTag(fullImageName);

// 3. 执行构建
BuildImageResultCallback callback = new BuildImageResultCallback() {
@Override
public void onNext(BuildResponseItem item) {
if (item.getStream() != null) {
log.debug("Docker构建日志: {}", item.getStream().trim());
}
}
};

String imageId = buildCmd.exec(callback).awaitImageId();

log.info("Docker镜像构建成功: imageName={}, tag={}, imageId={}",
imageName, tag, imageId);

return DockerBuildResult.success(imageId, fullImageName);

} catch (Exception e) {
log.error("Docker镜像构建失败: imageName={}", buildRequest.getImageName(), e);
return DockerBuildResult.error("镜像构建失败: " + e.getMessage());
}
}

/**
* 推送Docker镜像
* @param imageName 镜像名称
* @param tag 标签
* @return 推送结果
*/
public DockerPushResult pushImage(String imageName, String tag) {
try {
String fullImageName = String.format("%s/%s/%s:%s",
properties.getRegistry(), properties.getNamespace(), imageName, tag);

// 标记镜像
dockerClient.tagImageCmd(imageName + ":" + tag,
properties.getRegistry() + "/" + properties.getNamespace() + "/" + imageName, tag)
.exec();

// 推送镜像
PushImageCmd pushCmd = dockerClient.pushImageCmd(fullImageName);

PushImageResultCallback callback = new PushImageResultCallback() {
@Override
public void onNext(PushResponseItem item) {
if (item.getStatus() != null) {
log.debug("Docker推送日志: {}", item.getStatus());
}
}
};

pushCmd.exec(callback).awaitCompletion();

log.info("Docker镜像推送成功: imageName={}, tag={}", imageName, tag);

return DockerPushResult.success(fullImageName);

} catch (Exception e) {
log.error("Docker镜像推送失败: imageName={}", imageName, e);
return DockerPushResult.error("镜像推送失败: " + e.getMessage());
}
}

/**
* 创建容器
* @param containerRequest 容器请求
* @return 容器信息
*/
public DockerContainer createContainer(DockerContainerRequest containerRequest) {
try {
// 1. 创建容器配置
CreateContainerCmd createCmd = dockerClient.createContainerCmd(containerRequest.getImageName())
.withName(containerRequest.getContainerName())
.withEnv(containerRequest.getEnvironment())
.withExposedPorts(new ExposedPort(containerRequest.getPort()))
.withPortBindings(new PortBinding(
Ports.Binding.bindPort(containerRequest.getHostPort()),
new ExposedPort(containerRequest.getPort())))
.withRestartPolicy(RestartPolicy.unlessStopped())
.withLabels(containerRequest.getLabels());

// 2. 设置资源限制
if (containerRequest.getMemory() > 0) {
createCmd.withMemory(containerRequest.getMemory() * 1024 * 1024);
}

if (containerRequest.getCpu() > 0) {
createCmd.withCpuShares(containerRequest.getCpu() * 1024);
}

// 3. 创建容器
CreateContainerResponse response = createCmd.exec();
String containerId = response.getId();

log.info("Docker容器创建成功: containerName={}, containerId={}",
containerRequest.getContainerName(), containerId);

return DockerContainer.builder()
.containerId(containerId)
.containerName(containerRequest.getContainerName())
.imageName(containerRequest.getImageName())
.status("CREATED")
.createTime(System.currentTimeMillis())
.build();

} catch (Exception e) {
log.error("Docker容器创建失败: containerName={}",
containerRequest.getContainerName(), e);
throw new BusinessException("容器创建失败", e);
}
}

/**
* 启动容器
* @param containerId 容器ID
* @return 启动结果
*/
public boolean startContainer(String containerId) {
try {
dockerClient.startContainerCmd(containerId).exec();

log.info("Docker容器启动成功: containerId={}", containerId);

return true;

} catch (Exception e) {
log.error("Docker容器启动失败: containerId={}", containerId, e);
return false;
}
}

/**
* 停止容器
* @param containerId 容器ID
* @return 停止结果
*/
public boolean stopContainer(String containerId) {
try {
dockerClient.stopContainerCmd(containerId).exec();

log.info("Docker容器停止成功: containerId={}", containerId);

return true;

} catch (Exception e) {
log.error("Docker容器停止失败: containerId={}", containerId, e);
return false;
}
}

/**
* 删除容器
* @param containerId 容器ID
* @return 删除结果
*/
public boolean removeContainer(String containerId) {
try {
dockerClient.removeContainerCmd(containerId).exec();

log.info("Docker容器删除成功: containerId={}", containerId);

return true;

} catch (Exception e) {
log.error("Docker容器删除失败: containerId={}", containerId, e);
return false;
}
}

/**
* 获取容器信息
* @param containerId 容器ID
* @return 容器信息
*/
public DockerContainer getContainer(String containerId) {
try {
InspectContainerResponse response = dockerClient.inspectContainerCmd(containerId).exec();

return DockerContainer.builder()
.containerId(containerId)
.containerName(response.getName())
.imageName(response.getConfig().getImage())
.status(response.getState().getStatus())
.createTime(response.getCreated().getTime())
.build();

} catch (Exception e) {
log.error("获取Docker容器信息失败: containerId={}", containerId, e);
return null;
}
}

/**
* 获取容器列表
* @return 容器列表
*/
public List<DockerContainer> getContainers() {
try {
List<Container> containers = dockerClient.listContainersCmd()
.withShowAll(true)
.exec();

return containers.stream()
.map(container -> DockerContainer.builder()
.containerId(container.getId())
.containerName(container.getNames()[0])
.imageName(container.getImage())
.status(container.getStatus())
.createTime(container.getCreated())
.build())
.collect(Collectors.toList());

} catch (Exception e) {
log.error("获取Docker容器列表失败", e);
return new ArrayList<>();
}
}

/**
* 获取容器日志
* @param containerId 容器ID
* @param lines 日志行数
* @return 容器日志
*/
public String getContainerLogs(String containerId, int lines) {
try {
LogContainerCmd logCmd = dockerClient.logContainerCmd(containerId)
.withStdOut(true)
.withStdErr(true)
.withTail(lines);

StringBuilder logs = new StringBuilder();
LogContainerResultCallback callback = new LogContainerResultCallback() {
@Override
public void onNext(Frame item) {
logs.append(new String(item.getPayload()));
}
};

logCmd.exec(callback).awaitCompletion();

return logs.toString();

} catch (Exception e) {
log.error("获取Docker容器日志失败: containerId={}", containerId, e);
return "";
}
}

/**
* 创建Dockerfile
* @param buildRequest 构建请求
* @return Dockerfile文件
*/
private File createDockerfile(DockerBuildRequest buildRequest) {
try {
File dockerfile = new File("Dockerfile");

StringBuilder content = new StringBuilder();
content.append("FROM ").append(buildRequest.getBaseImage()).append("\n");
content.append("WORKDIR /app\n");
content.append("COPY ").append(buildRequest.getJarPath()).append(" app.jar\n");
content.append("EXPOSE ").append(buildRequest.getPort()).append("\n");
content.append("ENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]\n");

Files.write(dockerfile.toPath(), content.toString().getBytes());

return dockerfile;

} catch (Exception e) {
log.error("创建Dockerfile失败", e);
throw new BusinessException("创建Dockerfile失败", e);
}
}

/**
* 创建构建上下文
* @param buildRequest 构建请求
* @param dockerfile Dockerfile文件
* @return 构建上下文目录
*/
private File createBuildContext(DockerBuildRequest buildRequest, File dockerfile) {
try {
File buildContext = new File("build-context");
buildContext.mkdirs();

// 复制Dockerfile
Files.copy(dockerfile.toPath(),
new File(buildContext, "Dockerfile").toPath());

// 复制JAR文件
File jarFile = new File(buildRequest.getJarPath());
Files.copy(jarFile.toPath(),
new File(buildContext, jarFile.getName()).toPath());

return buildContext;

} catch (Exception e) {
log.error("创建构建上下文失败", e);
throw new BusinessException("创建构建上下文失败", e);
}
}
}

/**
* Docker构建请求
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerBuildRequest {
private String imageName;
private String tag;
private String baseImage;
private String jarPath;
private int port;
private Map<String, String> labels;
}

/**
* Docker构建结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerBuildResult {
private boolean success;
private String imageId;
private String imageName;
private String message;

public static DockerBuildResult success(String imageId, String imageName) {
return DockerBuildResult.builder()
.success(true)
.imageId(imageId)
.imageName(imageName)
.build();
}

public static DockerBuildResult error(String message) {
return DockerBuildResult.builder()
.success(false)
.message(message)
.build();
}
}

/**
* Docker推送结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerPushResult {
private boolean success;
private String imageName;
private String message;

public static DockerPushResult success(String imageName) {
return DockerPushResult.builder()
.success(true)
.imageName(imageName)
.build();
}

public static DockerPushResult error(String message) {
return DockerPushResult.builder()
.success(false)
.message(message)
.build();
}
}

/**
* Docker容器请求
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerContainerRequest {
private String containerName;
private String imageName;
private int port;
private int hostPort;
private int memory;
private int cpu;
private Map<String, String> environment;
private Map<String, String> labels;
}

/**
* Docker容器
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerContainer {
private String containerId;
private String containerName;
private String imageName;
private String status;
private long createTime;
}

4. Docker编排服务

4.1 Docker编排服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/**
* Docker编排服务
*/
@Service
public class DockerOrchestrationService {

private final DockerService dockerService;
private final DockerComposeService dockerComposeService;
private final KubernetesService kubernetesService;

public DockerOrchestrationService(DockerService dockerService,
DockerComposeService dockerComposeService,
KubernetesService kubernetesService) {
this.dockerService = dockerService;
this.dockerComposeService = dockerComposeService;
this.kubernetesService = kubernetesService;
}

/**
* 部署应用
* @param deploymentRequest 部署请求
* @return 部署结果
*/
public DockerDeploymentResult deployApplication(DockerDeploymentRequest deploymentRequest) {
try {
// 1. 构建镜像
DockerBuildRequest buildRequest = DockerBuildRequest.builder()
.imageName(deploymentRequest.getApplicationName())
.tag(deploymentRequest.getVersion())
.baseImage(deploymentRequest.getBaseImage())
.jarPath(deploymentRequest.getJarPath())
.port(deploymentRequest.getPort())
.build();

DockerBuildResult buildResult = dockerService.buildImage(buildRequest);
if (!buildResult.isSuccess()) {
return DockerDeploymentResult.error("镜像构建失败: " + buildResult.getMessage());
}

// 2. 推送镜像
DockerPushResult pushResult = dockerService.pushImage(
deploymentRequest.getApplicationName(), deploymentRequest.getVersion());
if (!pushResult.isSuccess()) {
return DockerDeploymentResult.error("镜像推送失败: " + pushResult.getMessage());
}

// 3. 创建容器
DockerContainerRequest containerRequest = DockerContainerRequest.builder()
.containerName(deploymentRequest.getApplicationName() + "-" + deploymentRequest.getVersion())
.imageName(pushResult.getImageName())
.port(deploymentRequest.getPort())
.hostPort(deploymentRequest.getHostPort())
.memory(deploymentRequest.getMemory())
.cpu(deploymentRequest.getCpu())
.environment(deploymentRequest.getEnvironment())
.labels(deploymentRequest.getLabels())
.build();

DockerContainer container = dockerService.createContainer(containerRequest);

// 4. 启动容器
boolean started = dockerService.startContainer(container.getContainerId());
if (!started) {
return DockerDeploymentResult.error("容器启动失败");
}

log.info("应用部署成功: applicationName={}, version={}, containerId={}",
deploymentRequest.getApplicationName(), deploymentRequest.getVersion(),
container.getContainerId());

return DockerDeploymentResult.success(container);

} catch (Exception e) {
log.error("应用部署失败: applicationName={}",
deploymentRequest.getApplicationName(), e);
return DockerDeploymentResult.error("应用部署失败: " + e.getMessage());
}
}

/**
* 扩缩容应用
* @param applicationName 应用名称
* @param targetInstances 目标实例数
* @return 扩缩容结果
*/
public DockerScalingResult scaleApplication(String applicationName, int targetInstances) {
try {
// 1. 获取当前实例
List<DockerContainer> currentContainers = getApplicationContainers(applicationName);
int currentInstances = currentInstances.size();

if (targetInstances > currentInstances) {
// 扩容
return scaleUp(applicationName, currentInstances, targetInstances);
} else if (targetInstances < currentInstances) {
// 缩容
return scaleDown(applicationName, currentInstances, targetInstances);
} else {
// 无需调整
return DockerScalingResult.success(currentInstances, "实例数无需调整");
}

} catch (Exception e) {
log.error("应用扩缩容失败: applicationName={}", applicationName, e);
return DockerScalingResult.error("扩缩容失败: " + e.getMessage());
}
}

/**
* 扩容应用
* @param applicationName 应用名称
* @param currentInstances 当前实例数
* @param targetInstances 目标实例数
* @return 扩容结果
*/
private DockerScalingResult scaleUp(String applicationName, int currentInstances, int targetInstances) {
try {
int instancesToAdd = targetInstances - currentInstances;

for (int i = 0; i < instancesToAdd; i++) {
// 创建新实例
DockerContainerRequest containerRequest = DockerContainerRequest.builder()
.containerName(applicationName + "-" + System.currentTimeMillis())
.imageName(getLatestImageName(applicationName))
.port(8080)
.hostPort(0) // 随机端口
.memory(512)
.cpu(1)
.build();

DockerContainer container = dockerService.createContainer(containerRequest);
dockerService.startContainer(container.getContainerId());

log.info("扩容实例创建成功: applicationName={}, containerId={}",
applicationName, container.getContainerId());
}

return DockerScalingResult.success(targetInstances,
String.format("扩容成功,新增%d个实例", instancesToAdd));

} catch (Exception e) {
log.error("扩容应用失败: applicationName={}", applicationName, e);
return DockerScalingResult.error("扩容失败: " + e.getMessage());
}
}

/**
* 缩容应用
* @param applicationName 应用名称
* @param currentInstances 当前实例数
* @param targetInstances 目标实例数
* @return 缩容结果
*/
private DockerScalingResult scaleDown(String applicationName, int currentInstances, int targetInstances) {
try {
int instancesToRemove = currentInstances - targetInstances;
List<DockerContainer> containers = getApplicationContainers(applicationName);

// 按创建时间排序,删除最新的实例
containers.sort((c1, c2) -> Long.compare(c2.getCreateTime(), c1.getCreateTime()));

for (int i = 0; i < instancesToRemove && i < containers.size(); i++) {
DockerContainer container = containers.get(i);

// 停止并删除容器
dockerService.stopContainer(container.getContainerId());
dockerService.removeContainer(container.getContainerId());

log.info("缩容实例删除成功: applicationName={}, containerId={}",
applicationName, container.getContainerId());
}

return DockerScalingResult.success(targetInstances,
String.format("缩容成功,删除%d个实例", instancesToRemove));

} catch (Exception e) {
log.error("缩容应用失败: applicationName={}", applicationName, e);
return DockerScalingResult.error("缩容失败: " + e.getMessage());
}
}

/**
* 滚动更新应用
* @param applicationName 应用名称
* @param newVersion 新版本
* @return 更新结果
*/
public DockerUpdateResult rollingUpdate(String applicationName, String newVersion) {
try {
// 1. 获取当前实例
List<DockerContainer> currentContainers = getApplicationContainers(applicationName);
if (currentContainers.isEmpty()) {
return DockerUpdateResult.error("未找到应用实例");
}

// 2. 逐个更新实例
int successCount = 0;
int totalCount = currentContainers.size();

for (DockerContainer container : currentContainers) {
try {
// 停止旧实例
dockerService.stopContainer(container.getContainerId());
dockerService.removeContainer(container.getContainerId());

// 创建新实例
DockerContainerRequest containerRequest = DockerContainerRequest.builder()
.containerName(container.getContainerName())
.imageName(applicationName + ":" + newVersion)
.port(8080)
.hostPort(0)
.memory(512)
.cpu(1)
.build();

DockerContainer newContainer = dockerService.createContainer(containerRequest);
dockerService.startContainer(newContainer.getContainerId());

successCount++;

log.info("实例更新成功: applicationName={}, oldContainerId={}, newContainerId={}",
applicationName, container.getContainerId(), newContainer.getContainerId());

} catch (Exception e) {
log.error("实例更新失败: applicationName={}, containerId={}",
applicationName, container.getContainerId(), e);
}
}

if (successCount == totalCount) {
return DockerUpdateResult.success(totalCount, "滚动更新成功");
} else {
return DockerUpdateResult.partial(successCount, totalCount,
String.format("部分更新成功,成功%d个,失败%d个", successCount, totalCount - successCount));
}

} catch (Exception e) {
log.error("滚动更新失败: applicationName={}", applicationName, e);
return DockerUpdateResult.error("滚动更新失败: " + e.getMessage());
}
}

/**
* 获取应用容器列表
* @param applicationName 应用名称
* @return 容器列表
*/
private List<DockerContainer> getApplicationContainers(String applicationName) {
return dockerService.getContainers().stream()
.filter(container -> container.getContainerName().startsWith(applicationName))
.collect(Collectors.toList());
}

/**
* 获取最新镜像名称
* @param applicationName 应用名称
* @return 镜像名称
*/
private String getLatestImageName(String applicationName) {
// 这里可以实现获取最新镜像的逻辑
return applicationName + ":latest";
}
}

/**
* Docker部署请求
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerDeploymentRequest {
private String applicationName;
private String version;
private String baseImage;
private String jarPath;
private int port;
private int hostPort;
private int memory;
private int cpu;
private Map<String, String> environment;
private Map<String, String> labels;
}

/**
* Docker部署结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerDeploymentResult {
private boolean success;
private DockerContainer container;
private String message;

public static DockerDeploymentResult success(DockerContainer container) {
return DockerDeploymentResult.builder()
.success(true)
.container(container)
.build();
}

public static DockerDeploymentResult error(String message) {
return DockerDeploymentResult.builder()
.success(false)
.message(message)
.build();
}
}

/**
* Docker扩缩容结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerScalingResult {
private boolean success;
private int instances;
private String message;

public static DockerScalingResult success(int instances, String message) {
return DockerScalingResult.builder()
.success(true)
.instances(instances)
.message(message)
.build();
}

public static DockerScalingResult error(String message) {
return DockerScalingResult.builder()
.success(false)
.message(message)
.build();
}
}

/**
* Docker更新结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerUpdateResult {
private boolean success;
private int successCount;
private int totalCount;
private String message;

public static DockerUpdateResult success(int totalCount, String message) {
return DockerUpdateResult.builder()
.success(true)
.successCount(totalCount)
.totalCount(totalCount)
.message(message)
.build();
}

public static DockerUpdateResult partial(int successCount, int totalCount, String message) {
return DockerUpdateResult.builder()
.success(false)
.successCount(successCount)
.totalCount(totalCount)
.message(message)
.build();
}

public static DockerUpdateResult error(String message) {
return DockerUpdateResult.builder()
.success(false)
.message(message)
.build();
}
}

5. Docker监控服务

5.1 Docker监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**
* Docker监控服务
*/
@Service
public class DockerMonitoringService {

private final DockerService dockerService;
private final DockerAlertService alertService;

public DockerMonitoringService(DockerService dockerService, DockerAlertService alertService) {
this.dockerService = dockerService;
this.alertService = alertService;
}

/**
* 监控容器状态
*/
@Scheduled(fixedRate = 30000) // 每30秒执行一次
public void monitorContainerStatus() {
try {
List<DockerContainer> containers = dockerService.getContainers();

for (DockerContainer container : containers) {
// 检查容器状态
if (!"running".equals(container.getStatus())) {
// 发送告警
alertService.sendAlert(DockerAlert.builder()
.type("CONTAINER_DOWN")
.severity("HIGH")
.message(String.format("容器%s状态异常: %s",
container.getContainerName(), container.getStatus()))
.containerId(container.getContainerId())
.timestamp(System.currentTimeMillis())
.build());
}

// 检查容器资源使用情况
checkContainerResources(container);
}

} catch (Exception e) {
log.error("监控容器状态失败", e);
}
}

/**
* 检查容器资源使用情况
* @param container 容器
*/
private void checkContainerResources(DockerContainer container) {
try {
// 获取容器统计信息
DockerContainerStats stats = getContainerStats(container.getContainerId());

if (stats != null) {
// 检查CPU使用率
if (stats.getCpuUsage() > 80) {
alertService.sendAlert(DockerAlert.builder()
.type("HIGH_CPU_USAGE")
.severity("MEDIUM")
.message(String.format("容器%s CPU使用率过高: %.2f%%",
container.getContainerName(), stats.getCpuUsage()))
.containerId(container.getContainerId())
.timestamp(System.currentTimeMillis())
.build());
}

// 检查内存使用率
if (stats.getMemoryUsage() > 80) {
alertService.sendAlert(DockerAlert.builder()
.type("HIGH_MEMORY_USAGE")
.severity("MEDIUM")
.message(String.format("容器%s 内存使用率过高: %.2f%%",
container.getContainerName(), stats.getMemoryUsage()))
.containerId(container.getContainerId())
.timestamp(System.currentTimeMillis())
.build());
}

// 检查磁盘使用率
if (stats.getDiskUsage() > 90) {
alertService.sendAlert(DockerAlert.builder()
.type("HIGH_DISK_USAGE")
.severity("HIGH")
.message(String.format("容器%s 磁盘使用率过高: %.2f%%",
container.getContainerName(), stats.getDiskUsage()))
.containerId(container.getContainerId())
.timestamp(System.currentTimeMillis())
.build());
}
}

} catch (Exception e) {
log.error("检查容器资源使用情况失败: containerId={}",
container.getContainerId(), e);
}
}

/**
* 获取容器统计信息
* @param containerId 容器ID
* @return 统计信息
*/
private DockerContainerStats getContainerStats(String containerId) {
try {
// 这里可以实现获取容器统计信息的逻辑
// 例如:使用Docker API获取容器统计信息

return DockerContainerStats.builder()
.containerId(containerId)
.cpuUsage(50.0)
.memoryUsage(60.0)
.diskUsage(70.0)
.timestamp(System.currentTimeMillis())
.build();

} catch (Exception e) {
log.error("获取容器统计信息失败: containerId={}", containerId, e);
return null;
}
}

/**
* 获取监控指标
* @return 监控指标
*/
public DockerMonitoringMetrics getMonitoringMetrics() {
try {
List<DockerContainer> containers = dockerService.getContainers();

int totalContainers = containers.size();
int runningContainers = (int) containers.stream()
.filter(container -> "running".equals(container.getStatus()))
.count();
int stoppedContainers = totalContainers - runningContainers;

return DockerMonitoringMetrics.builder()
.totalContainers(totalContainers)
.runningContainers(runningContainers)
.stoppedContainers(stoppedContainers)
.timestamp(System.currentTimeMillis())
.build();

} catch (Exception e) {
log.error("获取监控指标失败", e);
return null;
}
}
}

/**
* Docker容器统计
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerContainerStats {
private String containerId;
private double cpuUsage;
private double memoryUsage;
private double diskUsage;
private long timestamp;
}

/**
* Docker监控指标
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerMonitoringMetrics {
private int totalContainers;
private int runningContainers;
private int stoppedContainers;
private long timestamp;
}

/**
* Docker告警
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DockerAlert {
private String type;
private String severity;
private String message;
private String containerId;
private long timestamp;
}

6. Docker控制器

6.1 Docker控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* Docker控制器
*/
@RestController
@RequestMapping("/docker")
public class DockerController {

@Autowired
private DockerService dockerService;

@Autowired
private DockerOrchestrationService orchestrationService;

@Autowired
private DockerMonitoringService monitoringService;

/**
* 构建Docker镜像
*/
@PostMapping("/build")
public ResponseEntity<Map<String, Object>> buildImage(@RequestBody DockerBuildRequest request) {
try {
DockerBuildResult result = dockerService.buildImage(request);

Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("imageId", result.getImageId());
response.put("imageName", result.getImageName());
response.put("message", result.getMessage());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("构建Docker镜像失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "构建镜像失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 部署应用
*/
@PostMapping("/deploy")
public ResponseEntity<Map<String, Object>> deployApplication(@RequestBody DockerDeploymentRequest request) {
try {
DockerDeploymentResult result = orchestrationService.deployApplication(request);

Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("container", result.getContainer());
response.put("message", result.getMessage());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("部署应用失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "部署应用失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 扩缩容应用
*/
@PostMapping("/scale")
public ResponseEntity<Map<String, Object>> scaleApplication(
@RequestParam String applicationName,
@RequestParam int targetInstances) {
try {
DockerScalingResult result = orchestrationService.scaleApplication(applicationName, targetInstances);

Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("instances", result.getInstances());
response.put("message", result.getMessage());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("扩缩容应用失败: applicationName={}", applicationName, e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "扩缩容失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 滚动更新应用
*/
@PostMapping("/update")
public ResponseEntity<Map<String, Object>> rollingUpdate(
@RequestParam String applicationName,
@RequestParam String newVersion) {
try {
DockerUpdateResult result = orchestrationService.rollingUpdate(applicationName, newVersion);

Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("successCount", result.getSuccessCount());
response.put("totalCount", result.getTotalCount());
response.put("message", result.getMessage());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("滚动更新失败: applicationName={}", applicationName, e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "滚动更新失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取容器列表
*/
@GetMapping("/containers")
public ResponseEntity<Map<String, Object>> getContainers() {
try {
List<DockerContainer> containers = dockerService.getContainers();

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("containers", containers);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取容器列表失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取容器列表失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取监控指标
*/
@GetMapping("/metrics")
public ResponseEntity<Map<String, Object>> getMonitoringMetrics() {
try {
DockerMonitoringMetrics metrics = monitoringService.getMonitoringMetrics();

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("metrics", metrics);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取监控指标失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取监控指标失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
}

7. 总结

通过Docker自动化运维的实现,我们成功构建了一个完整的容器化运维平台。关键特性包括:

7.1 核心优势

  1. 容器化部署: Docker镜像构建和容器部署
  2. 自动化运维: 自动化部署、扩缩容、故障恢复
  3. 容器编排: Docker Compose和Kubernetes编排
  4. 监控告警: 容器监控和智能告警
  5. 运维管理: 日志管理、配置管理、备份恢复

7.2 最佳实践

  1. 容器化策略: 合理的容器化设计和镜像管理
  2. 自动化部署: 高效的自动化部署流程
  3. 监控告警: 全面的容器监控和告警机制
  4. 资源管理: 容器资源限制和优化
  5. 运维管理: 完善的运维管理工具

这套Docker自动化运维方案不仅能够提供高效的容器化部署能力,还包含了自动化运维、监控告警、容器编排等核心功能,是现代云原生应用的重要基础设施。