java集成Docker-java实现远程镜像、容器创建,服务发布

这篇具有很好参考价值的文章主要介绍了java集成Docker-java实现远程镜像、容器创建,服务发布。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、集成目的

       目前项目中需要实现水利机理模型的容器化部署,使用docker实现模型容器化部署操作,互相隔离,就是一个不错的方案。

2、需要docker-java 实现

  • 实现docker远程连接、远程安全连接
  • 构建镜像、加载镜像、删除镜像、拉取镜像、创建容器、启动容器、停止容器、删除容器。
  • 执行模型运行命令
  • 实现路径挂载。
  • 实现宿主机模型包复制

3、使用docker-java

3.1创建远程连接

3.1.1修改docker配置信息(普通连接)

打开docker.service文件
sudo vi /lib/systemd/system/docker.service
找到ExecStart 开头的配置,注释原配置 进行备份
插入以下内容
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
保存退出
sudo systemctl daemon-reload
sudo systemctl restart docker

注意:

1、我使用的是Ubutun系统,需要使用sudo进行操作。防火墙如果启动,需要开发2375端口,不然无法访问到docker。

2、浏览器输入:http://IP:2375/version 如果响应正常,则配置生效

3.1.2添加maven依赖

 <dependency>
   <groupId>com.github.docker-java</groupId>
   <artifactId>docker-java</artifactId>
   <version>3.2.13</version>
 </dependency>

 <dependency>
   <groupId>com.github.docker-java</groupId>
   <artifactId>docker-java-transport-httpclient5</artifactId>
   <version>3.2.13</version>
 </dependency>

 <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
 </dependency>

3.1.3创建普通连接

package com.sf.engines.config;
 
import com.alibaba.fastjson.JSONObject;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.model.Info;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.github.dockerjava.transport.DockerHttpClient;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import java.time.Duration;

@Configuration
public class DockerConfig {
 
    /**
     * 连接docker服务器
     * @return
     */
    @Bean("dockerClient")
    public DockerClient connectDocker(){
        DefaultDockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerTlsVerify(false)
                // 这里填最上面填的ip端口号,ip换成服务器ip
                .withDockerHost("tcp://192.168.10.8:2375")
                // docker API版本号,可以用docker version查看
                .withApiVersion("1.41")
                // 默认
                .withRegistryUrl("https://index.docker.io/v1/").build();
 
        DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .sslConfig(config.getSSLConfig())
                .maxConnections(100)
                .connectionTimeout(Duration.ofSeconds(30))
                .responseTimeout(Duration.ofSeconds(45))
                .build();
 
        DockerClient dockerClient = DockerClientImpl.getInstance(config, httpClient);
 
        Info info = dockerClient.infoCmd().exec();
        String infoStr = JSONObject.toJSONString(info);
        System.out.println("docker的环境信息如下:=================");
        System.out.println(infoStr);
        return dockerClient;
    }

}

控制台打印了docker信息,说明已经连上docker。

注意:

  • DOCKER_HOST Docker的地址,比如: tcp://localhost:2376 或者unix:///var/run/docker.sock
  • DOCKER_TLS_VERIFY 是否开启 TLS 验证 (http 和 https 之间切换)
  • DOCKER_CERT_PATH TLS 验证的证书路径
  • DOCKER_CONFIG 其他docker配置文件的路径 (比如 .dockercfg)
  • api.version API version版本
  • registry.url 下载源地址(docker镜像存放的地址)
  • registry.username 登陆用户名 (推送镜像到docker云仓库时需要)
  • registry.password 登陆用户密码(推送镜像到docker云仓库时需要)
  • registry.email 登陆账户的邮箱(推送镜像到docker云仓库时需要)

3.1.4创建安全连接 

  1. 首先修改docker.service
sudo vi /lib/systemd/system/docker.service
找到ExecStart 开头的配置,注释原配置 进行备份
插入以下内容
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock -D --tlsverify --tlscert=/etc/docker/certs.d/server-cert-docker.pem --tlskey=/etc/docker/certs.d/server-key-docker.pem --tlscacert=/etc/docker/certs.d/ca-docker.pem
保存退出
sudo systemctl daemon-reload
sudo service docker restart

   2. 证书脚本编写

#!/bin/bash
#
# -------------------------------------------------------------
# 自动创建 Docker TLS 证书
# -------------------------------------------------------------
# 以下是配置信息
# --[BEGIN]------------------------------
CODE="docker"
IP="192.168.1.1"
PASSWORD="123456"
COUNTRY="CN"
STATE="SHANDONG"
CITY="JINAN"
ORGANIZATION="thyc"
ORGANIZATIONAL_UNIT="Dev"
COMMON_NAME="$IP"
EMAIL="zjbang.ok@163.com"
# --[END]--
# Generate CA key
openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "ca-key-$CODE.pem" 4096
# Generate CA
openssl req -new -x509 -days 365 -key "ca-key-$CODE.pem" -sha256 -out "ca-$CODE.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
# Generate Server key
openssl genrsa -out "server-key-$CODE.pem" 4096
# Generate Server Certs.
openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key-$CODE.pem" -out server.csr
echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf
echo "extendedKeyUsage = serverAuth" >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "server-cert-$CODE.pem" -extfile extfile.cnf
# Generate Client Certs.
rm -f extfile.cnf
openssl genrsa -out "key-$CODE.pem" 4096
openssl req -subj '/CN=client' -new -key "key-$CODE.pem" -out client.csr
echo extendedKeyUsage = clientAuth >> extfile.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:$PASSWORD" -CA "ca-$CODE.pem" -CAkey "ca-key-$CODE.pem" -CAcreateserial -out "cert-$CODE.pem" -extfile extfile.cnf
rm -vf client.csr server.csr
chmod -v 0400 "ca-key-$CODE.pem" "key-$CODE.pem" "server-key-$CODE.pem"
chmod -v 0444 "ca-$CODE.pem" "server-cert-$CODE.pem" "cert-$CODE.pem"
# 打包客户端证书
mkdir -p "tls-client-certs-$CODE"
cp -f "ca-$CODE.pem" "cert-$CODE.pem" "key-$CODE.pem" "tls-client-certs-$CODE/"
cd "tls-client-certs-$CODE"
tar zcf "tls-client-certs-$CODE.tar.gz" *
mv "tls-client-certs-$CODE.tar.gz" ../
cd ..
rm -rf "tls-client-certs-$CODE"
# 拷贝服务端证书
mkdir -p /etc/docker/certs.d
cp "ca-$CODE.pem" "server-cert-$CODE.pem" "server-key-$CODE.pem" /etc/docker/certs.d/

脚本是网上找的,可以自动生成证书并完成拷贝的脚本。脚本命名自由:sudo vi auto_gen_docker.sh 

3.执行脚本

chmod a+x auto_gen_docker.sh
sh auto_gen_docker.sh

3.2镜像管理

3.2.1从dockerfile构建镜像


    /**
     * 从Dockerfile构建镜像
     * @return
     * @throws URISyntaxException
     */
    public String buildImage(String imageName, String imageTag, String dockerFile) throws URISyntaxException {
        ImmutableSet<String> tag = ImmutableSet.of(imageName + ":" + imageTag);
        String imageId = dockerClient.buildImageCmd(new File(dockerFile))
                .withTags(tag)
                .start()
                .awaitImageId();
        return imageId;
    }

提示:我在使用buileImageCmd时,无法正确构建镜像。不得已采取比较笨的办法,将dockerfile文件上传到服务器目标文件夹中,通过ssh远程调用的方式,进行远程镜像构建操作。具体实现代码如下:

//远程构建镜像
	private String buildImage(EnginesModelImageEntity image) {

		String tag = image.getImageName() + ":" + image.getImageTag();
		//模型解压命令
		StringBuffer buildBuffer = new StringBuffer("");
		buildBuffer.append(ModelConstant.CD_STR)
			.append(image.getDockerFileUrl())
			.append(ModelConstant.AND_STR)
			.append(ModelConstant.DOCKER_BUILD)
			.append(tag)
			.append(ModelConstant.DOCKER_BUILD_END);
		//调用远程命令进行模型解压
		Connection unzipCoon =  SshUtil.login(ip,userName,password);
		String result = SshUtil.execute(unzipCoon, buildBuffer.toString());
		return result;
	}

注意:远程连接的代码在以前的文章里有,可以去查阅。

1、首先通过CD名称进入到存放dockerfile的文件夹,然后执行镜像build命令: docker build -t imageName:imageTag . 

2、构建命令最后的. 一定不能省略。

3.2.2获取镜像ID

        构建镜像有时会没有那么快,可以通过接口获取镜像ID:

public R getImageID(EnginesModelImageEntity image) {
		if(ObjectUtils.isEmpty(dockerClient)){
			initDockerClient();
		}
		String tag = image.getImageName() + ":" + image.getImageTag();
		List<Image> images = dockerClient.listImagesCmd().withImageNameFilter(image.getImageName()).exec();
		if(images.isEmpty()){
			return R.fail("镜像构建中,请稍后再试!");
		}
		String imageId = "";
		for(Image i : images){
			if(Arrays.asList(i.getRepoTags()).contains(tag)){
				String id = i.getId();
				imageId = id.substring(id.indexOf(":")+1,id.indexOf(":")+13);
			}
		}
		if(ObjectUtils.isNotEmpty(imageId)){
			image.setImageId(imageId);
			image.setImageStatus("2");
			baseMapper.updateById(image);
			return R.success("获取镜像ID成功!");
		}
		return R.success("未查询到镜像ID,请稍后再试!");
	}

注意:如果使用同一个dockerfile文件构建镜像,则镜像ID是一致的,会存在多个镜像TAG,可以根据repoTags中是否包含自己的镜像标签来判断,镜像是否构建完成。

3.2.3删除镜像

docker-java删除镜像是通过镜像ID进行删除操作的:


    public void removeImage(DockerClient client,String imageId){
        dockerClient.removeImageCmd(imageId).exec();
    }

但是会把同一个dockerfile构造的镜像全部删除,我是通过镜像tag进行镜像删除操作的:

public boolean removeImage(Long id) {
		EnginesModelImageEntity image = baseMapper.selectById(id);
		if(ObjectUtils.isEmpty(dockerClient)){
			initDockerClient();
		}
		image.setImageStatus("3");
		if(baseMapper.updateById(image)>=0){
			String tag = image.getImageName() + ":" + image.getImageTag();
			//模型解压命令
			StringBuffer removeBuffer = new StringBuffer("");
			removeBuffer.append(ModelConstant.DOCKER_REMOVE)
				.append(tag);
			//调用远程命令进行模型解压
			Connection unzipCoon =  SshUtil.login(ip,userName,password);
			SshUtil.execute(unzipCoon, removeBuffer.toString());
			return true;
		}
		return false;
	}

注意:通过删除镜像命令:docker rmi imageName:imageTag进行镜像删除操作。

3.3容器管理

3.3.1创建容器

	private String createContainers(EnginesModelContainerEntity entity){
		EnginesModelImageEntity image = imageMapper.selectById(entity.getImageId());
		String result = "";
		for(int i=0;i<entity.getContainerNumber();i++){
			EnginesModelContainerChildEntity childEntity = new EnginesModelContainerChildEntity();
			childEntity.setModelId(entity.getModelId());
			String containerName = entity.getContainerName().replace(" ","") + ModelConstant.UNDERLINE +i;
			childEntity.setContainerName(containerName);
			childEntity.setContainerStatus("2");
			childEntity.setParentId(entity.getId());
			childEntity.setStatus(0);
			childEntity.setIsDeleted(0);
			childEntity.setCreateTime(new Date());
			childEntity.setCreateUser(entity.getCreateUser());
			String buffer = ModelConstant.DOCKER_RUN + containerName + ModelConstant.SPACE + image.getImageName() + ModelConstant.COLON + image.getImageTag();
			Connection pullCoon =  SshUtil.login(ip,userName,password);
			result = SshUtil.execute(pullCoon, buffer);
			if(ObjectUtils.isNotEmpty(result)){
				childMapper.insert(childEntity);
			}
		}

		return result;
	}

使用的远程ssh方式创建容器,容器启动命令:文章来源地址https://www.toymoban.com/news/detail-762436.html

docker run --gpus all -itd --name= containerName imageName:imageTag

4、远程服务器docker容器中写文件

public static void main(String[] args) {
		String containerId = "61cf0a2e4c4a0ae00ad8aa1193f3abfbdd9a48e6236f427d2c37fae23b84ae6f"; // Replace with your container ID
		String filePath = "/opt/model/twoHydrodynamic/ProcessData/Inflow_3.json";
		String fileContent = "Create JSON FILE";
		DockerClientService.initDockerClient("ip","docker端口");
		// 创建一个tar归档,将内容写入tar文件
		ByteArrayInputStream tarStream = null;
		try {
			tarStream = TarUtils.createTarArchive(filePath, fileContent);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}


		ExecCreateCmdResponse response = dockerClient.execCreateCmd(containerId)
			.withCmd("tar", "-C", "/", "-x")
			.withAttachStdout(true)
			.withAttachStderr(true)
			.exec();
		ExecStartCmd startCmd = dockerClient.execStartCmd(response.getId())
			.withDetach(false)
			.withTty(true);
		ExecStartResultCallback callback = new ExecStartResultCallback();

		startCmd.exec(callback);
		// 发送tar归档数据
		dockerClient.copyArchiveToContainerCmd(containerId)
			.withRemotePath("/")
			.withTarInputStream(tarStream)
			.exec();
		// 关闭tarStream
		try {
			tarStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

5、远程服务器docker容器中读文件

	public static void main(String[] args) {
		String containerId = "61cf0a2e4c4a0ae00ad8aa1193f3abfbdd9a48e6236f427d2c37fae23b84ae6f"; // Replace with your container ID
		String filePath = "/opt/model/twoHydrodynamic/OutputData/X2DProcess.dat";
		DockerClientService.initDockerClient("IP","docker端口");
		String taskId = UUID.randomUUID().toString();
		String basePath = "/Users/admin/Documents/shuke/modelFile/depth/"+taskId;
		File folder = new File(basePath);
		//如果文件夹不存在,则创建文件夹
		if (!folder.exists()) {
			folder.mkdirs();
		}
		String outPath = basePath + "/X2DProcess.dat";
		try {
			InputStream inputStream = dockerClient.copyArchiveFromContainerCmd(containerId, filePath).exec();
			try (OutputStream outputStream = new FileOutputStream(outPath)) {
				byte[] buffer = new byte[1024];
				int bytesRead;
				while ((bytesRead = inputStream.read(buffer)) != -1) {
					outputStream.write(buffer, 0, bytesRead);
				}

			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			contentGet(folder,outPath,taskId);
		} catch (NotFoundException e) {
			System.err.println("Container not found: " + e.getMessage());
		} catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
	}

到了这里,关于java集成Docker-java实现远程镜像、容器创建,服务发布的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Docker 的数据管理、容器互联、镜像创建

    目录 一、数据管理 1.数据卷 2. 数据卷容器 二、容器互联(使用centos镜像) 三、Docker 镜像的创建 1.基于现有镜像创建 1.1首先启动一个镜像,在容器里修改 1.2将修改后的容器提交为新的镜像,需使用该容器的id号创建新镜像 2.基于本地模板创建 2.1下载模板文件生成镜像  2

    2024年02月16日
    浏览(49)
  • (docker)mysql镜像拉取-创建容器-容器的使用【个人笔记】

    容器的第一次创建,需要先下载镜像,从 0、可以搜索镜像的版本 1、先拉取MySQL的镜像,默认拉取最新版,使用下面的命令拉取mysql镜像 也可以指定mysql的版本(我这里指定的是5.6版本) 2、在~(/root)目录下创建一个mysql的文件夹,用于保存mysql产生的数据,并进入mysql文件 在/

    2024年02月13日
    浏览(35)
  • docker-java

    2.1 docker已安装 2.2 运行程序用户的docker使用权限 默认docker安装后是root权限运行的,比如运行程序的用户是admin用户,则需要将admin用户加加入到docker用户组 gpasswd -a admin docker systemctl restart docker 2.3 docker.service 的访问方式,需要开启tcp访问默认,不然可能导致非root用户运行程序

    2024年02月10日
    浏览(27)
  • Docker概念|容器|镜像|命令详细(创建,删除,修改,添加)

    Docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源 是在Linux容器里运行应用的开源工具 是一种轻量级的”虚拟机“ Docker的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的,可移植的,自给自足的容器。 docker本质就是宿主机的一个进程,

    2023年04月19日
    浏览(37)
  • Docker容器与虚拟化技术:Docker镜像创建、Dockerfile实例

    目录 一、理论 1.Docker镜像的创建方法 2.Docker镜像结构的分层 3.Dockerfile 案例 4.构建Systemctl镜像(基于SSH镜像) 5.构建Tomcat 镜像 6.构建Mysql镜像 二、实验 1.Docker镜像的创建 2. Dockerfile 案例 3.构建Systemctl镜像(基于SSH镜像) 三、问题 1.nginx网页打不开  2.Apache容器启动一直为Ex

    2024年02月12日
    浏览(43)
  • Docker容器:docker数据管理、镜像的创建及dockerfile案例

    因为数据写入后如果停止了容器,再开启数据就会消失,使用数据管理的数据卷挂载,实现了数据的持久化,重启数据还会存在;还有一种方式,容器之间共享文件即相当于有个备份,也会解决停止容器后数据消失的问题。 管理 Docker 容器中数据主要有两种方式:数据卷(

    2024年02月12日
    浏览(40)
  • docker容器:docker镜像的三种创建方法及dockerfile案例

    目录 一、基于现有镜像创建 1、创建启动镜像 2、生成新镜像 二、基于本地模板创建  1、OPENVZ 下载模板 2、导入容器生成镜像 三、基于dockerfile创建  1、dockerfile结构及分层 2、联合文件系统 3、docker镜像加载原理 4、dockerfile操作常用的指令 (1)FROM指令 (2)MAINTAINER 指令 (3)RUN指令

    2023年04月20日
    浏览(48)
  • Docker:使用Nvidia官方的pytorch、tensorflow、TensorRT镜像创建Container容器

    文章目录 前言 一、前期准备 二、具体步骤 1.启动容器 2.使用容器 补充 相信大家在学习新的知识前都遇到过开发环境安装不上,或者环境冲突和版本不匹配的情况,另外当我们想要安装多个版本的支持库时,在本地环境上直接安装往往会导致版本冲突的情况,如果我们使用

    2024年02月19日
    浏览(35)
  • Docker在windows下使用教程,通过Dockerfile创建镜像/容器,以YOLO系列为例

     通过可视化界面将极大的降低学习难度。  1.1、Docker Desktop下载  下载地址:Docker Desktop: The #1 Containerization Tool for Developers | Docker 应当是这个界面,选择下载即可 1.2、下载完成后需打开window自带的虚拟机       将Hyper-V勾选即打开,勾选后需重启。  1.3、下载WSL,由于是在

    2024年02月05日
    浏览(44)
  • 逸学Docker【java工程师基础】2.Docker镜像容器基本操作+安装MySQL镜像运行

    在这里我们的应用程序比如redis需要构建成镜像, 它作为一个Docker文件就可以进行 构建 ,构建完以后他是在 本地的 ,我们可以 推送 到镜像服务器,逆向可以 拉取 到上传的镜像,或者说我们可以保存为 压缩包 进行 相互传递 。 在本地的镜像可以传来传去,本身也可以查看

    2024年02月01日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包