使用Java后端操作Docker的詳細(xì)教程
一、為什么要用后端程序操作Docker
Docker 是現(xiàn)代開發(fā)和部署流程中不可或缺的一部分。它簡化了應(yīng)用程序的環(huán)境配置、打包和分發(fā),使得在不同機(jī)器上運(yùn)行相同的應(yīng)用變得更加輕松和一致。本文將詳細(xì)介紹如何使用命令行工具(CMD)操控 Docker 來配置環(huán)境。
實(shí)現(xiàn)后端操作docker,可以用來實(shí)現(xiàn)云端IDE、一鍵環(huán)境搭建、多人協(xié)作環(huán)境、互動編程教學(xué)、可視化部署和管理等等功能。是Docker從服務(wù)器走向客戶端的必經(jīng)之路。
二、安裝Docker
1、安裝Docker
我寫過一份詳細(xì)的博客,請移步:Docker的基本概念、安裝步驟以及一些簡單的用法_docker_腳本之家
2、啟動Docker
安裝完成后,啟動 Docker Desktop,并確保其正常運(yùn)行??梢栽?CMD 中通過以下命令來驗(yàn)證:
docker --version
三、使用Java后端操作docker
1、構(gòu)建docker鏡像并生成容器
這一步的目的是通過Docker根據(jù)本地目錄中的DockerFlie文件、代碼、和其他配置數(shù)據(jù)文件生成新的鏡像,并生成容器。
一個簡單的DockerFile示例:
# 使用官方Python運(yùn)行時作為父鏡像 FROM python:3.8-slim # 設(shè)置工作目錄 WORKDIR /app # 將當(dāng)前目錄內(nèi)容復(fù)制到位于/app中的容器中 COPY . /app # 安裝requirements.txt中指定的任何所需包 RUN pip install --no-cache-dir -r requirements.txt # 使端口80可供此容器外的環(huán)境使用 EXPOSE 80 # 定義環(huán)境變量 ENV NAME World # 在容器啟動時運(yùn)行app.py CMD ["python", "app.py"]
其中0419test是構(gòu)建鏡像的tag名。
注意修改工作目錄,將其改為你實(shí)際的文件夾目錄。
public void buildImageAndContainer(){ try { // 設(shè)置第一個命令:構(gòu)建Docker鏡像 ProcessBuilder buildProcessBuilder = new ProcessBuilder("docker", "build", "-t", "test0419", "."); // 設(shè)置工作目錄為 "E:\\code\\docker\\test" buildProcessBuilder.directory(new File("E:\\code\\docker\\test")); // 啟動構(gòu)建鏡像的命令并等待其完成 Process buildProcess = buildProcessBuilder.start(); buildProcess.waitFor(); // 讀取并打印出構(gòu)建鏡像的輸出 printProcessOutput(buildProcess); // 檢查構(gòu)建是否成功 if (buildProcess.exitValue() == 0) { // 設(shè)置第二個命令:運(yùn)行Docker容器 ProcessBuilder runProcessBuilder = new ProcessBuilder("docker", "run", "-v", "E:/code/docker/test:/app", "-p", "80:80", "test0419"); // 啟動運(yùn)行容器的命令 Process runProcess = runProcessBuilder.start(); // 讀取并打印出運(yùn)行容器的輸出 printProcessOutput(runProcess); // 可以在這里等待容器運(yùn)行的進(jìn)程結(jié)束,或者根據(jù)需要進(jìn)行其他操作 // runProcess.waitFor(); } else { System.out.println("Docker image build failed."); } } catch (IOException | InterruptedException e) { System.out.println(e); e.printStackTrace(); } } // 輸出打印內(nèi)容的私有方法 private static String printProcessOutput(Process process) throws IOException { String output; String errorInfo; // 讀取并打印標(biāo)準(zhǔn)輸出 output = readAndPrint(process.getInputStream(), ""); // 讀取并打印標(biāo)準(zhǔn)錯誤 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、執(zhí)行完畢后刪除容器和鏡像
刪除容器和鏡像,釋放資源,一般在容器執(zhí)行完代碼之后運(yùn)行。
// 刪除容器和鏡像 public String deleteContainerAndImage(String imageName){ // 定義一個線程池用于執(zhí)行刪除操作 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秒,可以根據(jù)實(shí)際情況調(diào)整 // 同樣,如果你使用的是Docker,可以使用以下命令: String deleteImageCommand = "docker rmi " + imageName; executeCommand(deleteImageCommand); } catch (InterruptedException e) { e.printStackTrace(); } }); // 關(guān)閉線程池 executorService.shutdown(); return "鏡像與容器已刪除"; } // 用來執(zhí)行cmd命令的方法 private void executeCommand(String command) { try { // 使用ProcessBuilder執(zhí)行命令 ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); Process process = processBuilder.start(); // 調(diào)用已有的方法來打印輸出 printProcessOutput(process); // 等待進(jìn)程結(jié)束 int exitCode = process.waitFor(); if (exitCode != 0) { // 處理非零退出碼,可能表示命令執(zhí)行出錯 System.err.println("Command executed with error. Exit code: " + exitCode); } } catch (IOException e) { // 處理命令執(zhí)行過程中可能遇到的IO異常 e.printStackTrace(); } catch (InterruptedException e) { // 如果waitFor()方法被中斷,重新設(shè)置中斷狀態(tài)并處理 Thread.currentThread().interrupt(); e.printStackTrace(); } catch (Exception e) { // 處理命令字符串分割可能出現(xiàn)的異常 e.printStackTrace(); } }
3、在此基礎(chǔ)上開發(fā)其他功能
在生成與刪除之間,就可以自由添加和微調(diào)其中的部分步驟,比如刪除DockerFile中的CMD ["python", "app.py"],讓容器持續(xù)化后臺運(yùn)行,這樣就可以通過宿主機(jī)與容器的文件映射關(guān)系修改代碼內(nèi)容,然后擇機(jī)運(yùn)行代碼了;又比如創(chuàng)建一個滿足需求的鏡像,然后只創(chuàng)建和刪除容器來節(jié)省服務(wù)器資源等等。
四、總結(jié)
到此這篇關(guān)于使用Java后端操作Docker的詳細(xì)教程的文章就介紹到這了,更多相關(guān)Java后端操作Docker內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring中WebClient的創(chuàng)建和使用詳解
這篇文章主要介紹了Spring中WebClient的創(chuàng)建和使用詳解,在Spring5中,出現(xiàn)了Reactive響應(yīng)式編程思想,并且為網(wǎng)絡(luò)編程提供相關(guān)響應(yīng)式編程的支持,如提供了WebFlux,它是Spring提供的異步非阻塞的響應(yīng)式的網(wǎng)絡(luò)框架,需要的朋友可以參考下2023-11-11spring boot 統(tǒng)一JSON格式的接口返回結(jié)果的實(shí)現(xiàn)
這篇文章主要介紹了spring boot 統(tǒng)一JSON格式的接口返回結(jié)果的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10解決springboot利用ConfigurationProperties注解配置數(shù)據(jù)源無法讀取配置信息問題
今天在學(xué)習(xí)springboot利用ConfigurationProperties注解配置數(shù)據(jù)源的使用遇到一個問題無法讀取配置信息,發(fā)現(xiàn)全部為null,糾結(jié)是哪里出了問題呢,今天一番思考,問題根源找到,下面把我的解決方案分享到腳本之家平臺,感興趣的朋友一起看看吧2021-05-05Java匿名內(nèi)部類和Lambda(->) 的多種寫法總結(jié)
這篇文章主要和大家分享一下Java匿名內(nèi)部類和Lambda(->) 的多種寫法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定幫助,需要的可以先看一下2022-07-07掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用
這篇文章主要介紹了掌握SpringMVC中@InitBinder的實(shí)際應(yīng)用,@InitBinder是Spring MVC框架中的一個注解,用于自定義數(shù)據(jù)綁定的方法,通過在控制器中使用@InitBinder注解,可以將特定的數(shù)據(jù)綁定邏輯應(yīng)用于請求參數(shù)的處理過程中,需要的朋友可以參考下2023-10-10SpringBoot快速實(shí)現(xiàn)接口消息加密的過程詳解
在項目中,為了保證數(shù)據(jù)的安全,我們常常會對傳遞的數(shù)據(jù)進(jìn)行加密,常用的加密算法包括對稱加密(AES)和非對稱加密(RSA),博主選取碼云上最簡單的API加密項目進(jìn)行下面的講解,需要的朋友可以參考下2023-11-11Java實(shí)現(xiàn)動態(tài)創(chuàng)建類操作示例
這篇文章主要介紹了Java實(shí)現(xiàn)動態(tài)創(chuàng)建類操作,結(jié)合完整示例形式分析了Java動態(tài)創(chuàng)建類的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2020-02-02