干货含源码!如何用Java后端操作Docker(命令行篇)

news2024/11/14 14:26:51

目录

干货含源码!如何用Java后端操作Docker(命令行篇)

一、为什么要用后端程序操作Docker

二、安装Docker

1、安装Docker

2、启动Docker

三、使用Java后端操作docker

1、构建docker镜像并生成容器

2、执行完毕后删除容器和镜像

3、在此基础上开发其他功能

四、总结


作者:watermelo37

涉及领域:Vue、SpingBoot、Docker、LLM、python等

---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

干货含源码!如何用Java后端操作Docker(命令行篇)

一、为什么要用后端程序操作Docker

        Docker 是现代开发和部署流程中不可或缺的一部分。它简化了应用程序的环境配置、打包和分发,使得在不同机器上运行相同的应用变得更加轻松和一致。本文将详细介绍如何使用命令行工具(CMD)操控 Docker 来配置环境。

        实现后端操作docker,可以用来实现云端IDE、一键环境搭建、多人协作环境、互动编程教学、可视化部署和管理等等功能。是Docker从服务器走向客户端的必经之路。

二、安装Docker

1、安装Docker

        我写过一份详细的博客,请移步:Docker 入门全攻略:安装、操作与常用命令指南

2、启动Docker

        安装完成后,启动 Docker Desktop,并确保其正常运行。可以在 CMD 中通过以下命令来验证:

docker --version

三、使用Java后端操作docker

1、构建docker镜像并生成容器

        这一步的目的是通过Docker根据本地目录中的DockerFlie文件、代码、和其他配置数据文件生成新的镜像,并生成容器。

        一个简单的DockerFile示例:

# 使用官方Python运行时作为父镜像
FROM python:3.8-slim

# 设置工作目录
WORKDIR /app

# 将当前目录内容复制到位于/app中的容器中
COPY . /app

# 安装requirements.txt中指定的任何所需包
RUN pip install --no-cache-dir -r requirements.txt

# 使端口80可供此容器外的环境使用
EXPOSE 80

# 定义环境变量
ENV NAME World

# 在容器启动时运行app.py
CMD ["python", "app.py"]

        其中0419test是构建镜像的tag名。

        注意修改工作目录,将其改为你实际的文件夹目录。

    public void buildImageAndContainer(){
        try {
            // 设置第一个命令:构建Docker镜像
            ProcessBuilder buildProcessBuilder = new ProcessBuilder("docker", "build", "-t", "test0419", ".");

            // 设置工作目录为 "E:\\code\\docker\\test"
            buildProcessBuilder.directory(new File("E:\\code\\docker\\test"));

            // 启动构建镜像的命令并等待其完成
            Process buildProcess = buildProcessBuilder.start();
            buildProcess.waitFor();

            // 读取并打印出构建镜像的输出
            printProcessOutput(buildProcess);

            // 检查构建是否成功
            if (buildProcess.exitValue() == 0) {
                // 设置第二个命令:运行Docker容器
                ProcessBuilder runProcessBuilder = new ProcessBuilder("docker", "run", "-v", "E:/code/docker/test:/app", "-p", "80:80", "test0419");

                // 启动运行容器的命令
                Process runProcess = runProcessBuilder.start();

                // 读取并打印出运行容器的输出
                printProcessOutput(runProcess);

                // 可以在这里等待容器运行的进程结束,或者根据需要进行其他操作
                // runProcess.waitFor();
            } else {
                System.out.println("Docker image build failed.");
            }
        } catch (IOException | InterruptedException e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }

    // 输出打印内容的私有方法
    private static String printProcessOutput(Process process) throws IOException {
        String output;
        String errorInfo;
        // 读取并打印标准输出
        output = readAndPrint(process.getInputStream(), "");
        // 读取并打印标准错误
        errorInfo = readAndPrint(process.getErrorStream(), "");
        return output+errorInfo;
    }
    private static String readAndPrint(InputStream inputStream, String prefix) throws IOException {
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(prefix).append(line).append(System.lineSeparator());
                System.out.println(prefix + line); // 同时打印到控制台
            }
        }
        return output.toString();
    }

2、执行完毕后删除容器和镜像

        删除容器和镜像,释放资源,一般在容器执行完代码之后运行。

    // 删除容器和镜像
    public String deleteContainerAndImage(String imageName){
        // 定义一个线程池用于执行删除操作
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 异步获取容器 ID 列表并删除容器
        executorService.submit(() -> {
            try {
                List<String> containerIds = new ArrayList<>();
                String command = "docker ps -a -q --filter ancestor=" + imageName;
                ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
                Process process = processBuilder.start();

                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    containerIds.add(line.trim());
                }

                int exitCode = process.waitFor();
                if (exitCode != 0) {
                    System.err.println("Command executed with error. Exit code: " + exitCode);
                    return ;
                }

                // 删除容器
                for (String containerId : containerIds) {
                    String deleteContainerCommand = "docker rm -f " + containerId;
                    executeCommand(deleteContainerCommand);
                }

            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 异步删除镜像
        executorService.submit(() -> {
            // 等待容器被删除
            try {
                TimeUnit.SECONDS.sleep(5); // 等待5秒,可以根据实际情况调整
                // 同样,如果你使用的是Docker,可以使用以下命令:
                String deleteImageCommand = "docker rmi " + imageName;
                executeCommand(deleteImageCommand);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 关闭线程池
        executorService.shutdown();

        return "镜像与容器已删除";
    }

    // 用来执行cmd命令的方法
    private void executeCommand(String command) {
        try {
            // 使用ProcessBuilder执行命令
            ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
            Process process = processBuilder.start();

            // 调用已有的方法来打印输出
            printProcessOutput(process);

            // 等待进程结束
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                // 处理非零退出码,可能表示命令执行出错
                System.err.println("Command executed with error. Exit code: " + exitCode);
            }
        } catch (IOException e) {
            // 处理命令执行过程中可能遇到的IO异常
            e.printStackTrace();
        } catch (InterruptedException e) {
            // 如果waitFor()方法被中断,重新设置中断状态并处理
            Thread.currentThread().interrupt();
            e.printStackTrace();
        } catch (Exception e) {
            // 处理命令字符串分割可能出现的异常
            e.printStackTrace();
        }
    }

3、在此基础上开发其他功能

        在生成与删除之间,就可以自由添加和微调其中的部分步骤,比如删除DockerFile中的CMD ["python", "app.py"],让容器持续化后台运行,这样就可以通过宿主机与容器的文件映射关系修改代码内容,然后择机运行代码了;又比如创建一个满足需求的镜像,然后只创建和删除容器来节省服务器资源等等。

四、总结

         只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        更多优质内容,请关注:

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        shpfile转GeoJSON且控制转化精度;如何获取GeoJSON?GeoJson结构详解

        Docker 入门全攻略:安装、操作与常用命令指南

        通过array.reduce()实现数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式等

        巧用Array.forEach:简化循环与增强代码可读性

        Mapbox添加行政区矢量图层、分级设色图层、自定义鼠标悬浮框、添加天地图底图等

        管理数据必备!侦听器watch用法详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2098236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么删除谷歌浏览器的下载记录

定期删除谷歌浏览器的下载记录&#xff0c;对于保护个人隐私和提升浏览器性能都非常的重要。为了帮助大家安全的进行谷歌浏览器下载记录的清除&#xff0c;本文为大家分享了实用的操作方法&#xff0c;一起来看看吧。 删除谷歌浏览器下载记录的原因说明 1、保护隐私&#xff1…

【算法 动态规划 简单多状态 dp 问题】打家劫舍题型

打家劫舍题型 按摩师 (easy)解题思路代码 打家劫舍II &#xff08;medium&#xff09;解题思路代码 删除并获得点数&#xff08;medium&#xff09;解题思路代码 按摩师 (easy) 题目链接 该题是打家劫舍的变形 解题思路 状态表示 分析: 注意题目, 对于当天的预约, 可以接受…

车辆远控功能自动化测试方案:打造高效可靠的测试流程

随着汽车逐步走向智能化、网联化&#xff0c;整车的功能已经不再局限于驾驶员在车内进行本地操作。在远离车辆时&#xff0c;驾驶员也可以通过手机APP下发控制指令来实现对车辆的远程控制。 近几年&#xff0c;伴随远控功能项不断增多&#xff0c;其功能逻辑也越来越复杂&…

python开发--信息的增删改

部门信息的增删改 1. 增加 点击新建部门 跳转到新建部门页面&#xff1a;http://127.0.0.1:8000/depart/add/ 在views.py里面增加如下代码&#xff0c;可以将用户输入的信息添加到数据库中 def depart_add(request):if request.method GET:return render(request, depart…

STL之my_list容器

前言&#xff1a;各位老铁好久不见了&#xff0c;今天分享的知识是自己实现一个简单的list容器&#xff0c;为什么我先跳过vector容器的自我实现呢&#xff1f;我个人觉得vector相对于list的自我实现简单一点&#xff0c;所以今天先分享实现my_list的知识 我们要实现my_list&a…

machine learning - 2

泛化误差 也可以认为是预测时的误差。 训练误差 并不是越小越好&#xff0c;太小会过拟合。 获得测试集合的方法&#xff1a; 1&#xff09;&#xff1a; 2&#xff09;&#xff1a;例如&#xff1a;k-折交叉验证法&#xff0c; 就的每k个数据取一个座位测试集 3&#xff0…

nginx容器映射配置文件后,启动一直报错提示:failed (13: Permission denied)的排查

问题现象&#xff1a; 使用harbor 的install.sh 创建docker-compose之后&#xff0c;出现nginx容器一直重启。 查看日志发现是&#xff1a;配置文件无权限。报错信息如下&#xff1a; Sep 2 16:43:13 172.28.0.1 nginx[1344]: 2024/09/02 08:43:13 [emerg] 1#0: open() “/e…

网站网站建设公司用什么

随着互联网的飞速发展&#xff0c;网站已经成为企业的重要门面和宣传工具。为了在网上展示自己的品牌形象和吸引更多的客户&#xff0c;越来越多的企业选择找专业的网站建设公司进行网站建设。那么&#xff0c;网站建设公司主要使用什么技术和方法呢&#xff1f; 首先&#xff…

四、基本电路设计笔记——4.1 DC-DC稳压电路

目录 4.1 DC-DC稳压电路 4.1.1 基于MT2492的DC-DC稳压电路 &#xff08;1&#xff09;芯片参数 &#xff08;2&#xff09;芯片引脚 &#xff08;3&#xff09;输出电压设置 4.1.2 基于MT2499A的DC-DC稳压电路 &#xff08;1&#xff09;芯片参数 &#xff08;2&#xf…

【Redis】Redis 主从复制

文章目录 1 前言2 主从模式介绍3 配置 Redis 主从结构3.1 建立复制3.2 断开复制3.3 其他特性3.4 拓扑结构 4 Redis 主从复制原理4.1 复制过程4.2 PSYNC 数据同步4.3 PSYNC 运行流程 5 主从复制流程5.1 全量复制流程5.2 部分复制流程5.3 实时复制流程 1 前言 分布式系统中存在一…

鸿誉移民:定制化移民服务,吹响全球高效率移民的嘹亮号角!

鸿誉移民&#xff1a;定制化移民服务&#xff0c;吹响全球高效率移民的嘹亮号角&#xff01; 作为国内知名海外移民服务机构&#xff0c;鸿誉移民历经多年行业沉淀&#xff0c;拥有着极其丰富的移民咨询以及移民办理经验&#xff0c;并以咨询及时精准&#xff0c;签证快捷、通…

Bean 的实例化(创建 | 获取)

Spring为Bean提供了多种实例化方式&#xff0c;包括如下4种方式&#xff1a; 第一种&#xff1a;通过构造方法实例化第二种&#xff1a;通过简单工厂模式实例化第三种&#xff1a;通过factory-bean实例化&#xff08;工厂方法模式实例化&#xff09;第四种&#xff1a;通过Fact…

智能未来:低代码与AI如何重塑企业应用开发

引言 在当今瞬息万变的商业环境中&#xff0c;企业面临着前所未有的挑战与机遇。数字化转型已经成为各行各业的必然趋势&#xff0c;而在这一过程中&#xff0c;应用开发的效率与智能化程度成为企业竞争力的重要衡量标准。传统的开发模式往往需要大量的时间和资源&#xff0c;而…

【Godot4.3】基于ShapePoints的Polygon2D扩展

概述 这同样是来自2023年7月份的一项实验性工作&#xff0c;基于最初版本的ShapePoints静态函数库&#xff0c;实现了对Polygon2D节点的扩展&#xff0c;用于创建参数化图形的Polygon2D节点。 Polygon2D节点本身只能通过顶点绘制工具&#xff0c;创建很随意的多边形。通过Sha…

MySQL数据库管理系统下载安装

一. MySQL概述&#xff1a; 1.数据库相关概念 数据库&#xff1a;存储数据的仓库&#xff0c;数据是有组织地进行存储&#xff08;DataBase 简DB&#xff09;数据库管理系统&#xff1a;操纵和管理数据库的大型软件 &#xff08;DataBase Management System 简DBMS)SQL:操…

一分钟创建自己的分班查询系统,家长扫码即可进群

开学后&#xff0c;老师们的忙碌也达到了顶峰。整理教材、准备课程计划、布置教室&#xff0c;这些工作已经让人应接不暇&#xff0c;更别提还要处理分班事宜。以往&#xff0c;老师们需要一个个通知家长分班结果&#xff0c;这不仅耗时耗力&#xff0c;还容易出错。家长们也常…

​数字IC设计基本概念之多时钟设计​

当设计中使用了多个时钟时&#xff0c;这些时钟域之间的关系可能是synchronous、asynchronous或者exclusive的。如下所示&#xff1a; Synchronous&#xff1a; Asynchronous&#xff1a; Exclusive&#xff1a; 需要人为地指定设计中时钟之间的关系&#xff0c;EDA工具才能正…

燃油车淘汰倒计时开始了?

文 | AUTO芯球 作者 | 璇子 新能源车要取代燃油车了&#xff1f; 油车车主先别喷啊 就在上个月 新能源乘用车月销量数据一经公布 我一看 渗透率居然达到了惊人的51% 啥概念啊 如果卖100台车 51台都是新能源 其他49台才是燃油车 看到这数据 有好多看热闹的人就在说 …

Vue组件:创建组件、注册组件、使用组件

1、创建组件 组件&#xff08;component&#xff09;是 Vue.js 最强大的功能之一。通过开发组件可以封装可服用的代码&#xff0c;将封装好的代码注册成标签&#xff0c;扩展 HTML 元素的功能。几乎任意类型应用的界面都可以抽象为一个组件树&#xff0c;而组件树可以用独立可…

【完-移动云-基础】移动云架构和ECS

一、移动云产品架构 产品架构分为IaaS、PaaS、SaaS 我司使用的是IaaS&#xff0c;仅托管了服务器资源。软件则由浪潮提供。 一图理解三者区别 二、云主机ECS 是一种弹性按需提供的云端服务器&#xff0c;可选择不同的配置 基础服务&#xff1a; 虚拟化、镜像、云硬盘、云…