|
|
@@ -1,25 +1,26 @@
|
|
|
package cn.reghao.devops.common.docker;
|
|
|
|
|
|
-import cn.reghao.devops.common.docker.po.Config;
|
|
|
+import cn.reghao.devops.common.docker.model.DockerAuth;
|
|
|
import cn.reghao.jutil.jdk.exception.ExceptionUtil;
|
|
|
-import cn.reghao.jutil.jdk.converter.DateTimeConverter;
|
|
|
import cn.reghao.jutil.jdk.text.TextFile;
|
|
|
import com.github.dockerjava.api.DockerClient;
|
|
|
+import com.github.dockerjava.api.async.ResultCallback;
|
|
|
import com.github.dockerjava.api.command.*;
|
|
|
import com.github.dockerjava.api.model.*;
|
|
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
|
|
import com.github.dockerjava.core.DockerClientConfig;
|
|
|
import com.github.dockerjava.core.DockerClientImpl;
|
|
|
-import com.github.dockerjava.core.command.PushImageResultCallback;
|
|
|
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
|
|
|
import com.github.dockerjava.transport.DockerHttpClient;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
+import java.io.Closeable;
|
|
|
import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
import java.time.Duration;
|
|
|
-import java.util.Arrays;
|
|
|
-import java.util.HashSet;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Set;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* Docker 客户端
|
|
|
@@ -27,32 +28,59 @@ import java.util.Set;
|
|
|
* @author reghao
|
|
|
* @date 2021-10-27 03:41:38
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
public class DockerImpl implements Docker {
|
|
|
- private final DockerClient dockerClient;
|
|
|
+ private DockerClient dockerClient;
|
|
|
private final TextFile textFile = new TextFile();
|
|
|
+ private final String unixSock = "/var/run/docker.sock";
|
|
|
|
|
|
public DockerImpl() {
|
|
|
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
|
|
|
- .withDockerHost("unix:///var/run/docker.sock")
|
|
|
+ .withDockerHost("unix://" + unixSock)
|
|
|
.withDockerTlsVerify(false)
|
|
|
- //.withDockerCertPath("/home/user/.docker")
|
|
|
- //.withRegistryUsername(registryUser)
|
|
|
- //.withRegistryPassword(registryPass)
|
|
|
+ //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
|
|
|
+ //.withRegistryUsername("username")
|
|
|
+ //.withRegistryPassword("password")
|
|
|
//.withRegistryEmail(registryMail)
|
|
|
//.withRegistryUrl(registryUrl)
|
|
|
.build();
|
|
|
+ init(config);
|
|
|
+ }
|
|
|
+
|
|
|
+ public DockerImpl(DockerAuth dockerAuth) {
|
|
|
+ DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
|
|
|
+ .withDockerHost("unix://" + unixSock)
|
|
|
+ .withDockerTlsVerify(false)
|
|
|
+ //.withDockerCertPath(String.format("%s/.docker", System.getProperty("user.home")))
|
|
|
+ .withRegistryUrl(dockerAuth.getRegistryUrl())
|
|
|
+ .withRegistryUsername(dockerAuth.getUsername())
|
|
|
+ .withRegistryPassword(dockerAuth.getPassword())
|
|
|
+ //.withRegistryEmail(registryMail)
|
|
|
+ .build();
|
|
|
+ init(config);
|
|
|
+ }
|
|
|
|
|
|
+ private void init(DockerClientConfig config) {
|
|
|
DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
|
|
|
.dockerHost(config.getDockerHost())
|
|
|
.sslConfig(config.getSSLConfig())
|
|
|
.maxConnections(100)
|
|
|
- .connectionTimeout(Duration.ofSeconds(30))
|
|
|
- .responseTimeout(Duration.ofSeconds(45))
|
|
|
+ .connectionTimeout(Duration.ofSeconds(60))
|
|
|
+ .responseTimeout(Duration.ofSeconds(60))
|
|
|
.build();
|
|
|
-
|
|
|
this.dockerClient = DockerClientImpl.getInstance(config, httpClient);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public void auth() {
|
|
|
+ dockerClient.authCmd().exec();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Version version() {
|
|
|
+ return dockerClient.versionCmd().exec();
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void build(String repoTag, String compileHome, String dockerfileContent) throws Exception {
|
|
|
File dockerfile = new File(compileHome + "/Dockerfile.tmp");
|
|
|
@@ -63,55 +91,37 @@ public class DockerImpl implements Docker {
|
|
|
// repoTag 格式为 docker.reghao.cn/devops:12345678
|
|
|
.withTags(Set.of(repoTag))
|
|
|
.start()
|
|
|
- .awaitImageId();
|
|
|
+ .awaitImageId(300, TimeUnit.SECONDS);
|
|
|
} catch (Exception e) {
|
|
|
throw new Exception(ExceptionUtil.errorMsg(e));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
public void build(String repoTag, String compileHome) throws Exception {
|
|
|
String dockerfilePath = compileHome + "/Dockerfile";
|
|
|
dockerClient.buildImageCmd()
|
|
|
.withDockerfile(new File(dockerfilePath))
|
|
|
.withTags(Set.of(repoTag))
|
|
|
.start()
|
|
|
- .awaitImageId();
|
|
|
+ .awaitImageId(300, TimeUnit.SECONDS);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void push(String image) throws Exception {
|
|
|
try {
|
|
|
- dockerClient.pushImageCmd(image).exec(new PushImageResultCallback()).awaitCompletion();
|
|
|
+ ResultCallback.Adapter<PushResponseItem> callback = new PushCallback();
|
|
|
+ dockerClient.pushImageCmd(image)
|
|
|
+ //.exec(new ResultCallback.Adapter<>())
|
|
|
+ .exec(callback)
|
|
|
+ .awaitCompletion(300, TimeUnit.SECONDS);
|
|
|
+ PushCallback pushCallback = (PushCallback) callback;
|
|
|
+ int code = pushCallback.getCode();
|
|
|
+ if (code != 0) {
|
|
|
+ throw new Exception(pushCallback.getMsg());
|
|
|
+ }
|
|
|
} catch (InterruptedException e) {
|
|
|
throw new Exception(ExceptionUtil.errorMsg(e));
|
|
|
}
|
|
|
- /*dockerClient.pushImageCmd(image).exec(new ResultCallback<PushResponseItem>() {
|
|
|
- @Override
|
|
|
- public void onStart(Closeable closeable) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onNext(PushResponseItem object) {
|
|
|
- System.out.println(object.getStatus());
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onError(Throwable throwable) {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onComplete() {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void close() throws IOException {
|
|
|
-
|
|
|
- }
|
|
|
- }).onComplete();*/
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -176,26 +186,127 @@ public class DockerImpl implements Docker {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public InspectContainerResponse createAndRun(String containerName, Config containerConfig) throws Exception {
|
|
|
+ public InspectContainerResponse createAndRun(String containerName, cn.reghao.devops.common.docker.model.Config containerConfig) throws Exception {
|
|
|
stopAndDelete(containerName);
|
|
|
|
|
|
+ String image = containerConfig.getImage();
|
|
|
+ CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image)
|
|
|
+ .withName(containerName);
|
|
|
+
|
|
|
+ List<String> env = containerConfig.getEnv();
|
|
|
+ if (env != null) {
|
|
|
+ createContainerCmd.withEnv(env);
|
|
|
+ }
|
|
|
+
|
|
|
HostConfig hostConfig = HostConfig.newHostConfig()
|
|
|
.withNetworkMode("host")
|
|
|
.withRestartPolicy(RestartPolicy.unlessStoppedRestart());
|
|
|
+ if (containerConfig.getVolumes() != null) {
|
|
|
+ Map<String, String> map = containerConfig.getVolumes().getMap();
|
|
|
+ List<Bind> list = new ArrayList<>();
|
|
|
+ for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ String value = entry.getValue();
|
|
|
+ Volume volume2 = new Volume(value);
|
|
|
+ Bind bind = new Bind(key, volume2);
|
|
|
+ list.add(bind);
|
|
|
+ }
|
|
|
+ hostConfig.withBinds(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ createContainerCmd.withHostConfig(hostConfig);
|
|
|
+ CreateContainerResponse response = createContainerCmd.exec();
|
|
|
+ String containerId = response.getId();
|
|
|
+ dockerClient.startContainerCmd(containerId).exec();
|
|
|
+ return dockerClient.inspectContainerCmd(containerId).exec();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void runAndRm(cn.reghao.devops.common.docker.model.Config containerConfig) throws Exception {
|
|
|
String image = containerConfig.getImage();
|
|
|
- CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image)
|
|
|
- .withName(containerName)
|
|
|
- .withHostConfig(hostConfig);
|
|
|
+ CreateContainerCmd createContainerCmd = dockerClient.createContainerCmd(image).withCmd("rm");
|
|
|
|
|
|
List<String> env = containerConfig.getEnv();
|
|
|
if (env != null) {
|
|
|
createContainerCmd.withEnv(env);
|
|
|
}
|
|
|
|
|
|
+ HostConfig hostConfig = HostConfig.newHostConfig()
|
|
|
+ .withNetworkMode("host")
|
|
|
+ .withRestartPolicy(RestartPolicy.noRestart());
|
|
|
+ if (containerConfig.getVolumes() != null) {
|
|
|
+ Map<String, String> map = containerConfig.getVolumes().getMap();
|
|
|
+ List<Bind> list = new ArrayList<>();
|
|
|
+ for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ String value = entry.getValue();
|
|
|
+ Volume volume2 = new Volume(value);
|
|
|
+ Bind bind = new Bind(key, volume2);
|
|
|
+ list.add(bind);
|
|
|
+ }
|
|
|
+ hostConfig.withBinds(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (containerConfig.getCmd() != null) {
|
|
|
+ createContainerCmd.withCmd(containerConfig.getCmd());
|
|
|
+ }
|
|
|
+
|
|
|
+ createContainerCmd.withHostConfig(hostConfig);
|
|
|
CreateContainerResponse response = createContainerCmd.exec();
|
|
|
String containerId = response.getId();
|
|
|
dockerClient.startContainerCmd(containerId).exec();
|
|
|
- return dockerClient.inspectContainerCmd(containerId).exec();
|
|
|
+
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
+ LogContainerCmd logContainerCmd = dockerClient.logContainerCmd(containerId);
|
|
|
+ logContainerCmd.withStdOut(true).withStdErr(true).withFollowStream(true);
|
|
|
+ logContainerCmd.exec(new ResultCallback<Frame>() {
|
|
|
+ @Override
|
|
|
+ public void onStart(Closeable closeable) {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(Frame object) {
|
|
|
+ if (object.getStreamType().equals(StreamType.STDERR)) {
|
|
|
+ if (list.size() > 100) {
|
|
|
+ list.clear();
|
|
|
+ }
|
|
|
+ list.add(object.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(Throwable throwable) {
|
|
|
+ log.info(throwable.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void close() throws IOException {
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ dockerClient.waitContainerCmd(containerId).exec(new ResultCallback.Adapter<>())
|
|
|
+ .awaitCompletion(300, TimeUnit.SECONDS);
|
|
|
+
|
|
|
+ InspectContainerResponse response1 = dockerClient.inspectContainerCmd(containerId).exec();
|
|
|
+ InspectContainerResponse.ContainerState state = response1.getState();
|
|
|
+ Long exitCode = state.getExitCodeLong();
|
|
|
+ if (Boolean.TRUE.equals(state.getRunning())) {
|
|
|
+ dockerClient.stopContainerCmd(containerId).exec();
|
|
|
+ dockerClient.removeContainerCmd(containerId).exec();
|
|
|
+ throw new Exception("docker build timeout");
|
|
|
+ } else if (exitCode != null && exitCode == 0) {
|
|
|
+ dockerClient.removeContainerCmd(containerId).exec();
|
|
|
+ } else {
|
|
|
+ dockerClient.removeContainerCmd(containerId).exec();
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ list.forEach(line -> {
|
|
|
+ sb.append(line).append(System.lineSeparator());
|
|
|
+ });
|
|
|
+ throw new Exception("docker build failed:\n" + sb.toString());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -228,28 +339,42 @@ public class DockerImpl implements Docker {
|
|
|
@Override
|
|
|
public List<Image> images() {
|
|
|
List<Image> images = dockerClient.listImagesCmd().exec();
|
|
|
-
|
|
|
- images.forEach(image -> {
|
|
|
+ return images;
|
|
|
+ /*return images.stream().map(image -> {
|
|
|
long created = image.getCreated();
|
|
|
String[] repoTags = image.getRepoTags();
|
|
|
if (repoTags.length == 0) {
|
|
|
- return;
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
+ String imageId = image.getId();
|
|
|
String[] repoTag = repoTags[0].split(":");
|
|
|
String repo = repoTag[0];
|
|
|
String tag = repoTag[1];
|
|
|
- System.out.printf("%s:%s -> %s\n", repo, tag, DateTimeConverter.format(created*1000));
|
|
|
- });
|
|
|
+ LocalDateTime created1 = DateTimeConverter.localDateTime(created*1000);
|
|
|
+ return new ImageInfo(repo, tag, imageId, created1);
|
|
|
+ }).filter(Objects::nonNull).collect(Collectors.toList());*/
|
|
|
+ }
|
|
|
|
|
|
- return images;
|
|
|
+ @Override
|
|
|
+ public void imageRm(String imageId) {
|
|
|
+ dockerClient.removeImageCmd(imageId).exec();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void rm(String containerId) {
|
|
|
+ dockerClient.removeContainerCmd(containerId).exec();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<Container> ps(boolean isAll) {
|
|
|
- return dockerClient.listContainersCmd()
|
|
|
- .withShowAll(isAll)
|
|
|
+ public List<InspectContainerResponse> psAll() {
|
|
|
+ List<Container> list = dockerClient.listContainersCmd()
|
|
|
+ .withShowAll(true)
|
|
|
.exec();
|
|
|
+ return list.stream().map(container -> {
|
|
|
+ String containerId = container.getId();
|
|
|
+ return dockerClient.inspectContainerCmd(containerId).exec();
|
|
|
+ }).collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -266,4 +391,43 @@ public class DockerImpl implements Docker {
|
|
|
String containerId = container.getId();
|
|
|
return dockerClient.inspectContainerCmd(containerId).exec();
|
|
|
}
|
|
|
+
|
|
|
+ static class PushCallback extends ResultCallback.Adapter<PushResponseItem> {
|
|
|
+ private int code;
|
|
|
+ private String msg;
|
|
|
+
|
|
|
+ public PushCallback() {
|
|
|
+ this.code = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getCode() {
|
|
|
+ return code;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getMsg() {
|
|
|
+ return msg;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(PushResponseItem object) {
|
|
|
+ PushResponseItem.ErrorDetail errorDetail = object.getErrorDetail();
|
|
|
+ if (errorDetail != null) {
|
|
|
+ //log.info("error: {} {}", errorDetail.getCode(), errorDetail.getMessage());
|
|
|
+ code = 1;
|
|
|
+ msg = errorDetail.getMessage();
|
|
|
+ } else {
|
|
|
+ //log.info("info: {} {} {}", object.getStatus(), object.getId(), object.getProgressDetail());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+ super.onComplete();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(Throwable throwable) {
|
|
|
+ throwable.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|