使用Docker-java API对容器化操作
- Docker-java 简介
-
- 入门案例介绍
- Docker Remote API
- Docker Remote API 打开后可能存在的隐患(重要)
- Docker客户端与服务端TLS认证(Docker Remote API认证)
- 使用TLS认证案例
Docker-java 简介
Docker-java是一个开源的项目,目前托管在github上,拥有一套完整的API,用以操作docker服务.
github地址:docker-java,
基本入手文档:docker-java入门文档
测试demo需要将代码下载后,在docker-java/docker-java/src/test目录下,可以用于学习
入门案例介绍
``使用Docker-java上传镜像到私有化镜像仓库
Docker Remote API
Docker Remote API 介绍
Docker Remote API 打开后可能存在的隐患(重要)
Docker Remote API 开启后可能导致机器被控制
Docker客户端与服务端TLS认证(Docker Remote API认证)
使用合理的方式开启Docker Remote API,参考此文章讲了部分步骤,但是生成理念是错误的
Docker Remote API,开启TLS认证官方CA证书生成文档
推荐
使用脚本,一键生成CA证书信息,包含服务端,客户端
使用TLS认证案例
导入docker-java 相关maven依赖
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-core</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<version>3.2.7</version>
</dependency>
配置文件
#docker访问路径
docker.url=tcp://${IP}2376
#私服仓库配置
harbor.login_address=${IP}:5000
#私有仓库用户名,如果无,值可以不填写
harbor.username=xxx
#私有仓库密码,如果无,值可以不填写
harbor.password=xxx
#docker client证书地址,如果使用TLS必填
docker.cert.path="/Users/test/.docker"
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold =0
创建docker-java 工具类
package com.persion.docker.utils;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.model.AuthConfig;
import com.github.dockerjava.api.model.Image;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.core.LocalDirectorySSLConfig;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;
import com.github.dockerjava.transport.SSLConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* docker工具类
*/
@Component
public class DockerUtils {
//docker服务器
@Value("${docker.url}")
private String DOCKER_URL;
//私有仓库登录用户名
@Value("${harbor.username}")
private String HARBOR_USERNAME;
//私有仓库登录密码
@Value("${harbor.password}")
private String HARBOR_PASSWORD;
//私有仓库的登录地址
@Value("${harbor.login_address}")
private String HARBOR_LOGIN_ADDRESS;
// CA证书存放位置
@Value("${docker.cert.path}")
private String DOCKER_CERT_PATH;
/**
* 获取docker链接
*
* @return
*/
public DockerClient getDockerClient() {
DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
.withDockerHost(DOCKER_URL)
.withRegistryUsername(HARBOR_USERNAME)
.withRegistryPassword(HARBOR_PASSWORD)
.withRegistryUrl(HARBOR_LOGIN_ADDRESS)
.withDockerTlsVerify(true)
.withDockerCertPath(DOCKER_CERT_PATH)
.build();
// 配置docker客户端连接及证书信息
SSLConfig sslConfig = new LocalDirectorySSLConfig(DOCKER_CERT_PATH);
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
.dockerHost(dockerClientConfig.getDockerHost())
.sslConfig(sslConfig)
.build();
// 目前getInstance方法中,只有此方法被推荐
return DockerClientImpl.getInstance(dockerClientConfig, httpClient);
}
/**
* 参考之前文章《docker---镜像的加载》,镜像如何保存到本地
* 上传镜像
*
* @param file 镜像文件
* @param imageName
* @throws Exception
*/
public void uploadImage(MultipartFile file, String imageName) throws Exception {
DockerClient dockerClient = getDockerClient();
InputStream inputStream = file.getInputStream();
//Harbor登录信息
AuthConfig autoConfig =
new AuthConfig().withRegistryAddress(HARBOR_LOGIN_ADDRESS).
withUsername(HARBOR_USERNAME).withPassword(HARBOR_PASSWORD);
//加载镜像
dockerClient.loadImageCmd(inputStream).exec();
//获取加载镜像的名称
String uploadImageName = "";
String imageFile = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
String imageId = imageFile.substring(imageFile.lastIndexOf("_") + 1);
List<Image> list = dockerClient.listImagesCmd().exec();
for (Image image : list) {
// 压缩包可能包含多个对象,只导入指定镜像
if (image.getId().contains(imageId)) {
uploadImageName = image.getRepoTags()[0];
}
}
// 判断是否有这个需求
//镜像打tag
dockerClient.tagImageCmd(uploadImageName, imageName, imageName.split(":")[2]).exec();
//push至镜像仓库
dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(30, TimeUnit.SECONDS);
//push成功后,删除本地加载的镜像
// 以下这个应该饭在finally中
dockerClient.removeImageCmd(imageName).exec();
dockerClient.removeImageCmd(uploadImageName).exec();
//关闭文件流,这个应该使用try-catch 的try中
if (inputStream != null) {
inputStream.close();
}
}
/**
* 查询镜像信息
*/
public List<Image> listImages() {
return getDockerClient().listImagesCmd().withShowAll(true).exec();
}
}
创建Controller
/*
* Copyright (C) 2021 Baidu, Inc. All Rights Reserved.
*/
package com.persion.docker.web;
import java.io.File;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.github.dockerjava.api.model.Image;
import com.persion.docker.utils.DockerUtils;
@RestController
public class HarborController {
// 私有仓库地址
@Value("${harbor.login_address}")
private String HOST_HOST;
@Autowired
private DockerUtils dockerUtils;
@PostMapping("/uploadImages")
public String uploadImages(String projectName, String imageName, String tag, MultipartFile file) throws Exception {
if (file.isEmpty()) {
return "FILE can't be null!";
}
String imageNames = HOST_HOST + "/" + projectName + "/" + imageName + ":" + tag;
dockerUtils.uploadImage(file, imageNames);
return "SUCCESS";
}
@GetMapping("/list/image")
public List<Image> listImages() throws Exception {
return dockerUtils.listImages();
}
}