当前位置: 首页 > news >正文

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

目录

干货含源码!如何用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用法详解

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Redis在服务器启动的日志问题
  • 选择排序的动画展示与实现
  • Ubuntu20上的Qt程序连接Windows上的mssql服务器
  • Oracle(ORA-00214)-undo表空间文件损坏
  • 【Python机器学习】卷积神经网络(CNN)——语义理解
  • 深入解析C#中的锁机制:`lock(this)`、`lock(privateObj)`与`lock(staticObj)`的区别
  • 【C++】汇编分析,函数是如何调用,传参,返回
  • 四种NAT类型
  • OpenCVSharp中的图像数据结构与类型
  • 【PyQt6 应用程序】视频百叶窗效果一键生成模块
  • Android Studio gradle下载太慢了!怎么办?(已解决)
  • RO通讯数据包
  • Linux实现异步IO的方法:epoll,posix aio,libaio,io_uring
  • Datawhale x李宏毅苹果书AI夏令营深度学习详解进阶Task03
  • 基于生成对抗模型GAN蒸馏的方法FAKD及其在EdgesSRGAN中的应用
  • [nginx文档翻译系列] 控制nginx
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • Android组件 - 收藏集 - 掘金
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • Computed property XXX was assigned to but it has no setter
  • ES6核心特性
  • Java深入 - 深入理解Java集合
  • js中的正则表达式入门
  • MYSQL 的 IF 函数
  • nodejs调试方法
  • oschina
  • PermissionScope Swift4 兼容问题
  • Spark RDD学习: aggregate函数
  • Vue官网教程学习过程中值得记录的一些事情
  • 电商搜索引擎的架构设计和性能优化
  • 工作手记之html2canvas使用概述
  • 关于extract.autodesk.io的一些说明
  • 基于遗传算法的优化问题求解
  • 技术胖1-4季视频复习— (看视频笔记)
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 温故知新之javascript面向对象
  • 线上 python http server profile 实践
  • 一、python与pycharm的安装
  • #HarmonyOS:软件安装window和mac预览Hello World
  • %check_box% in rails :coditions={:has_many , :through}
  • (16)UiBot:智能化软件机器人(以头歌抓取课程数据为例)
  • (C语言)二分查找 超详细
  • (备忘)Java Map 遍历
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • ***监测系统的构建(chkrootkit )
  • **《Linux/Unix系统编程手册》读书笔记24章**
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .net core Swagger 过滤部分Api
  • .net 中viewstate的原理和使用
  • .NET/C# 避免调试器不小心提前计算本应延迟计算的值