利用Docker-java加载并将docker镜像包推送至镜像仓库

想要在java中或者其他方式访问dockerAPI都需要设置一个远程访问端口

vi /lib/systemd/system/docker.service

找到Execstart=/usr/bin/dockerd,并在后加上-H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --insecure-registry=10.142.20.68 退出并且保存

ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock --insecure-registry=10.142.20.68

运行以下命令,重启docker服务:

systemctl daemon-reload
 
service docker restart//重启启动docker
 
systemctl status docker//可以查看相关内容,看看2375是否已经设置好

运行:netstat -nlp |grep 2375 可以查看2375是否已经被监听

1. 编写上传附件接口或者从FTP下载附件至本地再上传

docker:
  host: tcp://10.154.2.15:2375
  registry:
      project: osmcs
      address: registry.paas
      username: admin              
      password: 123456Dcos
@Value("${docker.host}")
private String dockerHost;//加载的IP
    
@Value("${docker.registry.project}")
private String registryProject;//harbor下的项目
    
@Value("${docker.registry.username}")
private String registryUserName;//harbor用户名
    
@Value("${docker.registry.password}")
private String registryPassword;//harbor密码
    
@Value("${docker.registry.address}")
private String registryAddress;//harbor的IP

 @RequestMapping(value="/loadToRepository", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Object loadImageToRepository (@RequestPart(value = "file") MultipartFile file, String project, String softwareName, String version) {
        System.out.println("DockerUtils loadImageToRepository begin");
        System.out.println("docker镜像名称" + file.getOriginalFilename());
        try {
            String imageName = registryAddress + "/" + project + "/" + softwareName + ":" + version;
            new UploadThread(registryAddress, dockerHost, registryUserName, registryPassword, imageName, file.getInputStream()).start();
        } catch (IOException e) {
            System.err.println("获取文件流失败");
        }
        return ResultUtil.success("上传结束,正在同步至镜像仓库");
    }

从FTP下载附件至本地再上传至镜像仓库

@RequestMapping(value="/load", method = RequestMethod.POST)
    public Object loadAndPushImage(@RequestBody Software software) {
        System.out.println("DockerController load begin. request params are " + software);
        System.out.println("dockerHost = " + dockerHost);
        System.out.println("registryProject = " + registryProject);
        System.out.println("registryUserName = " + registryUserName);
        System.out.println("registryPassword = " + registryPassword);
        System.out.println("registryAddress = " + registryAddress);
//      String imageName = registryAddress + "/" + registryProject + "/" + softwareName + ":" + version;
        String tempFilePath = null;
//        if (!software.getFtpPath().startsWith(tempPath)) {
//            return ResultUtil.success("这不是FTP上的文件");
//        }
        if (!tempPath.endsWith(File.separator)) {
            tempFilePath = tempPath + File.separator + software.getFileName();
        } else {
            tempFilePath = tempPath + software.getFileName();
        }
        File tempFile = new File(tempFilePath);
        OutputStream os = null;
        try {
            os = new FileOutputStream(tempFile);
            ftpClient.retrieveFile(software.getFtpPath(), os);
            os.flush();
            os.close();
            if (tempFile.exists()) {
                String originalImageName = null;
                if (registryAddress.endsWith("/")) {
                    originalImageName = registryAddress + registryProject + "/" + software.getSoftwareName().toLowerCase() + ":" + software.getVersion();
                } else {
                    originalImageName = registryAddress + "/" + registryProject + "/" + software.getSoftwareName().toLowerCase() + ":" + software.getVersion();
                }
                String imageName = null;
                //解压jar压缩文件
                System.err.println("tempFilePath = " + tempFilePath);
                if (tempFilePath.endsWith(".tar")) {
                    imageName = originalImageName;
                    originalImageName = UnCompress.getImageName(tempFilePath);
                } else {
                    imageName = originalImageName;
                }
                
                System.out.println("originalImageName = " + originalImageName);
                new UploadThread(registryAddress, dockerHost, registryUserName, registryPassword, originalImageName, imageName, new FileInputStream(tempFile)).start();
                
                //删除文件
                boolean delete = tempFile.delete();
                System.out.println(delete ? "删除临时文件成功" : "删除临时文件失败");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("从FTP获取文件至本地失败" + e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    System.out.println("关闭输出流失败" + e.getMessage());
                }
            }
        }
        return ResultUtil.success("上传结束,正在同步至镜像仓库");
    }
    

2. 由于上传镜像比较慢,此处采用单独线程操作

public class UploadThread extends Thread {
    
    private final static Logger logger = LoggerFactory.getLogger(UploadThread.class);
    
    private String dockerHost;
    
    private String registryAddress;
    
    private String registryUserName;
    
    private String registryPassword;
    
    private InputStream inputStream;
    
    private String originalImageName;

    private String imageName;
    
    public UploadThread(String registryAddress, String dockerHost, String registryUserName, String registryPassword, 
            String originalImageName, String imageName, InputStream inputStream) {
        super();
        this.originalImageName = originalImageName;
        this.imageName = imageName;
        this.dockerHost = dockerHost;
        this.registryAddress = registryAddress;
        this.registryUserName = registryUserName;
        this.registryPassword = registryPassword;
        this.inputStream = inputStream;
    }

    @Override
    public void run() {

        long beginTime = System.currentTimeMillis();
        if (StringUtils.isEmpty(registryUserName)) {
            registryUserName = null;
        }
        if (StringUtils.isEmpty(registryPassword)) {
            registryPassword = null;
        }
        System.out.println("imageName = " + imageName);
        System.out.println("dockerHost = " + dockerHost);
        System.out.println("registryAddress = " + registryAddress);
        System.out.println("registryUserName = " + registryUserName);
        System.out.println("registryPassword = " + registryPassword);
        
        AuthConfig authConfig = new AuthConfig()
                .withUsername(registryUserName)
                .withPassword(registryPassword)
                .withRegistryAddress(registryAddress);
        
        DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost(dockerHost)
//                .withDockerConfig("C:\\Users\\Administrator\\Desktop\\docker-java-api\\daemon.json")
                .build();
        DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory().withReadTimeout(60000)
                .withConnectTimeout(1000)
                .withMaxTotalConnections(100)
                .withMaxPerRouteConnections(10);

        DockerClient dockerClient = DockerClientBuilder.getInstance(dockerClientConfig)
                .withDockerCmdExecFactory(dockerCmdExecFactory)
                .build();
        System.err.println("docker versin is " + dockerClient.versionCmd().exec().getVersion().toString());
        
        try {
            //加载镜像
            LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(inputStream);
            loadImageCmd.exec();
            //push至镜像仓库
            PushImageResultCallback pushImageResultCallback = new PushImageResultCallback() {
                @Override
                public void onNext(PushResponseItem item) {
                    System.out.println("id:" + item.getId()  +" status: "+item.getStatus());
                    super.onNext(item);
                }
                @Override
                public void onComplete() {
                    System.out.println("Image pushed completed!");
                    super.onComplete();
                }
            };
            if (!originalImageName.equalsIgnoreCase(imageName)) {
                dockerClient.tagImageCmd(originalImageName, imageName, imageName.split(":")[1]).exec();
            }
            
            dockerClient.pushImageCmd(imageName)
                        .withAuthConfig(authConfig)
                        .exec(pushImageResultCallback)
                        .awaitSuccess();
            
            System.out.println("push至docker镜像仓库后,删除本地load的镜像");
            dockerClient.removeImageCmd(originalImageName).exec();
            if (!originalImageName.equalsIgnoreCase(imageName)) {
                dockerClient.removeImageCmd(imageName).exec();
            }
            
            System.out.println("本地镜像删除成功");
            
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("上传Docker镜像失败");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("文件流关闭失败");
                }
            }
        }
        // }
        long endTime = System.currentTimeMillis();
        System.out.println("上传Docker镜像结束,用时:" + (endTime - beginTime) + "ms");
    }
}

3. 如果第三方接口想要调用此接口

public boolean uploadFile (String url, MultipartFile file, String tempPath) {
	    HttpHeaders headers = new HttpHeaders();

	    String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
	    logger.info("tempPath = " + tempPath);
	    String tempFilePath = tempPath + tempFileName;
	    File tempFile = new File(tempFilePath);
	    try {
            file.transferTo(tempFile);
            FileSystemResource fileSystemResource = new FileSystemResource(tempFilePath);
            logger.info("临时文件路径:" + fileSystemResource.getPath());
            MediaType type = MediaType.parseMediaType("multipart/form-data; charset=UTF-8");
            headers.setContentType(type);
            String cd = "filename=\"" + file.getOriginalFilename() + "\"";
            headers.add("Content-Disposition", cd);
            MultiValueMap form = new LinkedMultiValueMap();
            form.add("file", fileSystemResource);
            final RestTemplate restTemplate = new RestTemplate();
            Object recv = restTemplate.postForEntity(url, form, Object.class);
            try {
                logger.info("调用上传镜像包接口返回的数据:" + recv.toString());
                tempFile.delete();
            } catch (Exception e) {
                logger.error("删除本地临时文件失败", e);
            }
        } catch (IllegalStateException e) {
            logger.error("httpclient close failed", e);
        } catch (IOException e) {
            logger.error("httpclient close failed", e);
        }

	    return true;
	}

4. 解压缩镜像包文件,获取镜像的标签内容(RepoTags),此处以解压tar文件为例

利用Docker-java加载并将docker镜像包推送至镜像仓库_第1张图片

package com.github.dockerjava;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 解压缩
 * @author Administrator
 *
 */
public class UnCompress {
    

    
    private static final String BASE_DIR = "";  
  
    // 符号"/"用来作为目录标识判断符  
    private static final String PATH = File.separator;  
    private static final int BUFFER = 1024;  
  
    private static final String EXT = ".tar";  
  
    /** 
     * 归档 
     *  
     * @param srcPath 
     * @param destPath 
     * @throws Exception 
     */  
    public static void archive(String srcPath, String destPath)  
            throws Exception {  
  
        File srcFile = new File(srcPath);  
  
        archive(srcFile, destPath);  
  
    }  
  
    /** 
     * 归档 
     *  
     * @param srcFile 
     *            源路径 
     * @param destPath 
     *            目标路径 
     * @throws Exception 
     */  
    public static void archive(File srcFile, File destFile) throws Exception {  
  
        TarArchiveOutputStream taos = new TarArchiveOutputStream(  
                new FileOutputStream(destFile));  
  
        archive(srcFile, taos, BASE_DIR);  
  
        taos.flush();  
        taos.close();  
    }  
  
    /** 
     * 归档 
     *  
     * @param srcFile 
     * @throws Exception 
     */  
    public static void archive(File srcFile) throws Exception {  
        String name = srcFile.getName();  
        String basePath = srcFile.getParent();  
        String destPath = basePath+File.separator + name + EXT;  
        archive(srcFile, destPath);  
    }  
  
    /** 
     * 归档文件 
     *  
     * @param srcFile 
     * @param destPath 
     * @throws Exception 
     */  
    public static void archive(File srcFile, String destPath) throws Exception {  
        archive(srcFile, new File(destPath));  
    }  
  
    /** 
     * 归档 
     *  
     * @param srcPath 
     * @throws Exception 
     */  
    public static void archive(String srcPath) throws Exception {  
        File srcFile = new File(srcPath);  
  
        archive(srcFile);  
    }  
  
    /** 
     * 归档 
     *  
     * @param srcFile 
     *            源路径 
     * @param taos 
     *            TarArchiveOutputStream 
     * @param basePath 
     *            归档包内相对路径 
     * @throws Exception 
     */  
    private static void archive(File srcFile, TarArchiveOutputStream taos,  
            String basePath) throws Exception {  
        if (srcFile.isDirectory()) {  
            archiveDir(srcFile, taos, basePath);  
        } else {  
            archiveFile(srcFile, taos, basePath);  
        }  
    }  
  
    /** 
     * 目录归档 
     *  
     * @param dir 
     * @param taos 
     *            TarArchiveOutputStream 
     * @param basePath 
     * @throws Exception 
     */  
    private static void archiveDir(File dir, TarArchiveOutputStream taos,  
            String basePath) throws Exception {  
  
        File[] files = dir.listFiles();  
  
        if (files.length < 1) {  
            TarArchiveEntry entry = new TarArchiveEntry(basePath  
                    + dir.getName() + PATH);  
  
            taos.putArchiveEntry(entry);  
            taos.closeArchiveEntry();  
        }  
  
        for (File file : files) {  
  
            // 递归归档  
            archive(file, taos, basePath + dir.getName() + PATH);  
  
        }  
    }  
  
    /** 
     * 数据归档 
     *  
     * @param data 
     *            待归档数据 
     * @param path 
     *            归档数据的当前路径 
     * @param name 
     *            归档文件名 
     * @param taos 
     *            TarArchiveOutputStream 
     * @throws Exception 
     */  
    private static void archiveFile(File file, TarArchiveOutputStream taos,  
            String dir) throws Exception {  
  
        /** 
         * 归档内文件名定义 
         *  
         * 
 
         * 如果有多级目录,那么这里就需要给出包含目录的文件名 
         * 如果用WinRAR打开归档包,中文名将显示为乱码 
         * 
*/ TarArchiveEntry entry = new TarArchiveEntry(dir + file.getName()); //如果打包不需要文件夹,就用 new TarArchiveEntry(file.getName()) entry.setSize(file.length()); taos.putArchiveEntry(entry); BufferedInputStream bis = new BufferedInputStream(new FileInputStream( file)); int count; byte data[] = new byte[BUFFER]; while ((count = bis.read(data, 0, BUFFER)) != -1) { taos.write(data, 0, count); } bis.close(); taos.closeArchiveEntry(); } /** * 解归档 * * @param srcFile * @throws Exception */ public static void dearchive(File srcFile) throws Exception { String basePath = srcFile.getParent(); dearchive(srcFile, basePath); } /** * 解归档 * * @param srcFile * @param destFile * @throws Exception */ public static void dearchive(File srcFile, File destFile) throws Exception { TarArchiveInputStream tais = new TarArchiveInputStream( new FileInputStream(srcFile)); dearchive(destFile, tais); tais.close(); } /** * 解归档 * * @param srcFile * @param destPath * @throws Exception */ public static void dearchive(File srcFile, String destPath) throws Exception { dearchive(srcFile, new File(destPath)); } /** * 文件 解归档 * * @param destFile * 目标文件 * @param tais * ZipInputStream * @throws Exception */ private static void dearchive(File destFile, TarArchiveInputStream tais) throws Exception { TarArchiveEntry entry = null; while ((entry = tais.getNextTarEntry()) != null) { // 文件 String dir = destFile.getPath() + File.separator + entry.getName(); File dirFile = new File(dir); // 文件检查 fileProber(dirFile); if (entry.isDirectory()) { dirFile.mkdirs(); } else { dearchiveFile(dirFile, tais); } } } /** * 文件 解归档 * * @param srcPath * 源文件路径 * * @throws Exception */ public static void dearchive(String srcPath) throws Exception { File srcFile = new File(srcPath); dearchive(srcFile); } /** * 文件 解归档 * * @param srcPath * 源文件路径 * @param destPath * 目标文件路径 * @throws Exception */ public static void dearchive(String srcPath, String destPath) throws Exception { File srcFile = new File(srcPath); dearchive(srcFile, destPath); } /** * 文件解归档 * * @param destFile * 目标文件 * @param tais * TarArchiveInputStream * @throws Exception */ private static void dearchiveFile(File destFile, TarArchiveInputStream tais) throws Exception { BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(destFile)); int count; byte data[] = new byte[BUFFER]; while ((count = tais.read(data, 0, BUFFER)) != -1) { bos.write(data, 0, count); } bos.close(); } /** * 文件探针 * *
 
     * 当父目录不存在时,创建目录! 
     * 
* * @param dirFile */ private static void fileProber(File dirFile) { File parentFile = dirFile.getParentFile(); if (!parentFile.exists()) { // 递归寻找上级目录 fileProber(parentFile); parentFile.mkdir(); } } public static String getImageName(String tempFilePath) throws Exception{ System.out.println("tempFilePath = " + tempFilePath); String dirPath = tempFilePath.substring(0, tempFilePath.lastIndexOf(".")); File dirFile = new File(dirPath); if (!dirFile.exists()) { dirFile.mkdirs(); } UnCompress.dearchive(tempFilePath, dirPath); if (!dirPath.endsWith(File.separator)) { dirPath += File.separator; } //目标文件 String destFilePath = dirPath + "manifest.json"; File destFile = new File(destFilePath); if (!destFile.exists()) { return null; } StringBuilder sb = new StringBuilder(""); InputStream io = new FileInputStream(new File(destFilePath)); byte[] bytes = new byte[1024]; int len = 0; while ((len = io.read(bytes)) > 0) { sb.append(new String(bytes, 0, len)); } String content = sb.toString(); //只取第一个配置项 List jsonList = (List) JSONArray.parse(content); System.out.println("jsonList = " + jsonList); return ((List)jsonList.get(0).get("RepoTags")).get(0); /*if (content.startsWith("[")) { content = content.substring(1, content.length() - 2); } System.out.println("content = " + content); JSONObject json = JSONObject.parseObject(content.toString()); List list = (List) json.get("RepoTags"); System.out.println("list = " + list); return list.get(0);*/ } /*public static void main(String[] args) throws Exception { String str = getImageName("E:\\temp\\osmcs_redis.tar"); System.err.println(str); }*/ /*public static void main(String[] args) { List jsonList = (List) JSONArray.parse("[{'Config':'05af71dd925161e515a980a129868929ee200bd5f896f6be61cf0a25fb5912df.json','RepoTags':['tomcat:latest'],'Layers':['cdc670427c7f26730bc075317993e7e72eea6df68e1be0ddf785cb3b774edc7c/layer.tar','5872a7aa42489b9517d31cc4ae83876cb38a21111acb0303a270ad6156c180f1/layer.tar','a34ac92b6f61c316eb200d74a3333c9f6fb24efdd15f2e1415474a9a96d0be62/layer.tar','0318148a6b1a640ef69623d9b97b59eed85285401e8250d71008e72f637cae31/layer.tar','86de30dac6602cac8b9b788a867daf10feaba9fd86f258a215e6396f34c94582/layer.tar','0a493e1fcea7fb5ecd1a72a3b5793ecf75de5af77e59280d4a54e0b01a5245cc/layer.tar','84421a45d2a124bd8817cbc127020e54ea805f77eb845174e1339d3d191c0f03/layer.tar','779b0e2cbb049d99e0802f5691bcd87c3ecf1d6c1469a9ddec2ff08522967672/layer.tar','87c68fcc6b34277e18005b0b436dc41064ca21db2337325ed75402d97a911a14/layer.tar','b5d3df54bc2ef8eaf83d2ea17e905821ba7fd186b2dbe4715e792cfc082dbeaa/layer.tar','617232c843330e0a4b9b2c7054188226497a5bc2338261bb23265de0c94d504e/layer.tar','75c4928affc72da624cbecc4b7d5b9896262d2e07cbbd13409b127f33c423cd8/layer.tar']},{'Config':'05a60462f8bafb215ddc5c20a364b5fb637670200a74a5bb13a1b23f64515561.json','RepoTags':['nginx:1.11.5'],'Layers':['3cae701620ae8eaf6a7f9988227eb21175b74f42e37a8187af521e0211555286/layer.tar','cb1fb070144286bf18e01b22d594e5e8eda2e5e39a28f5e1618105fee0e469e2/layer.tar','b52be048d4d2ebc586ef1134e94116a2189e36abe19975c650bb0b226c2ce81d/layer.tar']}]"); for (JSONObject jsonObject : jsonList) { System.out.println(((List)jsonObject.get("RepoTags")).get(0)); } }*/ }

 

你可能感兴趣的:(Docker)