从安全到镜像流水线,Docker 最佳实践与反模式一览

作者 | Timothy Mugayi

译者 | 弯月,责编 | 夕颜

封图 | CSDN付费下载自视觉中国

出品 | CSDN(ID:CSDNnews)

在使用Docker的大部分时间里,我们并不关心其内部的工作原理。仅凭启动一个Docker容器并且让应用程序运行良好,并不能说明你已经实现了一个良好的解决方案。有时,由于时间限制,我们只能复制粘贴Docker镜像,却没能真正理解实现细节以及如何构建Docker镜像的细微差别。

 

在本文中,我们将探讨Docker的最佳实践和反模式。反模式是人们对于反复出现的问题的一般解决方案,这些方案没有效率,甚至会完全抵消Docker技术栈带来的好处。

 

下面我们来看看我们的哪些做法不可取。

 

我们需要的标签

 

标签是必不可少的,我们需要通过标签传达有关Docker镜像的信息。你可以将标签视为Docker镜像ID的别称。Git标签负责标记特定的提交,而Docker标签与之类似,可以给不同时间点上的Docker镜像添加版本。忘记打标签是小事,但会带来一些弊端,具体来讲,如果未指定标记,则默认镜像将被标记为latest。

 

FROM your_image_name:latest

 

如果你频繁执行该操作,那么很有可能镜像不是最新的,可能指向的是旧版本。因此,请使用适当的标签并遵守某个版本控制标准,例如语义版本控制。这样,Docker镜像使用者才能确保Docker镜像的兼容性并时刻保持最新,还可以有计划地使用正确的版本。

 

还有一个情况应该避免。你可以利用最新的默认标签(如FROM python3:latest),从Docker镜像仓库中提取最新的镜像。乍一看,这种做法似乎是个好主意,但却有一些意想不到的副作用:每个最新的请求可能都会派生出与以前的构建完全不同的Docker镜像。弄明白Docker镜像损坏的原因将会变得很困难,因为镜像本应该是不可变的。因此,我强力建议使用特定的标签来标记镜像(例如:python3:1.0.1)。这种方法可以确保你的Dockerfile保持不变。

 

在同一个容器中运行多个服务

 

虽然你可以在同一个容器中运行多个服务,但我并不建议你这么做,原因有两个。在使用Docker服务时,我们应该努力维持责任单一性。最佳做法是,组成应用程序的每个服务都应在各自的容器中运行,请务必将每项独立的功能都打包到单独的独立容器镜像中。

 

将多个服务添加到一个Docker镜像的做法似乎很诱人,但是你不应该将容器镜像视为虚拟机。一个容器包含多个服务,可能会导致你的应用程序很难水平扩展。Docker容器核心概念是,它们都是瞬态的,专为分发而设计,这对于现代Web应用程序来说很理想,因为它的瞬态特性、扩展和并发会非常容易。添加多个服务会增加管理分发的难度。

 

另外,单个容器上的多个服务还会加大管理安全性的难度。庞大的镜像可能会降低CI/CD的速度,你需要小心。

 

使用LABEL对镜像进行分类

 

这并不能说是反模式,但我认为值得一提。我在处理各种Docker镜像时注意到了一件事:有时这些镜像的创建者没有使用LABEL maintainer标签。这个标签可在事件中设置镜像的Author字段,当出现问题或需要澄清时,这个标签可以方便大家了解该与何人内部联系;如果镜像是公开共享的,也可以知道该与哪个外部的人联系。

 

这绝不是唯一可以使用的标签。你可以根据需要定义各种标签,来对镜像进行分类,定义许可信息,也可以定义标签来帮助自动化。

 

除了maintainer,还可以使用多行标签:

# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="RBTSB Incorporated"
LABEL vendor2=TIPTAPCODE\ Incorporated
LABEL com.example.release-date="202-04-02"
LABEL com.example.version.production="0.0.1"

Docker 1.10之前的单行标签会创建新的docker层,如果你使用的是最新版的Docker,则不必担心创建额外的层。

LABEL vendor=ACME\ Incorporated \
com.example.is-beta= \
com.example.is-production="" \
com.example.version="0.0.1-beta" \
com.example.release-date="2015-02-12"

我们应该将尽可能多的元数据添加到不可变的Docker镜像,以方便追踪,提高可见性和可维护性。

 

避免构建依赖特定环境的镜像

 

在构建Docker镜像时,我们应始终牢记不变性。最好不要使用带有dev、test、staging和production的镜像,因为这会破坏单一来源的原则。另一个问题是,如果在不同环境上验证或调试,则这种做法无法保证镜像的相似。

 

为什么要使用非Root容器?

 

在默认情况下,Docker容器以root身份运行。以root用户身份运行的Docker容器可以完全控制主机系统。然而,出于安全考虑,我并不推荐这种做法。使用非root运行的Docker容器镜像可以多一层保护,在生产环境中通常建议使用非root容器。但是,由于这些容器由非root用户运行,因此无法执行需要特殊权限的任务。如果需要利用USER指令指定非root用户(如以下示例所示),则需要进行一些上下文切换。

 

FROM python:3.6-slim-buster
LABEL maintainer="Timothy Mugayi <timothy.mugayi@gmail.com>"RUN apt-get update && apt-get install -y --no-install-recommends \
wget && rm -rf /var/lib/apt/lists/*# Dumb init
RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64
RUN chmod +x /usr/local/bin/dumb-initRUN pip install --upgrade pipWORKDIR /usr/src/appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY helloworld.py .USER 1001ENTRYPOINT ["/usr/local/bin/dumb-init", "python3", "-u", "./helloworld.py"] 

如果你使用的基础镜像不是由root生成的,但需要切换回root,则可以执行以下操作:

 FROM <namespace>/<image>:<tag_version>USER root

不要在单个容器内运行太多进程

 

容器的优点以及容器相对于虚拟机的优势在于,通过多个相互交互的容器组成一个完整的应用程序。我们无需在单个容器中运行完整的应用程序。相反,我们应尽可能将应用程序分解为多个服务,并将服务分布到多个容器上。这样可以最大程度地提高灵活性和可靠性。

 

不要在容器内安装操作系统

 

使用一段时间Docker后,你就有可能遇到这种情况。虽然你可以在容器内安装和运行完整的Linux操作系统。但是你应该这样做吗?

 

这可能不是一个好主意。Docker镜像是使用层的概念构建的,因此添加的东西越多,镜像就会膨胀得越大。一个完整的操作系统并不是Docker的理想使用情况。在理想情况下,你的容器内部只应该加载必要的组件。

 

不要在容器内运行不必要的服务

 

为了充分利用容器的优势,你应该尽可能保持容器精简。这样可以最大程度地提高性能,并最大程度地降低安全风险。因此,请避免运行并非绝对必要的服务。例如,若非必要请不要在容器内运行SSH服务,你可以选用其他方式(例如Docker exec)登录到容器。

 

不要在容器内加载不必要的程序

 

你必须知道这种反模式。在使用Docker时,很多人倾向于在镜像中加载sonar之类的工具,来确保代码覆盖率等。

 

使用从Docker CE 17.05+开始支持的多阶段构建(Multistage builds)模式,你可以在Dockerfile中使用多个FROM stage。临时构建的阶段容器将被丢弃,因此最终的运行时容器镜像都很精简。举个例子,当你需要从源文件编译一些二进制文件,然后在第二个阶段中将二进制文件复制到最终镜像中。

 

优点:

 

  • 构建速度更快,精简的镜像可以让CI/CD过程更快,镜像通过网络进行传输时花费的时间也更少。

  • 需要的存储空间更少。

  • 冷启动(拉取镜像)更快。

  • 潜在的受攻击面更少。

 

缺点:

 

  • 容器内的工具较少,但这是保证容器的精简所需付出的一点小小的代价。

在容器内加入供观察的工具

 

即便没有监视解决方案,你也可以照常运行容器,但需要牢记,从本质上来说,你很难知道容器内部发生了什么,特别是随着容器数量的增加。

 

Docker本身自带了许多指标,能够公开每个运行容器的CPU、内存、网络和I/O使用情况,可通过Docker远程API的/stats端点访问。App dynamics 和 Newrelic 是两个现成的程序,可以与Docker镜像一起打包,帮助你从应用程序级别了解应用程序和容器的运行状况。

 

基础镜像的爱恨交织

 

“你知道是谁构建了这个景象,里面都添加了什么吗?”

 

这里说的都是可追溯性。牢记安全性是所有软件开发人员都应努力的方向。你需要了解如何跟踪Docker镜像的源,并了解里面有什么。

 

你需要时刻牢记以下几点:

 

  • 镜像是怎样创建的。

  • 验证镜像在创建后未经更改。

  • 验证镜像的内容。

  • 扫描镜像是否有安全漏洞。

 

我们可以通过一些工具对容器进行静态分析。这些工具涉及方方面面,已超出了本文的范围,但是我建议你花一些时间来学习。

 

Clair是一个有趣的工具,可为你的Docker应用程序提供自动容器漏洞和安全扫描。扫描基于常见的漏洞和公开(CVE)的数据库。如果你本地运行Docker,则可以下载Postgres,然后将Clair连接到Postgres上。以下是启动和运行Clair所需的最低配置:

$ mkdir $PWD/clair_config
$ curl -L https://raw.githubusercontent.com/coreos/clair/master/config.yaml.sample -o $
PWD/clair_config/config.yaml
$ docker run -d -e POSTGRES_PASSWORD="" -p 5432:5432 postgres:9.6
$ docker run --net=host -d -p 6060-6061:6060-6061 -v 
PWD/clair_config:/config quay.io/coreos/clair:latest -config=/config/config.yaml

如果你想更改Postgres的端口,请确保同时修改config.yaml文件。如果你的系统上已经运行了另一个Postgres,请注意不要将docker端口更改为5432以外的端口。

 

clair:
database:
# Database driver
type: pgsql
options:
# PostgreSQL Connection string
# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
source: host=localhost port=5432 user=postgres password=123456 sslmode=disable statement_timeout=60000

在镜像启动并执行后,你可以运行Docker ps来确认容器已启动且正常运行:

你需要注意Clair没有Web UI或CLI。你只能通过REST API或第三方CLI工具来使用。

 

Bayan Collector是一款轻巧的静态分析应用程序,可以从镜像仓库启动容器以进行静态分析,可以运行任意脚本并收集有用的信息(例如已安装的软件包),强制执行策略,以及对镜像进行校验。

 

Docker Bench for Security是由Docker团队创建的工具,它会在Docker的宿主上运行一个安全最佳做法清单,并标记发现的任何问题。

 

不要在容器镜像中存储敏感数据

 

请一定避免这个错误。如果你的镜像对外公开,或者开发人员无意中将镜像推送到公共的Docker镜像仓库中,那么就会导致隐私和敏感信息的泄露。切记永远不要在Dockerfile中对敏感信息使用COPY或`。

 

为了避免这种情况,请将敏感数据存储在安全文件系统上,并让容器进行连接。一般情况下,这个文件系统应该在容器所在的宿主上,或者可通过AWS Elastic Block Storage(EBS)等块存储或S3等对象存储服务来使用。

 

此外,你应避免在Docker镜像中存储安全凭证。作为开发人员,有时我们会采用偷懒的做法,在代码中硬编码密码和私钥。你需要习惯使用-e参数在运行时为Docker容器指定环境变量。

 

你也可以通过env-file,从文件中读取环境变量。通过CMD或`从第三方来源获取凭据的自定义脚本也可用于获取Docker容器所需的相关凭据。

 

不要在容器内存储数据或日志

 

容器化改变了日志的性质。容器是瞬态、无状态应用程序的理想选择。本质上,存储在运行容器中的所有数据都应该是短暂的,你可能已经注意到,当容器关闭时,数据将丢失。因此,将数据存储在Docker容器之外的做法更值得推崇。有一些工具可以帮助你提取Docker日志,并将其放在更永久的数据存储中。

 

在处理Docker日志时需要牢记一点:Docker至少拥有三个级别的日志记录,即Docker容器、Docker服务和宿主操作系统,你选择的日志记录方法应该能够提取所有级别的日志。

 

不要写入容器的文件系统

 

每次将内容写入容器的文件系统都会激活“写时复制”策略。这会使用存储驱动程序(deviermapper、overlayfs或其他驱动)创建新的存储层。在实际应用中,这会给存储驱动带来巨大的压力,特别是使用Devicemapper或BTRFS的情况下。

 

确保容器只向卷中写入数据。对于小型的临时文件可以写入tmpfs,因为tmpfs是仅存在于内存或交换分区中的临时文件系统。

 

不要运行PID 1

 

这是许多人都不知道的常见问题。

 

Docker中的进程运行时没有init进程负责清理子进程,所以容器可能会出现僵尸进程,导致意料之外的错误。

 

使用tini或dumb-init

 

PID 1在Unix中很特殊,因此在init系统中忽略它通常会导致进程和信号处理错误。这会导致类似于容器无法优雅地停止,或本应摧毁的容器出现泄露等问题。

 

僵尸进程指的是运行已经停止,但依然在进程表中占据位置的进程,因为它们的父进程没有调用wait系统调用进行回收。理论上,每个结束的进程都会非常短暂地呈现僵尸状态,但有些进程的僵尸状态会持续很久。

 

如果某个进程会生成新进程,但信号处理的实现不好,无法捕获子进程的信号并将其终止,那么可以使用Tini或dumb-init。例如,bash脚本就无法正确处理或释放信号。

 

下面是运行dumb init的示例,其中prepare.sh可以是shell脚本,也可以是用于执行应用程序的命令:

RUN wget -O 
/usr/local/bin/dumb-init 
https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64RUN chmod +x /usr/local/bin/dumb-initENTRYPOINT ["/usr/local/bin/dumb-init", "/usr/bin/prepare.sh"]

或者如果你选择tini,可以参考下面使用Python anaconda conda的示例:

 

RUN conda install --yes -c 
conda-forge tiniENTRYPOINT ["tini", "-g", "--", "/usr/bin/prepare.sh"]

 

最后,这里是一个更一般的示例,不依赖于任何编程语言:

 

FROM node:13.12.0-slimMAINTAINER Timothy Mugayi <timothy.mugayi@gmail.com>ENV TINI_VERSION='v0.13.0'
# Add tini init, see https://github.com/krallin/tini
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tiniRUN chmod +x /tini
# Set tini as entrypoint
ENTRYPOINT ["/tini", "--"]

在CI/CD中使用Dockerfile格式检查

 

跟编程语言一样,Docker也有格式检查工具。

 

采用格式检查工具有许多好处,因为它会强制你使用最佳实践。在CI/CD过程中加入格式检查,可以帮助团队避免常见的错误,并在构建产品Docker镜像时建立最佳实践。可以从hadolint开始,这是一个用Haskell编写的Dockerfile格式检查工具,能够解析Dockerfile成AST,并在AST上执行规则检查。

 

我们来运行一个示例。要对Docker进行格式检查,可以执行以下命令:

$ docker run --rm -i 
hadolint/hadolint < Dockerfile

 

格式检查完成后会显示以下结果:

 

上图中的错误码DL3008“Pin”来自hadolint的错误码描述状态。固定版本号可以强制构建时安装特定版本的包,不论缓存中是什么。这个技巧可以减少依赖包意料之外的改变导致的构建错误。

 

最后的一点想法

 

在本文中,我们谈了很多内容,覆盖了从安全到Docker镜像流水线的方方面面。

 

有许多技巧可以让Docker镜像更好、更安全。希望这篇文章可以给你带来一些启发,帮助你理解应该做什么、不应该做什么,并为你提供一些在构建内部或外部Docker容器镜像时可以应用的方案。

  

原文链接:

https://medium.com/better-programming/docker-best-practices-and-anti-patterns-e7cbccba4f19

本文为CSDN翻译文章,转载请注明出处。 


推荐阅读

  • 大促下的智能运维挑战:阿里如何抗住“双11猫晚”?

  • 20万个法人、百万条银行账户信息,正在暗网兜售

  • 当莎士比亚遇见Google Flax:教你用字符级语言模型和归递神经网络写“莎士比亚”式句子

  • Hyperledger Fabric 和企业级以太坊,谁才是企业首选?

  • 面试时遇到「看门狗」脖子上挂着「时间轮」,我就问你怕不怕?

  • 同期两篇 Nature:运行温度高于 1K 的量子计算平台问世!

  • GitHub 标星 10,000+,Apache 顶级项目 ShardingSphere 的开源之路

    真香,朕在看了!
    

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

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

相关文章

ChaosBlade 发布对 C++ 应用混沌实验的支持

前言 为满足 C 应用系统故障演练&#xff0c;阿里妈妈安全生产团队开源了 C 混沌实验执行器&#xff0c;填补了 C 应用混沌工程实验的空白&#xff0c;其遵循《混沌实验模型》&#xff0c;可通过 ChaosBlade 工具直接执行。项目详情点击这里&#xff01; 。 本文重点介绍该执…

TortoiseGitPlink提示输入密码解决方法

文章目录一、现象二 、解决方法2.1. 打开TortoiseGit 下的puttygen工具2.2. 点击load&#xff0c;加载私钥2.3. 生成一个新的私钥2.4. 项目拉取2.5. 配置新的私钥一、现象 二 、解决方法 2.1. 打开TortoiseGit 下的puttygen工具 双击D:\software\TortoiseGit\bin下面的puttyg…

引领高并发直播场景进入毫秒时代,阿里云发布超低延时直播服务

近日&#xff0c;阿里云上线超低延时直播服务RTS&#xff08;Real-time Streaming&#xff09;&#xff0c;该服务在视频直播产品的基础上&#xff0c;进行全链路延时监控、传输协议改造等底层技术优化&#xff0c;支持千万级并发场景下的毫秒级延迟直播能力&#xff0c;保障低…

JavaScript-面向对象 class 继承

class继承 class 关键字是在ES6引入的 ES6之前的写法&#xff1a; function Student(name) {this.name name } // 给Student新增一个方法 Student.prototype.hello function () {alert(Hello) }ES6的写法&#xff1a; // 定义一个 学生的 类 class Student1{constructor(…

我26岁,月薪一万,刚实现“黄焖鸡自由”(苦笑)

今天是CSDN微信公众号千万粉丝达成的日子&#xff0c;因此&#xff0c;“千万粉丝狂欢节”来了&#xff01;第一弹超值福利来袭&#xff0c;前方高能&#xff1a;「粉丝节限定版一卡通」重磅上线&#xff01;可看该大牛老师全部课程&#xff01;课程涵盖热门的Java、Python和AI…

Android侧滑原来可以这么优雅

前言 侧滑手势在Android App应用得非常广泛&#xff0c;常见的使用场景包括&#xff1a;滑动抽屉、侧滑删除、侧滑返回、下拉刷新以及侧滑封面等。由于这些使用场景实在是太通用了&#xff0c;各路大神们八仙过海各显神通&#xff0c;每种侧滑场景都开源出了很多非常实用的框架…

TortoiseGit状态图标不能正常显示的解决办法

文章目录一. 运行环境一、方案11.1. 右键点击桌面空白处&#xff0c;打开TortoiseGit的Settings1.2. 修改Icon Overlays的Status cache1.3. 重启电脑&#xff0c;你就会发现你的小乌龟箭头出来了。二、方案2一. 运行环境 版本说明Windows 10 64bit操作系统TortoiseGit-2.12.0.…

平头哥广发英雄帖,公开首款CPU“玄铁”仿真代码

“在自研芯片的路上&#xff0c;阿里走出了万里长征的第一步。” 7月25日&#xff0c;阿里云峰会上海站&#xff0c;压轴出场的平头哥&#xff0c;交出了时隔10月的首份答卷&#xff1a;玄铁910&#xff08;XuanTie910&#xff09;&#xff0c;目前业界性能最强的RISC-V处理器…

JavaScript-操作BOM对象

BOM&#xff08;Browser Object Model&#xff09;: 浏览器对象模型 浏览器介绍 JavaScript 和 浏览器关系&#xff1f; JavaScript 诞生就是为了能够让他在浏览器中运行&#xff01; 内核&#xff1a; IE 6~11ChromeSafariFireFox 第三方浏览器&#xff08;可以换上面的内核…

一文带你认识keepalived,再带你通关LVS+Keepalived!

来源 | 故事凌责编 | Carol封图 | CSDN 下载于视觉中国昨天我们讲到《那些你不知道的 LVS 秘密》&#xff0c;今天我们就继续一起来进行 LVS 更深的探索&#xff0c;来一起通关 LVSKeepalived吧&#xff01;keepalivedkeepalive的学习参考网站&#xff1a;https://www.keepali…

手把手教你D2C,走向前端智能化

这几年来 AI 来势汹汹&#xff0c;在部分领域应用也逐渐成熟。前端发展至今&#xff0c;我们也有许多成熟的前端解决方案代码&#xff0c;有大量的设计稿&#xff0c;我们是否能够结合智能化的能力将一个 Design 变成一个 Code &#xff08;设计转代码&#xff0c;简称 D2C&…

TortoiseGit 冲突和解决方案_入门试炼_07

文章目录一、张三操作1. 张三新增hello.java2. 提交本地仓库3. 更新项目4. 将本地仓库变动文件提交远程二、李四操作2.1. 编辑Hello.java2.2. 提交三、张三操作23.1. 在hello.java中添加内容3.2. 提交本地仓库3.3. 更新项目至最新版本3.4. 更新最版本异常&#xff08;冲突&…

如何低成本实现Flutter富文本,看这一篇就够了!

作者&#xff1a;闲鱼技术-玄川 背景 闲鱼是国内最早使用Flutter 的团队&#xff0c;作为一个电商App商品详情页是非常重要场景&#xff0c;其中最主要的技术能力是文字混排。 我们面对文本类的需求是复杂而且多变&#xff0c;然而Flutter历史的几个版本&#xff0c;Text只能…

赋能零售成长型企业营销增长,云徙「数盈·新营销中台」发布

巨石崩裂时&#xff0c;有人看见了恐惧&#xff0c;有人看见了光。 因为有光&#xff0c;万物生长。 疫情给每个企业的影响都是巨大的。但在疫情冲击之下&#xff0c;由中台技术推动企业数字化转型&#xff0c;又给企业带来了希望。 从2016年创业至今&#xff0c;云徙科技的每…

TortoiseGit 下载、安装、配置_入门试炼_01

TortoiseGit 简介: TortoiseGit 简称 tgit&#xff0c; 中文名海龟Git。TortoiseGit是一个开放的GIT版本控制系统的源客户端。 文章目录一、软件下载1.1. 下载安装Git1.2. Tortoisegit二、安装流程2.1. 双击安装程序2.2. 直接点击下一步(Next)2.3. Next2.4. 选择安装目录2.5. 点…

ArchSummit分享 | 高德地图App架构演化与实践

讲师介绍 郝仁杰&#xff0c;高德地图无线开发专家。在7月13日落幕的2019年ArchSummit峰会上就高德地图近几年的App架构演化和实践进行了分享。 背景概述 高德是国内领先的数字地图内容、导航和位置服务解决方案提供商&#xff0c;端上分手机和车机两条主线。近年来&#xf…

工程师的灵魂拷问:你的密钥安全吗?

阿里妹导读&#xff1a;密钥管理是密码学应用的核心问题之一。任何涉及加密/签名的应用&#xff0c;无论算法本身机制多么安全&#xff0c;最终都会受到灵魂拷问&#xff1a;你密钥存在哪儿&#xff1f;本文实现了一种安全的密钥管理方案&#xff0c;基于安全多方计算技术&…

优化算法2D可视化的补充

4. 分析上图&#xff0c;说明原理&#xff08;选做&#xff09; 1、为什么SGD会走“之字形”&#xff1f;其它算法为什么会比较平滑&#xff1f; 之所以会走"之字形"&#xff0c;是因为它在每次更新参数时只考虑当前的样本梯度。这导致参数更新非常不稳定&#xff0c…

TortoiseGit 本地仓库和远程仓库建立联系_入门试炼_02

TortoiseGit 简介: TortoiseGit 简称 tgit&#xff0c; 中文名海龟Git。TortoiseGit是一个开放的GIT版本控制系统的源客户端。 文章目录一、前提准备1.1. 生成秘钥和公钥1.2. 把 SSH Key 填到Git 服务器的配置中一、前提准备 声明&#xff1a;此处介绍通过SSH URL方式传输&…

来自 Spring Cloud 官方的消息,Spring Cloud Alibaba 即将毕业

2019 年 7 月 24 日晚&#xff0c;Spring Cloud 官方发布公告&#xff1a; 仓库迁移是官方决定Spring Cloud Alibaba 即将毕业 根据官方最新的发版规则&#xff0c;我们会把孵化器中的 Spring Cloud Alibaba 仓库迁移回 Alibaba 官方仓库&#xff0c;进行正式的毕业发布&#…