package com.dsideal.Utils; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ZipUtil; import com.alibaba.fastjson2.JSONObject; import com.jfinal.kit.Kv; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; import java.io.*; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; public class PublishUtil { /** * 功能:执行批处理命令 * * @param path * @throws IOException * @throws InterruptedException */ public static void ExecBatchCmd(String path) throws IOException, InterruptedException { String[] cmd = {path}; Process process = Runtime.getRuntime().exec(cmd); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } process.waitFor(); } public static void doLogin(SSHUtil ssh, String username, String password) throws Exception { String cmd = "docker login --username=" + username + " --password=" + password + " registry.cn-hangzhou.aliyuncs.com"; ssh.exec(cmd); } public static void bluePrint(String msg) { // 设置文本颜色 System.out.println("\033[34m" + msg + "\033[0m"); // 蓝色 } public static void redPrint(String msg) { // 设置文本颜色 System.out.println("\033[31m" + msg + "\033[0m"); // 红色文本 } /** * 删除本机所有Docker镜像 * docker images --format "{{.Repository}}:{{.Tag}}" | xargs -r docker rmi -f * 登录远程仓库 * docker login --username=东师黄海 registry.cn-hangzhou.aliyuncs.com --password DsideaL4r5t6y7u * docker login --username=驿来特充电 registry.cn-hangzhou.aliyuncs.com --password=ylt5033. *
* # 搜索 * docker search registry.cn-hangzhou.aliyuncs.com/yltcharge/zhu-que:20240903 * #拉取 * docker pull registry.cn-hangzhou.aliyuncs.com/yltcharge/zhu-que:20240903 *
* docker pull registry.cn-hangzhou.aliyuncs.com/dsideal/jdk:21
* docker tag 19a54d2204aa registry.cn-hangzhou.aliyuncs.com/yltcharge/jdk:21
* docker push registry.cn-hangzhou.aliyuncs.com/yltcharge/jdk:21
*/
public static Kv publish(String projectName, boolean isStatic, String workingPath, String localLibPath, Kv choiceWarehouse, String choiceConfig) throws Exception {
//判断是不是有需要批处理的生成JAR的过程
String cmdPath = workingPath + "生成依赖jar.bat";
if (FileUtil.exist(cmdPath)) {
ExecBatchCmd(cmdPath);
}
System.out.println("正在生成" + projectName + "的镜像...");
//配置文件
String path = PathKit.getRootClassPath() + "\\publishImage.json";
JSONObject jo = JSONObject.parseObject(FileUtil.readUtf8String(path));
//主机
String host = jo.getString("host");
String user = jo.getString("user");
String pwd = jo.getString("pwd");
int port = jo.getIntValue("port");
String project_port = null;
//声明SSH对象
SSHUtil ssh = new SSHUtil(user, pwd, host, port);
ssh.connect();
// 格式化日期
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String newVersion = now.format(formatter);
if (!StrKit.isBlank(choiceConfig)) {
newVersion = choiceConfig + "_" + newVersion.replace(" ", "").replace("-", "").replace(":", "");
} else {
newVersion = newVersion.replace(" ", "").replace("-", "").replace(":", "");
}
//准备工作
String remotePath = "/usr/local/" + projectName + "/";
ssh.exec("rm -rf " + remotePath);
ssh.mkdir(remotePath);
if (!isStatic) {
System.out.println("正在上传Dockerfile...");
ssh.upload(workingPath + "Dockerfile", remotePath + "Dockerfile");
}
if (!StrKit.isBlank(localLibPath)) {
System.out.println("正在创建lib目录...");
ssh.mkdir(remotePath + "lib");
//遍历lib目录下的文件
for (File file : FileUtil.loopFiles(localLibPath)) {
System.out.println("正在上传jar包:" + file.getName());
ssh.upload(file.getAbsolutePath(), remotePath + "lib/" + file.getName());
}
}
//打包target为zip
if (FileUtil.isDirectory(workingPath + "target")) {
String localFile = workingPath + "target.zip";
if (FileUtil.exist(localFile)) {
FileUtil.del(localFile);
}
System.out.println("正在上传target.zip...");
// 将目录打包成ZIP文件,不包含目录本身,只包含目录下的文件和子目录
ZipUtil.zip(workingPath + "target", localFile, true);
//上传
ssh.upload(localFile, remotePath + "target.zip");
//删除target.zip
FileUtil.del(localFile);
//解压缩
System.out.println("正在解压缩target.zip...");
ssh.exec("cd " + remotePath + " && unzip target.zip");
ssh.exec("cd " + remotePath + " && rm -rf target.zip");
//获取项目端口
String undertow_dev = remotePath + "target/classes/undertow_dev.properties";
String cmd = "grep '^undertow\\.port=' " + undertow_dev + " | awk -F'=' '{print $2}'";
project_port = ssh.exec(cmd).getStr("message").replace("[", "").replace("]", "");
}
//处理静态文件
if (isStatic) {
//倒数第二个/
int cnt = 0;
int pos;
for (int i = workingPath.length() - 1; ; i--) {
if (workingPath.charAt(i) == '\\') cnt++;
if (cnt == 2) {
pos = i;
break;
}
}
String localFile = workingPath.substring(0, pos) + "\\static.zip";
if (FileUtil.exist(localFile)) {
FileUtil.del(localFile);
}
System.out.println("正在上传static.zip...");
// 将目录打包成ZIP文件,不包含目录本身,只包含目录下的文件和子目录
ZipUtil.zip(workingPath, localFile, false);
//上传
ssh.upload(localFile, remotePath + "static.zip");
//删除target.zip
FileUtil.del(localFile);
//解压缩
System.out.println("正在解压缩static.zip...");
ssh.exec("cd " + remotePath + " && unzip static.zip");
ssh.exec("cd " + remotePath + " && rm -rf static.zip");
}
//登录镜像仓库
//处理一下Dockerfile中的JDK21此用问题,因为不同的打包操作,需要登录不同的仓库,这里临时用shell修改一下
String remoteDockerFile = remotePath + "Dockerfile";
if (choiceWarehouse.get("id") != null) {
doLogin(ssh, choiceWarehouse.getStr("username"), choiceWarehouse.getStr("password"));
System.out.println("仓库登录成功!");
}
//修改镜像要用的配置文件
String cmd = "sed -i 's|ENV WORKING_ENV=\"pro\"|ENV WORKING_ENV=\"" + choiceConfig + "\"|g' " + remoteDockerFile;
ssh.exec(cmd);
System.out.println(cmd);
System.out.println("环境变量修改成功!");
//如果容器正在运行中,那么容器对应的镜像删除失败
cmd = "docker rm -f $(docker ps -aq)";
ssh.exec(cmd);
//删除所有镜像
cmd = "docker rmi -f $(docker images -q)";
ssh.exec(cmd);
//打包
System.out.println("开始打包镜像,稍等....");
cmd = "cd /usr/local/" + projectName + " && docker build -t " + projectName + ":" + newVersion + " .";
System.out.println(cmd);
ssh.exec(cmd);
//获取最新打包后的镜像ID
cmd = "docker images --format \"{{.Repository}} {{.Tag}} {{.ID}} {{.CreatedAt}}\" | grep " + projectName + " | head -n1 | awk '{print $3}'";
Kv kv = ssh.exec(cmd);
String imageId = kv.getStr("message").replace("[", "").replace("]", "");
System.out.println("镜像打包完成,镜像ID=" + imageId);
if (StrKit.isBlank(imageId)) {
System.out.println("镜像ID生成异常,请检查后再试!");
System.exit(0);
}
if (choiceWarehouse.get("id") != null) {
System.out.println("打标签...");
cmd = "docker tag " + imageId + " registry.cn-hangzhou.aliyuncs.com/" + choiceWarehouse.getStr("name") + "/" + projectName + ":" + newVersion;
ssh.exec(cmd);
System.out.println("开始推送到远程仓库,稍等...");
cmd = "docker push registry.cn-hangzhou.aliyuncs.com/" + choiceWarehouse.getStr("name") + "/" + projectName + ":" + newVersion;
System.out.println(cmd);
ssh.exec(cmd);
System.out.println("推送到远程仓库完成!");
}
ssh.disconnect();
System.out.println("恭喜,镜像打包成功!");
Kv ret = Kv.by("projectName", projectName + ":" + newVersion);
ret.set("project_port", project_port);
return ret;
}
/**
* 功能:获取项目列表
*
* @return
* @throws IOException
*/
public static List