docker-java没有标准的文档,网上资料也零零散散,而且网上2.8版本和我使用的3.3版本有了不少变化,因此贴一点我使用的示例以供参考。
maven依赖:
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.30.1</version>
</dependency>
docker示例:
package cn.mx.docker.impl;
import cn.mx.common.utils.StringUtils;
import cn.mx.docker.DockerApiService;
import cn.mx.docker.vo.DockerContainerVO;
import cn.mx.docker.vo.LabelsOrKvVO;
import cn.mx.modules.resourcePool.handler.ResourcePoolSocketHandler;
import cn.mx.services.common.exceptions.CsbitException;
import com.alibaba.fastjson.JSONArray;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerCmd;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.LogContainerCmd;
import com.github.dockerjava.api.model.BlkioStatEntry;
import com.github.dockerjava.api.model.BlkioStatsConfig;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.CpuStatsConfig;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.api.model.Image;
import com.github.dockerjava.api.model.Info;
import com.github.dockerjava.api.model.MemoryStatsConfig;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.StatisticNetworksConfig;
import com.github.dockerjava.api.model.Statistics;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.core.InvocationBuilder;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
public class DockerApiServiceImpl {
private final static Logger log = LoggerFactory.getLogger(DockerApiServiceImpl.class);
public DockerClient createClient(String ip, Integer port) {
String url = "tcp://" + ip + ":" + port;
return DockerClientBuilder.getInstance(url).build();
}
public boolean testClientConn(String ip, Integer port) {
DockerClient client = createClient(ip, port);
Info exec = null;
try {
exec = client.infoCmd().exec();
} catch (Exception e) {
log.error("docker测试连接失败,ip为:{},端口为:{},失败原因为:{}", ip, port, e.getMessage());
return false;
}
String serverVersion = exec.getServerVersion();
if (!StringUtils.isEmpty(serverVersion)) {
return true;
}
return false;
}
public String localImageToRemote(String localImagePath, String remoteIp, Integer remotePort) {
String imageId = "";
File file = new File(localImagePath);
if (!file.exists()) {
log.error("推送本地镜像到宿主机失败,本地镜像路径为:{},失败原因为该路径的镜像文件不存在", localImagePath);
return null;
}
try {
FileInputStream is = new FileInputStream(file);
// 获取该镜像的id
TarArchiveInputStream tin = new TarArchiveInputStream(is);
TarArchiveEntry entry = tin.getNextTarEntry();
String json = null;
while (entry != null) {
// 只读取manifest.json
if (entry.getName().equals("manifest.json")) {
ByteArrayOutputStream result = new ByteArrayOutputStream();
int count;
byte[] data = new byte[1024];
while ((count = tin.read(data, 0, 1024)) != -1) {
result.write(data, 0, count);
}
result.close();
json = result.toString();
break;
}
entry = tin.getNextTarEntry();
}
// 不存在就直接返回失败
if (json == null) {
log.error("加载镜像到宿主机,镜像包中没有manifest.json文件,无法解析出镜像id,因此失败");
return null;
}
imageId = JSONArray.parseArray(json).getJSONObject(0).getString("Config").replace(".json", "");
// 关闭资源
is.close();
// 获取宿主机存在的镜像,如果已经存在则不再重新加载
DockerClient docker = createClient(remoteIp, remotePort);
List<Image> images = docker.listImagesCmd().exec();
boolean isAlreadyExit = false;
for (Image image : images) {
// sha256:xxxxxxx
if (image.getId().split(":")[1].equals(imageId)) {
isAlreadyExit = true;
break;
}
}
if (!isAlreadyExit) {
FileInputStream fis = new FileInputStream(file);
// 加载镜像
docker.loadImageCmd(fis).exec();
fis.close();
}
docker.close();
} catch (Exception e) {
return null;
}
return imageId;
}
public String imageInfo(String imageId) {
return null;
}
public List<Container> listContainer(Boolean showAll) {
return null;
}
public List<String> logContainer(String remoteIp, Integer remotePort, String containerId) {
List<String> logs = new ArrayList<>();
DockerClient docker = createClient(remoteIp, remotePort);
LogContainerCmd logContainerCmd = docker.logContainerCmd(containerId)
.withStdOut(true)
.withFollowStream(true) // 实时获取日志
// .withTailAll() // 获取所有日志
.withStdErr(true);
InvocationBuilder.AsyncResultCallback<Frame> callback = new InvocationBuilder.AsyncResultCallback<Frame>() {
@Override
public void onNext(Frame object) {
if (ResourcePoolSocketHandler.SESSIONS.get(containerId) == null || !ResourcePoolSocketHandler.SESSIONS.get(containerId).isOpen()) {
logContainerCmd.close();
try {
docker.close();
} catch (IOException e) {
log.error("关闭docker客户端失败,失败原因:{}", e.getMessage());
}
return;
}
// 实时通过webSocket传递日志
ResourcePoolSocketHandler.sendMessage(containerId, object.toString());
logs.add(object.toString());
}
};
try {
logContainerCmd.exec(callback).awaitCompletion();
} catch (InterruptedException e) {
log.error("docker获取容器日志失败,失败原因:{}", e.getMessage());
}
return logs;
}
public String containerInfo(String containerId) {
return null;
}
public Boolean removeContainer(String remoteIp, Integer remotePort, String containerId) {
try {
DockerClient docker = createClient(remoteIp, remotePort);
docker.removeContainerCmd(containerId).exec();
return true;
} catch (Exception e) {
log.error("删除容器失败,远程服务器ip为:{},端口为:{},容器ID为:{},失败原因:{}", remoteIp, remotePort, containerId, e.getMessage());
return false;
}
}
public Boolean stopContainer(String remoteIp, Integer remotePort, String containerId) {
try {
DockerClient docker = createClient(remoteIp, remotePort);
docker.stopContainerCmd(containerId).exec();
return true;
} catch (Exception e) {
log.error("停止容器失败,远程服务器ip为:{},端口为:{},容器ID为:{},失败原因:{}", remoteIp, remotePort, containerId, e.getMessage());
return false;
}
}
public Boolean startContainer(String remoteIp, Integer remotePort, String containerId) {
try {
DockerClient docker = createClient(remoteIp, remotePort);
docker.startContainerCmd(containerId).exec();
return true;
} catch (Exception e) {
log.error("开启容器失败,远程服务器ip为:{},端口为:{},容器ID为:{},失败原因:{}", remoteIp, remotePort, containerId, e.getMessage());
return false;
}
}
public String createContainer(DockerContainerVO dockerContainerVO) {
CreateContainerResponse response = null;
try {
DockerClient docker = createClient(dockerContainerVO.getRemoteIp(), dockerContainerVO.getRemotePort());
Ports portBinding = new Ports();
if (dockerContainerVO.getExposePorts() != null) {
for (LabelsOrKvVO exposePort : dockerContainerVO.getExposePorts()) {
portBinding.bind(ExposedPort.tcp(Integer.parseInt(exposePort.getKey())), Ports.Binding.bindPort(Integer.parseInt(exposePort.getValue())));
}
}
CreateContainerCmd containerCmd = docker.createContainerCmd(dockerContainerVO.getImageId());
containerCmd.withImage(dockerContainerVO.getImageId())
.withName(dockerContainerVO.getContainerName());
if (portBinding.getBindings() != null && !portBinding.getBindings().isEmpty()) {
// 映射端口需要先将端口暴露出来再映射
containerCmd.withExposedPorts(new ArrayList<>(portBinding.getBindings().keySet()));
containerCmd.withPortBindings(portBinding);
}
// 同步宿主机的时间到容器
containerCmd.withEnv("TZ=Asia/Shanghai");
if (StringUtils.isNotEmpty(dockerContainerVO.getCmd())) {
containerCmd.withCmd(dockerContainerVO.getCmd());
}
// 限制容器使用的cpu核心数
if (StringUtils.isNotEmpty(dockerContainerVO.getCpus())) {
containerCmd.withCpusetCpus(dockerContainerVO.getCpus());
}
// 限制容器使用的内存-默认单位字节,太难输,升级到MB
if (dockerContainerVO.getMemory() != null && dockerContainerVO.getMemory() > 0) {
containerCmd.withMemory(dockerContainerVO.getMemory() * 1024 * 1024);
}
response = containerCmd.exec();
} catch (Exception e) {
throw new CsbitException("创建容器失败,失败原因:" + e.getMessage());
}
if (StringUtils.isNotEmpty(response.getId())) {
return response.getId();
} else {
throw new CsbitException("创建容器失败,失败原因:" + Arrays.toString(response.getWarnings()));
}
}
public Boolean restartContainer(String remoteIp, Integer remotePort, String containerId) {
try {
DockerClient docker = createClient(remoteIp, remotePort);
docker.restartContainerCmd(containerId).exec();
return true;
} catch (Exception e) {
log.error("重启容器失败,远程服务器ip为:{},端口为:{},容器ID为:{},失败原因:{}", remoteIp, remotePort, containerId, e.getMessage());
return false;
}
}
public Map<String, String> getContainerResourceInfo(String remoteIp, Integer remotePort, String containerId) {
DockerClient docker = createClient(remoteIp, remotePort);
Map<String, String> map = new HashMap<>();
InvocationBuilder.AsyncResultCallback<Statistics> callback = new InvocationBuilder.AsyncResultCallback<Statistics>() {
@Override
public void onNext(Statistics object) {
CpuStatsConfig cpu = object.getCpuStats();
CpuStatsConfig preCpu = object.getPreCpuStats();
Long num1 = cpu.getCpuUsage().getTotalUsage() - preCpu.getCpuUsage().getTotalUsage();
Long num2 = cpu.getSystemCpuUsage() - preCpu.getSystemCpuUsage();
double cpuu = new BigDecimal(num1)
.multiply(new BigDecimal(cpu.getCpuUsage().getPercpuUsage().size() * 100))
.divide(new BigDecimal(num2), 2, RoundingMode.HALF_UP).doubleValue();
map.put("cpu", cpuu + "%");
MemoryStatsConfig memoryStatsConfig = object.getMemoryStats();
double mem = new BigDecimal(memoryStatsConfig.getUsage()).multiply(new BigDecimal(100))
.divide(new BigDecimal(memoryStatsConfig.getLimit()), 2, RoundingMode.HALF_UP).doubleValue();
map.put("memory", mem + "%");
Map<String, StatisticNetworksConfig> networks = object.getNetworks();
networks.forEach(new BiConsumer<String, StatisticNetworksConfig>() {
@Override
public void accept(String s, StatisticNetworksConfig statisticNetworksConfig) {
String networkI = "";
String networkO = "";
if (statisticNetworksConfig.getRxBytes() > 1024) {
networkI = (statisticNetworksConfig.getRxBytes() / 1024) + "KB";
} else {
networkI = statisticNetworksConfig.getRxBytes() + "B";
}
if (statisticNetworksConfig.getTxBytes() > 1024) {
networkO = (statisticNetworksConfig.getTxBytes() / 1024) + "KB";
} else {
networkO = statisticNetworksConfig.getTxBytes() + "B";
}
map.put("networks", networkI + "-" + networkO);
}
});
BlkioStatsConfig blkioStats = object.getBlkioStats();
Long sumDiskI = 0L;
Long sumDiskO = 0L;
for (BlkioStatEntry blkioStatEntry : blkioStats.getIoServiceBytesRecursive()) {
if (blkioStatEntry.getOp().equals("Read")) {
sumDiskI += blkioStatEntry.getValue();
} else if (blkioStatEntry.getOp().equals("Write")) {
sumDiskO += blkioStatEntry.getValue();
}
}
String diskI = "";
String diskO = "";
if (sumDiskI > 1024) {
diskI = (sumDiskI / 1024) + "KB";
} else {
diskI = sumDiskI + "B";
}
if (sumDiskO > 1024) {
diskO = (sumDiskO / 1024) + "KB";
} else {
diskO = sumDiskO + "B";
}
map.put("diskIO", diskI + "-" + diskO);
}
};
docker.statsCmd(containerId).withNoStream(true).exec(callback).awaitResult();
try {
docker.close();
} catch (IOException e) {
log.error("docker容器关闭失败,失败原因:{}", e.getMessage());
}
return map;
}
public List<Image> getImageListInfo(String remoteIp, Integer remotePort) {
DockerClient docker = createClient(remoteIp, remotePort);
List<Image> images = docker.listImagesCmd().exec();
try {
docker.close();
} catch (IOException e) {
log.error("关闭docker连接失败,失败原因:{}", e.getMessage());
}
return images;
}
public static void main(String[] args) {
createContainerTest();
}
private static void loadImage() {
try {
File file = new File("D:\\xxx.tar");
FileInputStream fis = new FileInputStream(file);
// 加载镜像
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
docker.loadImageCmd(fis).exec();
fis.close();
FileInputStream is = new FileInputStream(file);
// 获取该镜像的id
TarArchiveInputStream tin = new TarArchiveInputStream(is);
TarArchiveEntry entry = tin.getNextTarEntry();
String json = null;
while (entry != null) {
// 只读取manifest.json
if (entry.getName().equals("manifest.json")) {
ByteArrayOutputStream result = new ByteArrayOutputStream();
int count;
byte[] data = new byte[1024];
while ((count = tin.read(data, 0, 1024)) != -1) {
result.write(data, 0, count);
}
result.close();
json = result.toString();
break;
}
entry = tin.getNextTarEntry();
}
// 不存在就直接返回失败
if (json == null) {
log.error("加载镜像到宿主机,镜像包中没有manifest.json文件,无法解析出镜像id,因此失败");
}
String imageId = JSONArray.parseArray(json).getJSONObject(0).getString("Config").replace(".json", "");
System.out.println(imageId);
// 关闭资源
is.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void startContainerTest() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
docker.startContainerCmd("containerID").exec();
}
private static void deleteContainerTest() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
docker.removeContainerCmd("containerID").exec();
}
private static void containerInfo() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
System.out.println(111);
InvocationBuilder.AsyncResultCallback<Statistics> callback = new InvocationBuilder.AsyncResultCallback<Statistics>() {
@Override
public void onNext(Statistics object) {
CpuStatsConfig cpu = object.getCpuStats();
CpuStatsConfig preCpu = object.getPreCpuStats();
Long num1 = cpu.getCpuUsage().getTotalUsage() - preCpu.getCpuUsage().getTotalUsage();
Long num2 = cpu.getSystemCpuUsage() - preCpu.getSystemCpuUsage();
double cpuu = new BigDecimal(num1)
.multiply(new BigDecimal(cpu.getCpuUsage().getPercpuUsage().size() * 100))
.divide(new BigDecimal(num2), 2, RoundingMode.HALF_UP).doubleValue();
MemoryStatsConfig memoryStatsConfig = object.getMemoryStats();
double mem = new BigDecimal(memoryStatsConfig.getUsage()).multiply(new BigDecimal(100))
.divide(new BigDecimal(memoryStatsConfig.getLimit()), 2, RoundingMode.HALF_UP).doubleValue();
// Integer mem = Math.round((memoryStatsConfig.getUsage() * 100 / memoryStatsConfig.getLimit()) * 100);
Map<String, StatisticNetworksConfig> networks = object.getNetworks();
networks.forEach(new BiConsumer<String, StatisticNetworksConfig>() {
@Override
public void accept(String s, StatisticNetworksConfig statisticNetworksConfig) {
System.out.println(s + ":");
System.out.println(statisticNetworksConfig.getRxBytes() + "-" + statisticNetworksConfig.getTxBytes() + "\n");
}
});
BlkioStatsConfig blkioStats = object.getBlkioStats();
Long sumDiskI = 0L;
Long sumDiskO = 0L;
for (BlkioStatEntry blkioStatEntry : blkioStats.getIoServiceBytesRecursive()) {
if (blkioStatEntry.getOp().equals("Read")) {
sumDiskI += blkioStatEntry.getValue();
} else if (blkioStatEntry.getOp().equals("Write")) {
sumDiskO += blkioStatEntry.getValue();
}
}
System.out.println("sumDiskI:" + sumDiskI);
System.out.println("sumDiskO:" + sumDiskO);
}
};
docker.statsCmd("containerID").withNoStream(true).exec(callback).awaitResult();
System.out.println("容器资源获取完成");
}
private static void createContainerTest() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
// List<PortBinding> ports = new ArrayList<>();
// ports.add(PortBinding.parse("443:8443"));
// HostConfig hostConfig = HostConfig.newHostConfig();
// hostConfig.withPortBindings(ports);
Ports portBinding = new Ports();
portBinding.bind(ExposedPort.tcp(443), Ports.Binding.bindPort(8443));
portBinding.bind(ExposedPort.tcp(990), Ports.Binding.bindPort(9090));
CreateContainerResponse response = docker.createContainerCmd("imageID")
.withImage("imageID")
.withName("containerName")
.withExposedPorts(ExposedPort.tcp(443), ExposedPort.tcp(990))
.withPortBindings(portBinding)
// .withCmd("--cpus", "1",
//// "--storage-opt", "size=50G",
// "--memory", "3G")
.withCmd("/usr/sbin/init") // docker save的命令
.withCpusetCpus("1")
.withMemory(1024 * 1024 * 1024 * 3L)
// .withAuthConfig(authConfig)
.exec();
System.out.println("创建容器完成!");
System.out.println(response.getId());
System.out.println(Arrays.toString(response.getWarnings()));
}
private static void listImages() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
// List<SearchItem> items = docker.searchImagesCmd("9115afd2b62be67406aaaf856faa64600733421717618fb3c77d24d52d382f16").exec();
// for (SearchItem item : items) {
// System.out.println("item:" + item.getName());
// }
List<Image> images = docker.listImagesCmd().exec();
for (Image image : images) {
System.out.println("created:" + image.getCreated());
System.out.println("size:" + image.getSize());
if (image.getId().split(":")[1].equals("imageID")) {
System.out.println("镜像已经上传");
}
for (String repoTag : image.getRepoTags()) {
System.out.println(repoTag + ":" + image.getId());
}
}
}
private static void getContainerLog() {
String url = "tcp://ip:2375";
DockerClient docker = DockerClientBuilder.getInstance(url).build();
System.out.println(111);
LogContainerCmd logContainerCmd = docker.logContainerCmd("containerID")
.withStdOut(true)
// .withFollowStream(true)
.withStdErr(true)
.withTailAll();
List<Object> logs = new ArrayList<>();
InvocationBuilder.AsyncResultCallback<Frame> callback = new InvocationBuilder.AsyncResultCallback<Frame>() {
@Override
public void onNext(Frame object) {
logs.add(object);
}
};
try {
logContainerCmd.exec(callback).awaitCompletion();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("logs的size:" + logs.size());
for (Object o : logs) {
System.out.println("logContent:" + o.toString());
}
System.out.println("日志获取完成");
}
}