回溯法(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,如圖:
圖示修改說明:
① 原URL為https://start.spring.io ;可能會因為網路問題無法訪問而導致創建失敗,因此改為:https://start.aliyun.com
② 自定義項目名稱
③ 自定義項目存放目錄
④ 按需選擇JDK和JAVA版本
上面信息填寫完成後,點擊Next:
在這一步,只勾選 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 即可看到如下效果:
配置IDEA遠程連接Docker進行打包部署併進行debug調試
IDEA遠程連接Docker的方式有兩種:分別是IDEA自帶插件方式和maven插件方式
方式一:IDEA插件遠程連接Docker打包部署
-
在idea中配置docker遠程連接
如圖,在設置中填寫好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,這裡不再表述。
-
創建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"]
-
如圖所示創建一個配置文件
-
配置詳情如下圖:
上圖中Run Maven Goal添加配置運行前的mavne打包命令為:
clean package -U -DskipTests
; 註意,不帶mvn指令;表示每次在構建鏡像之前,都會將當前工程清理掉並且重新編譯構建 -
設置完成後,點擊下圖紅框中的綠色三角按鈕,運行此配置
-
-
運行結果
-
運行後,控制台效果如下:
-
打開瀏覽器,輸入http://localhost:18080/test;效果如下:
-
打開WSL2,使用docker命令查看鏡像和容器
查看鏡像:
docker images
查看容器:docker ps -a
-
-
遠程debug配置
上面我們已完成了應用的容器構建和部署運行;但作為開發,也許我們還會經常用到debug功能;但應用部署在遠程docker容器中,我們該怎麼進行debug呢?這時,我們就需要用到IDEA的遠程debug功能了。
-
和前面添加配置一樣,點擊Edit Configurations...創建配置文件
-
配置詳情如圖:
需要特別說明的是,之前dockerfile配置文件的ENTRYPOINT開啟遠程調試的配置,就是從Command line arguments for remote JVM這裡複製的命令。另外,因為我是WSL2,所以遠程主機填的是localhost;埠可根據需要自定義。
-
開始遠程debug;
我們給應用打上斷點,然後點擊debug圖標開始運行。之後在控制台出現“Connected to the target VM”字樣,即為成功連接到遠程的虛擬機上。這時,再次在瀏覽器訪問 http://localhost:18080/test 即可看到程式進入斷點:
-
至此,IDEA插件方式遠程連接打包部署並遠程調試完畢。
方式二:MAVEN插件遠程連接Docker打包部署(推薦)
-
創建Dockerfile(在此直接使用方式一的Dockerfile文件,如沒有,需創建)。
-
在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>
配置中已有註釋,這裡不再做說明
-
運行結果
-
配置完pom.xml後,在應用打上斷點,然後雙擊install即可開始運行;如果前面按照方式一構建運行過docker; 記得要先在WSL2中把容器刪除(雖然是同一dockerfile構建的鏡像,但maven刪除無法自動刪除別的插件運行產生的鏡像),否則會出現如下報錯:
-
執行命令把容器刪除:
-
再次雙擊install運行
-
點擊停止按鈕,容器停止運行;和方式一不一樣,此時去WSL2中已查看到不視窗進行。也就是說,在這種方式下,WSL2中的容器是隨著IDEA的停止而銷毀的。
兩種方式效果差異:
-
方式一會隨著項目不斷重覆構建,而產生很多個
標簽的鏡像;但方式二卻不會。方式二不管構建多少次,都只會產生一個鏡像。 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
-