WSL2+Docker+IDEA一站式開發調試

来源:https://www.cnblogs.com/yuque/archive/2022/05/18/16284976.html
-Advertisement-
Play Games

回溯法(98條消息) (新手向)遞歸與回溯演算法學習(一)——n位逐位整除數_TripleGold.的博客-CSDN博客 演算法思想: (通用的解題法)窮舉的搜索嘗試過程,主要是在搜索嘗試過程中尋找問題的解,當發現不滿足求解條件時就回退,嘗試其他路徑 回溯法的解題步驟: 針對給定問題確定問題的解空間樹, ...


WSL2+Docker+IDEA一站式開發調試

前言

​ 我們知道,Docker是一個容器引擎;對於開發者來說,使用Dokcer容器部署各種開發需要的中間件(比如myql、redis)會非常簡單方便;效率更高。Docker天生是完美支持Linux的,但大多數開發者都是在windows環境下進行開發,雖然Docker也相容Windows;但並不是那麼完美。好在,微軟推出了WSL2(全稱:Windows Subsystem for Linux),即Windows的Linux子系統;子系統運行真正的 Linux 內核,可以完美支持Docker。而新版IDEA支持Docker遠程連接進行開發調試。因此WSL2+Docker+IDEA進行開發可以說是最佳搭配。本文就是介紹如何使用這三者搭建開發環境的。

環境配置

WSL2:安裝的是CentOS7

Docker:版本20.10.14;已開啟遠程訪問;開啟方式可參考文章:docker開啟遠程訪問

IDEA:版本為2022.1.1

創建springboot應用

為了測試環境效果,我們先簡單創建一個最基礎的springboot應用,打開IDEA,選擇New Project,如圖:

image-20220513101201525

圖示修改說明:

① 原URL為https://start.spring.io ;可能會因為網路問題無法訪問而導致創建失敗,因此改為:https://start.aliyun.com

② 自定義項目名稱

③ 自定義項目存放目錄

④ 按需選擇JDK和JAVA版本

上面信息填寫完成後,點擊Next:

image-20220513102032850

在這一步,只勾選 Lombok 和 Spring Web即可。然後點擊Create,即可創建一個最簡單的springboot應用。創建完成後的pom.xml內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>dev-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dev-demo</name>
    <description>dev-demo</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.example.devdemo.DevDemoApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

我們再新建一個controller包,在包中新建一個DemoController類,在類中添加一個web響應介面:

package com.example.devdemo.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@RestController
public class DemoController {
    @RequestMapping("/test")
    public String test(){
        log.info("測試介面:Hello world, docker!");
        return "Hello world, docker!" + new SimpleDateFormat(" [yyyy-MM-dd HH:mm:ss]").format(new Date());
    }
}

以上,我們的demo應用創建完畢,點擊運行,然後訪問:http://localhost:8080/test 即可看到如下效果:

image-20220513103415194

配置IDEA遠程連接Docker進行打包部署併進行debug調試

IDEA遠程連接Docker的方式有兩種:分別是IDEA自帶插件方式和maven插件方式

方式一:IDEA插件遠程連接Docker打包部署

  1. 在idea中配置docker遠程連接

    image-20220513110804087

    如圖,在設置中填寫好Name和Engine API URL後,如果顯示Connection successful即為成功連接到遠程docker。URL中的windows.wsl為我的WSL2地址,我做了host映射。

    踩坑記錄:如果是使用WSL2的,windows.wsl可以改為localhost;但經過測試,在win10的wsl2中,使用localhost能成功連接docker;但在win11中卻不行。如果localhost無法連接到wsl2的Docker,則需要使用腳本對wsl2進行固定IP,然後像我一樣做host映射即可;可參考我另一篇文章:WSL2-CenOS7固定IP,這裡不再表述。

  2. 創建Dockerfile併進行運行環境配置

    • 在項目根目錄下創建Dockerfile文件,並寫入如下內容:

      # Docker image for springboot application
      # VERSION 0.0.1
      # Author: Lunfy
      
      ### 基礎鏡像; 直接基於java8運行
      FROM anapsix/alpine-java
      
      #作者
      MAINTAINER Lunfy <[email protected]>
      
      #系統編碼
      ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
      
      #設置時區
      ENV TZ=Asia/Shanghai
      RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
      
      #聲明一個掛載點,容器內此路徑會對應宿主機的某個文件夾
      VOLUME /tmp
      
      #應用構建成功後的jar文件被覆制到鏡像內,名字也改成了app.jar
      ADD target/dev-demo-0.0.1-SNAPSHOT.jar app.jar
      
      #暴露8080埠;5005為遠程調試埠,根據需要選擇是否暴露
      EXPOSE 8080 5005
      
      #啟動容器時的進程
      #ENTRYPOINT ["java","-jar","/app.jar"]
      
      #遠程調試
      ENTRYPOINT ["java","-jar","-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005","app.jar"]
      
      
    • 如圖所示創建一個配置文件

      image-20220513112748302

      image-20220513112956771

    • 配置詳情如下圖:

      image-20220513115754239

      上圖中Run Maven Goal添加配置運行前的mavne打包命令為:clean package -U -DskipTests; 註意,不帶mvn指令;表示每次在構建鏡像之前,都會將當前工程清理掉並且重新編譯構建

    • 設置完成後,點擊下圖紅框中的綠色三角按鈕,運行此配置

      image-20220513132232044

  3. 運行結果

    • 運行後,控制台效果如下:

      image-20220513132728043

    • 打開瀏覽器,輸入http://localhost:18080/test;效果如下:

      image-20220513132839952

    • 打開WSL2,使用docker命令查看鏡像和容器

      查看鏡像:docker images 查看容器:docker ps -a

      image-20220513133029590

  4. 遠程debug配置

    上面我們已完成了應用的容器構建和部署運行;但作為開發,也許我們還會經常用到debug功能;但應用部署在遠程docker容器中,我們該怎麼進行debug呢?這時,我們就需要用到IDEA的遠程debug功能了。

    • 和前面添加配置一樣,點擊Edit Configurations...創建配置文件

      image-20220513112748302

      image-20220513133830262

    • 配置詳情如圖:

      image-20220513134728976

      需要特別說明的是,之前dockerfile配置文件的ENTRYPOINT開啟遠程調試的配置,就是從Command line arguments for remote JVM這裡複製的命令。另外,因為我是WSL2,所以遠程主機填的是localhost;埠可根據需要自定義。

    • 開始遠程debug;

      image-20220513135447563

      我們給應用打上斷點,然後點擊debug圖標開始運行。之後在控制台出現“Connected to the target VM”字樣,即為成功連接到遠程的虛擬機上。這時,再次在瀏覽器訪問 http://localhost:18080/test 即可看到程式進入斷點:

      image-20220513135755178

至此,IDEA插件方式遠程連接打包部署並遠程調試完畢。

方式二:MAVEN插件遠程連接Docker打包部署(推薦)

  1. 創建Dockerfile(在此直接使用方式一的Dockerfile文件,如沒有,需創建)。

  2. 在pom.xml中配置插件信息;參考:docker-maven-plugin插件官方文檔標簽中添加如下配置:

                <!-- docker-maven-plugin 插件 -->
                <plugin>
                    <groupId>io.fabric8</groupId>
                    <artifactId>docker-maven-plugin</artifactId>
                    <version>0.39.1</version>
                    <!-- 全局配置 -->
                    <configuration>
                        <!-- 這一部分是為了實現對遠程docker容器的控制 -->
                        <!-- docker主機地址,用於完成docker各項功能;tcp或者http均可! -->
                        <dockerHost>tcp://localhost:2375</dockerHost>
                        <!-- <dockerHost>http://localhost:2375</dockerHost> -->
    
                        <!-- 這一部分是為了實現docker鏡像的構建和推送,如果不需要可不配置; 比如我就只是在本地WSL環境開發,所以不配置 -->
                        <!-- registry地址,用於推送,拉取鏡像
                        <registry>registry.example.com</registry>
                        <authConfig>
                            <push>
                                <username>這裡填registry的用戶名</username>
                                <password>這裡填registry的密碼</password>
                            </push>
                        </authConfig>
                        -->
    
                        <!-- 鏡像相關配置,支持多鏡像-->
                        <images>
                            <!-- 單個鏡像配置 -->
                            <image>
                                <!-- 鏡像名(含標簽); 標準鏡像名格式為:命名空間/倉庫名稱:鏡像標簽;如標簽不填,則預設為latest -->
                                <!--例: <name>lunfy/devdemo:test</name>  -->
                                <name>lunfy/devdemo</name>
                                <!-- 鏡像別名;可用於作為容器名(服務名稱) -->
                                <alias>demo-service</alias>
                                <build>
                                    <!-- 可指定Dockerfile目錄或者指定Dockerfile文件;配置二選一即可 -->
    
                                    <!-- 指定dockerfile所在目錄 -->
                                    <!-- <contextDir>${project.basedir}</contextDir> -->
    
                                    <!-- 指定dockerfile文件的位置 -->
                                    <dockerFile>${project.basedir}/Dockerfile</dockerFile>
                                </build>
    
                                <!-- 配置docker-compose文件
                                <external>
                                    <type>compose</type>
                                    <basedir>${project.basedir}/docker</basedir>
                                    <composeFile>docker-compose.yml</composeFile>
                                </external>
                                -->
    
                                <run>
                                    <!-- 容器運行埠映射,對應docker的 -p 命令 -->
                                    <ports>
                                        <port>28080:8080</port>
                                        <port>5005:5005</port>
                                    </ports>
                                    <!-- 容器命名策略:alias:使用鏡像別名作為容器名;none:隨機命名 -->
                                    <namingStrategy>alias</namingStrategy>
                                </run>
    
                            </image>
                        </images>
                    </configuration>
    
                    <executions>
                        <execution>
                            <id>docker-exec</id>
                            <!-- 綁定mvn install階段,當執行mvn install時 就會執行docker stop、docker build、docker start -->
                            <phase>install</phase>
                            <goals>
                                <!-- 要先停止並刪除容器,否則下一步刪除鏡像會報錯 -->
                                <goal>stop</goal>
                                <!-- 刪除鏡像;此步可省略,build構建的時候會自動刪除 -->
                                <!-- <goal>remove</goal>  -->
                                <!-- 構建鏡像 -->
                                <goal>build</goal>
                                <!-- 啟動容器 -->
                                <goal>start</goal>
    
                                <!-- 運行容器:
                                 run和start的區別:
                                 run:在前臺運行docker容器,容器直接與idea聯動;日誌會直接輸出到idea控制台,可以在idea直接控制容器狀態。在idea點擊停止按鈕,容器停止運行。
                                 start: 在後臺運行docker容器;容器與idea解耦;日誌不會輸出到idea控制台;和正常在命令行啟動docker一樣
                                 -->
                                <!-- <goal>run</goal>  -->
                            </goals>
                        </execution>
                    </executions>
                </plugin>
    

    配置中已有註釋,這裡不再做說明

  3. 運行結果

    • 配置完pom.xml後,在應用打上斷點,然後雙擊install即可開始運行;如果前面按照方式一構建運行過docker; 記得要先在WSL2中把容器刪除(雖然是同一dockerfile構建的鏡像,但maven刪除無法自動刪除別的插件運行產生的鏡像),否則會出現如下報錯:

      image-20220513141435038

    • 執行命令把容器刪除:

      image-20220513141545543

    • 再次雙擊install運行

      image-20220513141954145

    • 訪問 http://localhost:18080/test

      image-20220513132839952

    • 點擊停止按鈕,容器停止運行;和方式一不一樣,此時去WSL2中已查看到不視窗進行。也就是說,在這種方式下,WSL2中的容器是隨著IDEA的停止而銷毀的。

    兩種方式效果差異:

    • 方式一會隨著項目不斷重覆構建,而產生很多個標簽的鏡像;但方式二卻不會。方式二不管構建多少次,都只會產生一個鏡像。

      image-20220513142831215

      idea dockder反覆打包後,會有很多標簽的鏡像
      解決辦法:使用以下指令進行快速刪除
      docker rmi -f $(docker images | grep "none" | awk '{print $3}')
      或者
      docker rmi -f $(docker images -f "dangling=true" -q)
      或者
      docker image prune -f

      深度清理命令:docker image prune -a -f

      這個命令將清理整個系統,並且只會保留真正在使用的鏡像,容器,數據捲以及網路,因此需要格外謹慎。
      比如,我們不能在生產環境中運行prune -a命令,因為一些備用鏡像(用於備份,回滾等)有時候需要用到,如果這些鏡像被刪除了,則運行容器時需要重新下載。

    • Maven插件方式功能強大,從docker的構建、運行、推送等等全流程支持;而且經過配置,即使多次重覆構建鏡像,也不會像idea插件一樣產生很多個標簽的鏡像;非常適合開發調試使用。這也是推薦的最大理由。

    • Maven插件方式部署步驟比較少,但需要對docker-maven-plugin的配置比較瞭解;而IDEA插件配置方式雖然步驟多一些,但都是圖形化配置。比較方便。因此可根據需要進行選擇。

    最後附上Demo代碼:https://gitee.com/lunfangyu/dev-demo


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Cookied的設置會造成XSS攻擊,所以出現了防禦機制HttpOnly標誌(可選),客戶端腳本將無法訪問cookie(如果瀏覽器支持該標誌的話)。因此即使客戶端存在跨站點腳本(XSS)漏洞,瀏覽器也不會將Cookie透露給第三方。Cookie和Session後面還會設計到xss和csrf漏洞的利用... ...
  • 為了修複生產數據,需要執行一段一次性的代碼。 鑒於是spring老項目,就想到了InitializingBean。 代碼如下。服務啟動後,log里發現出現2條“一次性任務開始”。 好在裡面邏輯做了防重控制,沒有受到什麼影響。 @Slf4j @Component public class TransT ...
  • 什麼是隱藏類 隱藏類,是一種不能被其他類直接使用的類。引入隱藏類的主要目的是給框架來使用,使得框架可以在運行時生成類,並通過反射間接使用它們。可能有點抽象,不要緊,下麵我們通過一個例子來直觀的認識它! 隱藏類案例 第一步:先創建一個普通的Java類 public class JEP371Hidden ...
  • 下麵介紹的是JUC包下一些線程安全類的一些簡單使用和一些小demo。 Semaphore 信號量,即可以同時使用的線程數,tryrequire就是將信號量減一,release就是信號量+1,當等於0就會阻塞,大於零才會喚醒。 當需要控制線程訪問數量,可以使用信號量來做控制,比較簡單。 下麵是使用信號 ...
  • Spring Ioc源碼分析系列--Ioc容器註冊BeanPostProcessor後置處理器以及事件消息處理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那麼這一篇繼續在refresh()方法里游蕩,相信對Spring熟悉點的朋友,在看完BeanFactoryPost ...
  • 大家好,這篇文章分享了C程式設計(譚浩強)第五版第十章課後題答案,所有程式已經測試能夠正常運行,如果小伙伴發現有錯誤的的地方,歡迎留言告訴我,我會及時改正!感謝大家的觀看!!! ...
  • 高精度 運算:加法、減法、階乘、乘法 翻轉: 這些運算都是從小位開始,所以一般需要翻轉。以字元串儲存:reverse(a.begin(),a,end())。以數組儲存: for (int i1 = lena1 - 1; i1 >= 0; i1--) { a1[lena1-1-i1] = a[i1] ...
  • 大家好,這篇文章分享了C程式設計(譚浩強)第五版第九章課後題答案,所有程式已經測試能夠正常運行,如果小伙伴發現有錯誤的的地方,歡迎留言告訴我,我會及時改正!感謝大家的觀看!!! ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...