基于机器学习的网络入侵检测二元分类模型构建与性能评估(NSL-KDD数据集)

简介

该项目是一个基于NSL-KDD数据集的网络入侵检测系统,主要采用机器学习方法对网络流量数据进行使用了多种机器学习模型,如逻辑回归、线性SVM、多项式核SVM、高斯核SVM、决策树、随机森林、朴素贝叶斯和K近邻算法训练二元分类(正常/异常)模型及预测,最后比较了各个算法的检测效果。

实现步骤

  1. 加载和导入数据:
  • 导入所需的Python库,如numpy、pandas、matplotlib等,以及sklearn中的各种机器学习算法和评估指标。
  • 读取KDDTrain+.txt和KDDTest+.txt文件作为训练集和测试集,并给数据列添加对应的标签。
  1. 数据预处理:
  • 检查并打印训练集和测试集中重复的数据行数。
  • 将攻击类别转化为二元分类:‘normal’ 和 ‘abnormal’,并将原始攻击类别列删除。
  • 对分类特征(如protocol_type, service, flag)进行标签编码。
  1. 特征选择:
  • 使用mutual_info_classif方法计算特征与目标变量之间的互信息,并根据结果选择最重要的20个特征。
  1. 数据标准化:
    选定筛选后的特征子集后,对训练集和测试集的特征进行标准化处理,使用MinMaxScaler将所有特征缩放到[0, 1]区间内。

  2. 模型初始化与训练:

  • 初始化多种分类模型,包括逻辑回归、支持向量机(线性核、多项式核、高斯核)、决策树、随机森林、朴素贝叶斯和K近邻。
  • 对每个模型进行训练,使用训练好的模型在测试集上进行预测。
  1. 性能评估:
  • 计算并存储每个模型在测试集上的准确率、精确度和召回率。

实现代码

导入必要的库和数据

# 导入和加载数据
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split,StratifiedKFold,GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier,VotingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import GridSearchCV,RandomizedSearchCV
from sklearn.svm import SVC
from sklearn import metrics
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import make_scorer, roc_auc_score
import scipy
from scipy import stats
import warnings
warnings.filterwarnings("ignore")
from sklearn.preprocessing import StandardScaler# 设置列标签
columns = (['duration'
,'protocol_type'
,'service'
,'flag'
,'src_bytes'
,'dst_bytes'
,'land'
,'wrong_fragment'
,'urgent'
,'hot'
,'num_failed_logins'
,'logged_in'
,'num_compromised'
,'root_shell'
,'su_attempted'
,'num_root'
,'num_file_creations'
,'num_shells'
,'num_access_files'
,'num_outbound_cmds'
,'is_host_login'
,'is_guest_login'
,'count'
,'srv_count'
,'serror_rate'
,'srv_serror_rate'
,'rerror_rate'
,'srv_rerror_rate'
,'same_srv_rate'
,'diff_srv_rate'
,'srv_diff_host_rate'
,'dst_host_count'
,'dst_host_srv_count'
,'dst_host_same_srv_rate'
,'dst_host_diff_srv_rate'
,'dst_host_same_src_port_rate'
,'dst_host_srv_diff_host_rate'
,'dst_host_serror_rate'
,'dst_host_srv_serror_rate'
,'dst_host_rerror_rate'
,'dst_host_srv_rerror_rate'
,'attack'
,'level'])# 从文件中读取训练集和测试集
df_train=pd.read_csv('../input/nslkdd/KDDTrain+.txt',header=None,names=columns)
df_test=pd.read_csv('../input/nslkdd/KDDTest+.txt',header=None,names=columns)

数据内容如下所示:

durationprotocol_typeserviceflagsrc_bytesdst_byteslandwrong_fragmenturgenthot...dst_host_same_srv_ratedst_host_diff_srv_ratedst_host_same_src_port_ratedst_host_srv_diff_host_ratedst_host_serror_ratedst_host_srv_serror_ratedst_host_rerror_ratedst_host_srv_rerror_rateattacklevel
00tcpftp_dataSF49100000...0.170.030.170.000.000.000.050.00normal20
10udpotherSF14600000...0.000.600.880.000.000.000.000.00normal15
20tcpprivateS0000000...0.100.050.000.001.001.000.000.00neptune19
30tcphttpSF23281530000...1.000.000.030.040.030.010.000.01normal21
40tcphttpSF1994200000...1.000.000.000.000.000.000.000.00normal21
..................................................................
1259680tcpprivateS0000000...0.100.060.000.001.001.000.000.00neptune20
1259698udpprivateSF1051450000...0.960.010.010.000.000.000.000.00normal21
1259700tcpsmtpSF22313840000...0.120.060.000.000.720.000.010.00normal18
1259710tcpkloginS0000000...0.030.050.000.001.001.000.000.00neptune20
1259720tcpftp_dataSF15100000...0.300.030.300.000.000.000.000.00normal21

125973 rows × 43 columns

数据格式如下所示:
在这里插入图片描述

检查训练集和测试集中重复数据的数量。

# 检查并打印训练集中重复数据的数量
print(df_train.duplicated().sum())# 检查并打印测试集中重复数据的数量
print(df_test.duplicated().sum())

0
0

计算DataFrame中每个列的空值数量

df_train.isnull().sum()

在这里插入图片描述

检查异常值

绘制所有列的箱线图以查看异常值

# 绘制箱线图
df_train.plot(kind='box', subplots=1, layout=(15, 3), figsize=(20, 40))
plt.show()

在这里插入图片描述
计算并返回训练数据集中‘attack’列中各标签的出现次数

df_train['attack'].value_counts()

用于计算数据框 df_train 中指定列 ‘attack’ 中不同值的出现次数,并以降序排列。这里没有参数传递,函数直接返回一个 Series 对象,其中包含各标签的计数。这个操作对于了解数据的分布非常有用,特别是当需要了解数据集中各类攻击的相对频率时。
在这里插入图片描述
将数据集中的异常类别转换为单一的异常类
该代码块主要对训练集和测试集进行处理,将原始攻击类别转化为二元分类:
正常(normal)和异常(abnormal)。这有助于简化后续的模型训练和评估过程。

# 将训练集中的攻击类别转化为二元分类
df_train["binary_attack"]=df_train.attack.map(lambda a: "normal" if a == 'normal' else "abnormal")
# 删除原始的攻击类别列
df_train.drop('attack',axis=1,inplace=True)# 将测试集中的攻击类别转化为二元分类
df_test["binary_attack"]=df_test.attack.map(lambda a: "normal" if a == 'normal' else "abnormal")
# 删除测试集中的原始攻击类别列
df_test.drop('attack',axis=1,inplace=True)
df_train.select_dtypes(['object']).columns

Index([‘protocol_type’, ‘service’, ‘flag’, ‘binary_attack’], dtype=‘object’)

数据编码

该代码块主要功能是对给定的数据集的几个指定列进行标签编码。
使用的是sklearn库中的preprocessing模块的LabelEncoder类。

from sklearn import preprocessing
le=preprocessing.LabelEncoder()  # 创建标签编码器实例clm=['protocol_type', 'service', 'flag', 'binary_attack']  # 需要进行标签编码的列名列表
for x in clm:  # 遍历列名列表df_train[x]=le.fit_transform(df_train[x])  # 对训练数据集的指定列进行标签编码df_test[x]=le.fit_transform(df_test[x])  # 对测试数据集的指定列进行标签编码

数据分割

对输入的数据集进行处理,分割为训练集和测试集的特征和标签。

主要步骤包括:

  1. 从训练集数据框(df_train)中去除标签列(‘binary_attack’),保留其余特征列,得到训练集的特征(x_train);
  2. 从训练集数据框(df_train)中提取标签列(‘binary_attack’),得到训练集的标签(y_train);
  3. 从测试集数据框(df_test)中去除标签列(‘binary_attack’),保留其余特征列,得到测试集的特征(x_test);
  4. 从测试集数据框(df_test)中提取标签列(‘binary_attack’),得到测试集的标签(y_test)。
# 分割训练集的特征和标签
x_train=df_train.drop('binary_attack',axis=1)
y_train=df_train["binary_attack"]# 分割测试集的特征和标签
x_test=df_test.drop('binary_attack',axis=1)
y_test=df_test["binary_attack"]

特征工程

计算特征与目标变量之间的互信息。

:param x_train: 训练集的特征矩阵,其中每一列是一个特征。
:param y_train: 训练集的目标变量向量。

from sklearn.feature_selection import mutual_info_classif# 使用mutual_info_classif计算特征与目标变量的互信息
mutual_info = mutual_info_classif(x_train, y_train)# 将计算结果转换为pandas Series,方便后续处理
mutual_info = pd.Series(mutual_info)# 设置Series的索引为特征名,这样可以方便地与特征矩阵相对应
mutual_info.index = x_train.columns# 按照互信息值降序排序,使得最重要的特征排在前面
mutual_info.sort_values(ascending=False)

在这里插入图片描述

绘制相互信息的柱状图

对名为mutual_info的数据结构(假设为DataFrame)按值进行降序排序,
然后使用bar方法绘制柱状图。figsize(图形大小)参数设置为(20, 8),以确保图形足够大,
便于细节查看和展示。该图形可用于展示不同变量间的相互信息量,帮助分析者理解变量间的关联程度。

mutual_info.sort_values(ascending=False).plot.bar(figsize=(20, 8));

在这里插入图片描述

# 选择最重要的20个特征进行筛选
from sklearn.feature_selection import SelectKBest
# 使用mutual_info_classif方法评估特征重要性,选择最重要的20个特征
sel_five_cols = SelectKBest(mutual_info_classif, k=20)
# 对训练数据进行特征选择
sel_five_cols.fit(x_train, y_train)
# 获取选择出的特征的列名
x_train.columns[sel_five_cols.get_support()]

Index([‘service’, ‘flag’, ‘src_bytes’, ‘dst_bytes’, ‘logged_in’, ‘count’,
‘serror_rate’, ‘srv_serror_rate’, ‘same_srv_rate’, ‘diff_srv_rate’,
‘srv_diff_host_rate’, ‘dst_host_count’, ‘dst_host_srv_count’,
‘dst_host_same_srv_rate’, ‘dst_host_diff_srv_rate’,
‘dst_host_same_src_port_rate’, ‘dst_host_srv_diff_host_rate’,
‘dst_host_serror_rate’, ‘dst_host_srv_serror_rate’, ‘level’],
dtype=‘object’)

为了确保训练集和测试集在进行模型训练和评估前,其特征维度和类型保持一致,只包含对模型有意义或者相关的特征,从而提高模型的准确性和泛化能力。

# 将训练集和测试集的数据调整为只包含指定的列
col=['service', 'flag', 'src_bytes', 'dst_bytes', 'logged_in','same_srv_rate', 'diff_srv_rate', 'dst_host_srv_count','dst_host_same_srv_rate', 'dst_host_diff_srv_rate']# 调整训练集特征矩阵,仅包含指定的列
x_train=x_train[col]# 调整测试集特征矩阵,也仅包含指定的列
x_test=x_test[col]

生成并显示一个热力图,用于可视化x_train数据集的协方差矩阵。

# 创建一个新的图形窗口,设置其宽度和高度
plt.figure(figsize=(12,10))
# 生成热力图,显示元素值,使用'RdYlGn'颜色映射
p=sns.heatmap(x_train.corr(), annot=True, cmap='RdYlGn')  

在这里插入图片描述

数据缩放

对机器学习模型的输入数据(训练集和测试集)进行标准化处理,使得数据的范围在0到1之间,以提升模型的性能和稳定性。

# 导入MinMaxScaler类,用于数据的标准化处理
from sklearn.preprocessing import MinMaxScaler# 实例化MinMaxScaler对象,用于后续的数据转换
scaler = MinMaxScaler()# 对训练集数据进行标准化处理,转换后的数据范围在[0, 1]之间
x_train = scaler.fit_transform(x_train)# 对测试集数据进行标准化处理,同样的转换确保训练集和测试集的特征缩放一致
x_test = scaler.fit_transform(x_test)

二元分类模型训练及预测

# 初始化各种模型并将它们以名称为键存储在一个字典中
models = {}# 初始化逻辑回归模型
from sklearn.linear_model import LogisticRegression
models['Logistic Regression'] = LogisticRegression()# 初始化线性支持向量机模型
from sklearn.svm import LinearSVC
models['Support Vector Machines linear'] = LinearSVC()# 初始化多项式核支持向量机模型
models['Support Vector Machines plonomial'] = SVC(kernel='poly')# 初始化高斯核支持向量机模型,通过调整C参数来避免过拟合
models['Support Vector Machines RBf'] =  SVC(C=100.0)# 初始化决策树模型,限制树的最大深度为3
from sklearn.tree import DecisionTreeClassifier
models['Decision Trees'] = DecisionTreeClassifier(max_depth=3)# 初始化随机森林模型
from sklearn.ensemble import RandomForestClassifier
models['Random Forest'] = RandomForestClassifier()# 初始化朴素贝叶斯模型
from sklearn.naive_bayes import GaussianNB
models['Naive Bayes'] = GaussianNB()# 初始化K最近邻模型,选择20个最近邻点
from sklearn.neighbors import KNeighborsClassifier
models['K-Nearest Neighbor'] = KNeighborsClassifier(n_neighbors=20)

根据提供的模型集合,分别训练每个模型,作出预测,并计算与存储各个模型的准确度、精确度和召回率。
使用的指标来自sklearn.metrics模块,包括:accuracy_score(准确率)、precision_score(精确度)、recall_score(召回率)。
三个字典accuracy、precision、recall用于存储每个模型对应的指标结果。

from sklearn.metrics import accuracy_score, precision_score, recall_scoreaccuracy, precision, recall = {}, {}, {}for key in models.keys():# 对当前循环到的模型进行训练models[key].fit(x_train, y_train)# 使用训练好的模型对测试集进行预测predictions = models[key].predict(x_test)# 计算并存储当前模型的准确率、精确度和召回率accuracy[key] = accuracy_score(predictions, y_test)precision[key] = precision_score(predictions, y_test)recall[key] = recall_score(predictions, y_test)

根据提供的模型准确度、精确度和召回率生成一个DataFrame

df_model = pd.DataFrame(index=models.keys(), columns=['Accuracy', 'Precision', 'Recall'])
# 初始化DataFrame,设置索引为模型名称,列名为Accuracy, Precision, Recalldf_model['Accuracy'] = accuracy.values()
# 将accuracy字典的值赋给DataFrame的Accuracy列df_model['Precision'] = precision.values()
# 将precision字典的值赋给DataFrame的Precision列df_model['Recall'] = recall.values()
# 将recall字典的值赋给DataFrame的Recall列df_model
# 输出生成的DataFrame
AccuracyPrecisionRecall
Logistic Regression0.7170420.9435690.611111
Support Vector Machines linear0.7238730.9556170.615630
Support Vector Machines plonomial0.7643720.9627230.653822
Support Vector Machines RBf0.7729330.9573680.663977
Decision Trees0.8230130.8409020.769579
Random Forest0.7622870.9696220.650276
Naive Bayes0.5462650.4406340.471463
K-Nearest Neighbor0.7889460.9620020.680358

使用条形图可视化模型数据。

# 绘制条形图
ax = df_model.plot.barh()# 设置图例
ax.legend(ncol=len(models.keys()),  # 根据模型数量确定图例列数bbox_to_anchor=(0, 1),  # 将图例位置设置在绘图区右上角loc='lower left',  # 位置细节调整,将图例放置在左下角prop={'size': 14}  # 设置图例文字大小
)# 调整布局,确保图表各部分之间没有空隙
plt.tight_layout()

在这里插入图片描述

遍历所有模型并绘制ROC曲线

from sklearn.metrics import plot_roc_curve# 遍历所有模型并绘制ROC曲线
for key in models.keys():plot_roc_curve( models[key], x_test, y_test)"""plot_roc_curve函数用于绘制ROC(受试者操作特性)曲线。参数:models[key]:表示模型,从字典models中通过key获取对应的模型。x_test:测试集的特征向量。y_test:测试集的真实标签。返回值:无返回值,直接在图形窗口中绘制ROC曲线。"""

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
不难得出,随机森林和决策树分类器对于NSL-KDD数据集来说有较好的分类效果。

优化建议

  1. 平衡数据处理:
  • NSL-KDD数据集中各类别的样本分布可能存在不均衡情况,应考虑使用欠采样、过采样或SMOTE等方法来平衡正负样本。
  1. 特征工程改进:
  • 除了基于互信息的选择外,可以尝试其他特征选择方法,例如递归特征消除(RFE)、基于卡方检验的选择等,以及探索更高阶的交互特征。
  • 可以进一步研究数据集中的特征关联性和冗余性,减少共线性特征的影响。
  1. 模型调优:
  • 对于每个模型,通过GridSearchCV或RandomizedSearchCV进行参数网格搜索,寻找最优超参数组合,提高模型性能。
  • 考虑集成学习方法,比如AdaBoost、BaggingClassifier或者StackingClassifier,结合多个基础模型提升整体表现。
  1. 评估指标:
  • 由于这是一个二分类问题且可能涉及类不平衡,仅依赖准确率评价模型效果可能不够全面。应引入F1分数、AUC-ROC曲线等相关指标进行综合评估。
  1. 模型解释性:
  • 引入模型可解释性技术,例如SHAP值、LIME等,帮助理解模型在各个特征上的重要性,以及为何做出特定预测,增加系统的透明度和可信度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/733539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bug总结(1)--变量取错

a c t i v i t y [ ′ t a g n a m e ′ ] 应为 activity[tag_name]应为 activity[′tagn​ame′]应为couponActivitList[0][‘name’] .隐藏的bug,在测试中竟然测不出来,而且上线了好久。为啥会出现这种低级错误呢?第一是写的时候不够仔细认…

Day26:安全开发-PHP应用模版引用Smarty渲染MVC模型数据联动RCE安全

目录 新闻列表 自写模版引用 Smarty模版引用 代码RCE安全测试 思维导图 PHP知识点: 功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输…

2024 年中国高校大数据挑战赛赛题 C:用户对博物馆评论的情感分析完整思路以及源代码分享

博物馆是公共文化服务体系的重要组成部分。国家文物局发布, 2021 年我国新增备案博物馆 395 家,备案博物馆总数达 6183 家,排 名全球前列;5605 家博物馆实现免费开放,占比达 90%以上;全国 博物馆举办展览 3…

【深度学习笔记】6_5 RNN的pytorch实现

注:本文为《动手学深度学习》开源内容,部分标注了个人理解,仅为个人学习记录,无抄袭搬运意图 6.5 循环神经网络的简洁实现 本节将使用PyTorch来更简洁地实现基于循环神经网络的语言模型。首先,我们读取周杰伦专辑歌词…

Python操作Redis 各种数据类型

本文将深入探讨如何使用Python操作Redis,覆盖从基础数据类型到高级功能的广泛主题。无论是字符串、列表、散列、集合还是有序集合,我们将一一解析,同时提供丰富的代码示例帮助读者更好地理解和应用。除此之外,本文还将介绍Redis的…

【20240309】WORD宏设置批量修改全部表格格式

WORD宏设置批量修改全部表格格式 引言1. 设置表格文字样式2. 设置表格边框样式3. 设置所有表格边框样式为075pt4. 删除行参考 引言 这两周已经彻底变为office工程师了,更准确一点应该是Word工程师,一篇文档动不动就成百上千页,表格图片也是上…

STM32之串口中断接收UART_Start_Receive_IT

网上搜索了好多,都是说主函数增加UART_Receive_IT()函数来着,实际正确的是UART_Start_Receive_IT()函数。 —————————————————— 参考时间:2024年3月9日 Cube版本:STM32CubeMX 6.8.1版本 参考芯片&#xff1a…

Svg Flow Editor 原生svg流程图编辑器(二)

系列文章 Svg Flow Editor 原生svg流程图编辑器(一) 说明 这项目也是我第一次写TS代码哈,现在还被绕在类型中头昏脑胀,更新可能会慢点,大家见谅~ 目前实现的功能:1. 元件的创建、移动、形变;2…

【C语言】字符指针

在指针的类型中我们知道有一种指针类型为字符指针char* 一般使用: int main() { char ch w; char *pc &ch; *pc w; return 0; } 还有一种使用方式,如下: int main() { const char* pstr "hello bit.";//这⾥是把⼀个字…

plantUML使用指南之序列图

文章目录 前言一、序列图1.1 语法规则1.1.1 参与者1.1.2 生命线1.1.3 消息1.1.4 自动编号1.1.5 注释1.1.6 其它1.1.7 例子 1.2 如何画好 参考 前言 在软件开发、系统设计和架构文档编写过程中,图形化建模工具扮演着重要的角色。而 PlantUML 作为一种强大且简洁的开…

【stm32 外部中断】

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行 中断优先级:当有多个中…

LoadBalancer (本地负载均衡)

1.loadbalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别 Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实现的。 loadbalancer本地负载均衡,在调用微服务接口时候&a…

考研复习C语言初阶(4)+标记和BFS展开的扫雷游戏

目录 1. 一维数组的创建和初始化。 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 1.4 一维数组在内存中的存储 2. 二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 3. 数组越界 4. 冒泡…

【Java JVM】Class 文件的加载

Java 虚拟机把描述类的数据从 Class 文件加载到内存, 并对数据进行校验, 转换解析和初始化, 最终形成可以被虚拟机直接使用的 Java 类型, 这个过程被称作虚拟机的类加载机制。 与那些在编译时需要进行连接的语言不同, 在 Java 语言里面, 类的加载, 连接和初始化过程都是在程序…

解决阿里云服务器开启frp服务端,内网服务器开启frp客户端却连接不上的问题

解决方法: 把阿里云自带的Alibabxxxxxxxlinux系统 换成centos 7系统!!!! 说一下我的过程和问题:由于我们内网的服务器在校外是不能连接的,因此我弄了个阿里云服务器做内网穿透,所谓…

大模型学习过程记录

一、基础知识 自然语言处理:能够让计算理解人类的语言。 检测计算机是否智能化的方法:图灵测试 自然语言处理相关基础点: 基础点1——词表示问题: 1、词表示:把自然语言中最基本的语言单位——词,将它转…

你应该打好你的日志,起码避免被甩锅

大家好,我是蓝胖子,相信大家或多或少都有这样的经历,当你负责的功能出现线上问题时,领导第一时间便是找到你询问原因,然而有时问题的根因或许不在你这儿,只是这个功能或许依赖了第三方或者内部其他部门,这个…

【Unity InputSystem】实用指南:在PC端(鼠标与键盘)、手机端(触摸屏)、主机手柄上同步实现角色移动与跳跃功能

前引 随着Unity的不断发展,开发者对于项目的输入系统要求也日益提高。在进行多平台适配和跨平台移植时,常常需要改变输入系统,这给开发者带来了不少困扰。而Unity官方推出的InputSystem插件,则是为了解决这一问题而推出的全新输入…

Linux内存管理--系列文章壹

一、引子 作者、我在上班闲着没事的时候,看了一些关于Linux内存管理和程序装载、链接的文章,然后自己就总结出了一些东西。 本系列文章一方面将资料中的长篇大论总结到最少、以方便可以直接找到答案,一方面也是方便面试的时候可以吹牛逼。 L…

【Docker】golang使用DockerFile正确食用指南

【Docker】golang使用DockerFile正确食用指南 大家好 我是寸铁👊 总结了一篇golang使用DockerFile正确食用指南✨ 喜欢的小伙伴可以点点关注 💝 问题背景 今天寸铁想让编写好的go程序在docker上面跑,要想实现这样的效果,就需要用…