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

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


作者:watermelo37

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

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

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

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

image.gif 编辑

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

image.gif 编辑

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

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

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

二、安装Docker

1、安装Docker

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

2、启动Docker

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

docker --version

image.gif

三、使用Java后端操作docker

image.gif 编辑

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"]

image.gif

       其中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();
    }

image.gif

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();
        }
    }

image.gif

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用法详解

目录
打赏
0
0
0
0
7
分享
相关文章
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
50 17
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
以上内容是一个简单的实现在Java后端中通过DockerClient操作Docker生成python环境并执行代码,最后销毁的案例全过程,也是实现一个简单的在线编程后端API的完整流程,你可以在此基础上添加额外的辅助功能,比如上传文件、编辑文件、查阅文件、自定义安装等功能。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
90 11
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
构建高效Java后端与前端交互的定时任务调度系统
通过以上步骤,我们构建了一个高效的Java后端与前端交互的定时任务调度系统。该系统使用Spring Boot作为后端框架,Quartz作为任务调度器,并通过前端界面实现用户交互。此系统可以应用于各种需要定时任务调度的业务场景,如数据同步、报告生成和系统监控等。
41 9
|
15天前
|
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
当我们创建一个`ThreadPoolExecutor`的时候,你是否会好奇🤔,它到底发生了什么?比如:我传的拒绝策略、线程工厂是啥时候被使用的? 核心线程数是个啥?最大线程数和它又有什么关系?线程池,它是怎么调度,我们传入的线程?...不要着急,小手手点上关注、点赞、收藏。主播马上从源码的角度带你们探索神秘线程池的世界...
83 0
【源码】【Java并发】【线程池】邀请您从0-1阅读ThreadPoolExecutor源码
智慧产科一体化管理平台源码,基于Java,Vue,ElementUI技术开发,二开快捷
智慧产科一体化管理平台覆盖从备孕到产后42天的全流程管理,构建科室协同、医患沟通及智能设备互联平台。通过移动端扫码建卡、自助报道、智能采集数据等手段优化就诊流程,提升孕妇就诊体验,并实现高危孕产妇五色管理和孕妇学校三位一体化管理,全面提升妇幼健康宣教质量。
48 12
Java智慧工地(源码):数字化管理提升施工安全与质量
随着科技的发展,智慧工地已成为建筑行业转型升级的重要手段。依托智能感知设备和云物互联技术,智慧工地为工程管理带来了革命性的变革,实现了项目管理的简单化、远程化和智能化。
40 5
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
docker容器为啥会开机自启动
通过配置适当的重启策略,Docker容器可以在主机系统重启后自动启动。这对于保持关键服务的高可用性和自动恢复能力非常有用。选择适合的重启策略(如 `always`或 `unless-stopped`),可以确保应用程序在各种情况下保持运行。理解并配置这些策略是确保Docker容器化应用可靠性的关键。
289 93

热门文章

最新文章