开发者博客 – IT技术 尽在开发者博客

开发者博客 – 科技是第一生产力


  • 首页

  • 归档

  • 搜索

『Netty核心』Netty心跳机制

发表于 2021-11-27

「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」。

点赞再看,养成习惯👏👏

心跳检测机制

所谓心跳,即在 TCP 长连接中,客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线,以确保 TCP 连接的有效性。

心跳检测机制:客户端每隔一段时间发送PING消息给服务端,服务端接受到后回复PONG消息。客户端如果在一定时间内没有收到PONG响应,则认为连接断开,服务端如果在一定时间内没有收到来自客户端的PING请求,则认为连接已经断开。通过这种来回的PING-PONG消息机制侦测连接的活跃性。

在 Netty 中,本身也提供了 IdleStateHandler 用于检测连接闲置,该Handler可以检测连接未发生读写事件而触发相应事件。

看下它的构造器:

1
2
3
java复制代码public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
this((long)readerIdleTimeSeconds, (long)writerIdleTimeSeconds, (long)allIdleTimeSeconds, TimeUnit.SECONDS);
}

解释下三个参数的含义:

  • eaderIdleTimeSeconds 读超时:当在指定的时间间隔内没有从 Channel 读取到数据时,会触发一个 READER_IDLE 的 IdleStateEvent 事件。
  • riterIdleTimeSeconds 写超时:即当在指定的时间间隔内没有数据写入到 Channel 时,会触发一个 WRITER_IDLE 的 IdleStateEvent 事件。
  • llIdleTimeSeconds 读/写超时:即当在指定的时间间隔内没有读或写操作时,会触发一个 ALL_IDLE 的 IdleStateEvent 事件。

注:这三个参数默认的时间单位是秒。若需要指定其他时间单位,可以使用另一个构造方法:

1
2
3
java复制代码public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime, TimeUnit unit) {
this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}

要实现 Netty 服务端心跳检测机制需要在服务器端的 ChannelInitializer 中加入如下的代码:

1
java复制代码pipeline.addLast(new IdleStateHandler(3, 0, 0, TimeUnit.SECONDS));

初步地看下 IdleStateHandler 源码,先看下 IdleStateHandler 中的 channelRead 方法:

红框代码其实表示该方法只是进行了透传,不做任何业务逻辑处理,让 channelPipe 中的下一个 handler 处理channelRead 方法

我们再看看 channelActive 方法:

这里有个 initialize 的方法,这是 IdleStateHandler 的精髓,接着探究:

image.png

这边会触发一个 Task,ReaderIdleTimeoutTask,这个task里的 run 方法源码是这样的:

image.png

第一个红框代码是用当前时间减去最后一次 channelRead 方法调用的时间,假如这个结果是6s,说明最后一次调用channelRead 已经是6s之前的事情了,你设置的是5s,那么 nextDelay 则为-1,说明超时了,那么第二个红框代码则会触发下一个 handler 的 userEventTriggered 方法:

如果没有超时则不触发 userEventTriggered 方法。

服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
java复制代码public class HeartBeatServer {

public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline channelPipeline = socketChannel.pipeline();
channelPipeline.addLast("decoder",new StringDecoder());
channelPipeline.addLast("encoder",new StringEncoder());
channelPipeline.addLast(new IdleStateHandler(3,0,0, TimeUnit.SECONDS));
channelPipeline.addLast(new HeartBeatServerHandler());
}
});
System.out.println("netty server start。。");
ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();
channelFuture.channel().closeFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}

继承 SimpleChannelInboundHandler 重写 channelRead 方法和 userEventTriggered 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
java复制代码public class HeartBeatServerHandler extends SimpleChannelInboundHandler<String> {

int readIdleTimes = 0;

@Override
protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
System.out.println(" ====== > [server] message received : " + s);
if ("Heartbeat Packet".equals(s)){
ctx.channel().writeAndFlush("ok");
}else{
System.out.println(" 其他信息处理...");
}
}

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = null;
switch (event.state()){
case READER_IDLE:
eventType = "读空闲";
readIdleTimes++; // 读空闲的计数加1
break;
case WRITER_IDLE:
eventType = "写空闲";
// 不处理
break;
case ALL_IDLE:
eventType = "读写空闲";
// 不处理
break;
}
System.out.println(ctx.channel().remoteAddress() + "超时事件:" + eventType);
if (readIdleTimes > 3){
System.out.println(" [server]读空闲超过3次,关闭连接,释放更多资源");
ctx.channel().writeAndFlush("idle close");
ctx.channel().close();
}
}

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.err.println("=== " + ctx.channel().remoteAddress() + " is active ===");
}
}

客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
java复制代码public class HeartBeatClient {

public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline channelPipeline = socketChannel.pipeline();
channelPipeline.addLast("decoder",new StringDecoder());
channelPipeline.addLast("encoder",new StringEncoder());
channelPipeline.addLast(new HeartBeatClientHandler());
}
});
System.out.println("netty client start。。");
Channel channel = bootstrap.connect("127.0.0.1", 8888).sync().channel();
String text = "Heartbeat Packet";
Random random = new Random();
while(channel.isActive()){
int num = random.nextInt(8);
Thread.sleep(num*1000);
channel.writeAndFlush(text);
}
}catch (Exception e){
e.printStackTrace();
}finally {
group.shutdownGracefully();
}
}

static class HeartBeatClientHandler extends SimpleChannelInboundHandler<String>{
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(" client received :" + msg);
if (msg != null && msg.equals("idle close")) {
System.out.println(" 服务端关闭连接,客户端也关闭");
ctx.channel().closeFuture();
}
}
}
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

OpenCV中绘制模拟时钟显示当前时间

发表于 2021-11-27

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」

前言

在本篇中,将利用绘图函数,学习如何在实战项目中使用绘图,绘制模拟时钟显示当前时间。

模拟时钟外观

结合 OpenCV 中的绘图函数(例如,cv2.line()、cv2.circle()和 cv2.putText() 等),以渲染更高级的绘图,同时更好的理解和实际运用所了解的绘图函数。为了将所有绘图函数进行综合运用,构建一个模拟时钟来显示当前时间——包括时针、分针和秒针。

为了实现上述需求,编写 clock_appearance.py 脚本。clock_appearance.py 脚本使用 cv.line() 、 cv.circle() 和 cv2.putText() 绘制模拟时钟,首先绘制静态时钟外观,我们需要两个包含固定坐标的数组(至于这些数组是如何计算得到的,将在下一小节中介绍):

1
2
python复制代码hours_orig = np.array([(620,320), (580, 470), (470, 580), (320, 620), (170, 580), (60, 470), (20, 320), (60, 170), (169, 61), (319, 20), (469, 60), (579, 169)])
hours_dest = np.array([(600,320), (563, 460), (460, 562), (320, 600), (180, 563), (78, 460), (40, 320), (77, 180), (179, 78), (319, 40), (459, 77), (562, 179)])

这些数组是渲染小时刻度所必需的,因为它们定义了时钟每小时的刻度线条。数组定义完成后,将这些刻度进行绘制:

1
2
python复制代码for i in range(0, 12):
cv2.line(image, array_to_tuple(hours_orig[i]), array_to_tuple(hours_dest[i]), colors['black'], 3)

此外,还应该绘制了一个大圆圈,对应于模拟时钟表盘的形状:

1
scss复制代码cv2.circle(image, (320, 320), 310, colors['black'], 8)

最后,在时钟内绘制文本,进行个性化定制:

1
2
3
python复制代码cv2.rectangle(image, (150, 175), (490, 270), colors['dark_gray'], -1)
cv2.putText(image, "Mastering OpenCV 4", (150, 200), 1, 2, colors['light_gray'], 1, cv2.LINE_AA)
cv2.putText(image, "with Python", (210, 250), 1, 2, colors['light_gray'], 1, cv2.LINE_AA)

一旦在图像中绘制了这些静态信息,我们将其复制到 image_original 图像中:

1
python复制代码image_original = image.copy()

在下图中,可以看到模拟时钟的外观:

模拟时钟的外观

计算时针刻度 hours_orig 和 hours_dest 数组

为了计算计算时针刻度 hours_orig 和 hours_dest 数组,我们编写 clock_hours.py 计算 hours_orig 和 hours_dest 数组的固定坐标。为了计算小时刻度的 (x, y) 坐标,我们使用圆的参数方程:

{x=x0+r∗cos(t),0≤t≤2πy=y0+r∗sin(t),0≤t≤2π\begin{cases}
x=x_0+r*cos(t), & \text{$0 \le t \le 2\pi$} \
y=y_0+r*sin(t), & \text{$0 \le t \le 2\pi$}
\end{cases}{x=x0​+r∗cos(t),y=y0​+r∗sin(t),​0≤t≤2π0≤t≤2π​
按照上述公式计算从 0 度开始每隔 30 度为一个时针刻度,共 12 个点 P(x, y) 的坐标( 0、30、60、90、120、150、180、210、240、270、300 和 330 ),为了获取两个端点的坐标,我们具有两个不同的半径。这样,我们就可以得到时针刻度线的坐标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
python复制代码radius = 300
center = (320, 320)

for x in (0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330):
x_coordinate = center[0] + radius * math.cos(x * 3.14 / 180)
y_coordinate = center[1] + radius * math.sin(x * 3.14 / 180)
print("x: {} y: {}".format(round(x_coordinate), round(y_coordinate)))

print("----------------------")

for x in (0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330):
x_coordinate = center[0] + (radius - 20) * math.cos(x * 3.14 / 180)
y_coordinate = center[1] + (radius - 20) * math.sin(x * 3.14 / 180)
print("x: {} y: {}".format(round(x_coordinate), round(y_coordinate)))

使用模拟时钟显示当前时间

得到表盘外观后,接下来就要使用模拟时钟显示当前时间:

  1. 从当前时间获取小时、分钟和秒:
1
2
3
4
5
ini复制代码date_time_now = datetime.datetime.now()
time_now = date_time_now.time()
hour = math.fmod(time_now.hour, 12)
minute = time_now.minute
second = time_now.second
  1. 将时、分和秒都转换为角度,用于接下来指针线段的绘制:
1
2
3
python复制代码second_angle = math.fmod(second * 6 + 270, 360)
minute_angle = math.fmod(minute * 6 + 270, 360)
hour_angle = math.fmod((hour*30) + (minute/2) + 270, 360)
  1. 绘制与时针、分针和秒针对应的线段:
1
2
3
4
5
6
7
8
9
10
11
python复制代码second_x = round(320 + 310 * math.cos(second_angle * 3.14 / 180))
second_y = round(320 + 310 * math.sin(second_angle * 3.14 / 180))
cv2.line(image, (320, 320), (second_x, second_y), colors['cyan'], 2)

minute_x = round(320 + 260 * math.cos(minute_angle * 3.14 / 180))
minute_y = round(320 + 260 * math.sin(minute_angle * 3.14 / 180))
cv2.line(image, (320, 320), (minute_x, minute_y), colors['cyan'], 8)

hour_x = round(320 + 220 * math.cos(hour_angle * 3.14 / 180))
hour_y = round(320 + 220 * math.sin(hour_angle * 3.14 / 180))
cv2.line(image, (320, 320), (hour_x, hour_y), colors['cyan'], 10)
  1. 最后绘制一个小圆圈作为三根指针的连接点:
1
python复制代码cv2.circle(image, (320, 320), 10, colors['dark_gray'], -1)

运行代码可以看到绘制的模拟时钟可以正确显示当前时间:

模拟时钟显示当前时间

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

prometheus+grafana监控rabbitmq

发表于 2021-11-27

这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战

在prometheus需要向rabbitmq中打入探针,通过探针获取rabbmq信息,并通过接口输出。下文将讲述如何监控rabbitmq。

1.下载exporter

为了各位小伙伴方便,这里提供了一波下载地址,如果模板不是特别满意,也可以去官网自行下载。
rabbitmq_exporter
链接:pan.baidu.com/s/1It9m5qA-…
提取码:9m28

rabbitmq-monitoring_rev4(可视化界面模板)
链接:pan.baidu.com/s/19ZuCfJNy…
提取码:pmvx

2.安装rabbitmq_exporter

1.解压

1
js复制代码tar -zxvf rabbitmq_exporter-1.0.0-RC7.linux-amd64.tar

2.启动

需要在RABBIT_USER=root RABBIT_PASSWORD=root填写rabbit账号密码

1
2
js复制代码cd usr/local/rabbitmq_exporter-1.0.0-RC7.linux-amd64
RABBIT_USER=root RABBIT_PASSWORD=root OUTPUT_FORMAT=JSON PUBLISH_PORT=9099 RABBIT_URL=http://localhost:5672 nohup ./rabbitmq_exporter &

3.验证

输入http://ip:9099/metrics,如果显示下图,代表成功。(端口号为上文配置)
在这里插入图片描述

3.配置prometheus

老套路加入以下配置文件

1
2
3
4
5
js复制代码  - job_name: 'rabbitMq'
static_configs:
- targets: ['ip:9099']
labels:
instance: rabbitMq

4.配置grafana

输入grafana可视化页面地址:ip:3000

1.配置数据源 (prometheus地址:ip:9090)

在这里插入图片描述
在这里插入图片描述
上图填写你prometheus地址,端口切记填写9090,点击save后,如果失败会有提示 。

2.可视化界面模板

在这里插入图片描述
选择上文配置好的数据源,prometheus选项就是上文配置的数据源。
在这里插入图片描述

3.验证

在这里插入图片描述
出现以上画面 配置完成!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

版本控制工具——Git 1、什么是版本控制 2、版本控制工具

发表于 2021-11-27

「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」。

1、什么是版本控制

版本控制最主要的功能就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了已录下来。每一次文件的改变,文件的版本号都将增加。除了记录版本变更外,版本控制的另一个重要功能是并行开发。软件开发往往是多人协同作业,版本控制可以有效地解决版本的同步以及不同开发者之间的开发通信问题,提高协同开发的效率。并行开发中最常见的不同版本软件的错误(Bug)修正问题也可以通过版本控制中分支与合并的方法有效地解决。

2、版本控制工具有哪些?

版本控制工具就是实现版本控制这一思想的结果。

集中式版本控制工具:

SVN、CVS、VSS……

分布式版本控制工具:

Git、Mercurial、Bazaar、Darcs……

3、版本控制工具应该有哪些功能?

  • 协同修改

多人并行不悖的修改服务器端的同一个文件。

  • 数据备份

不仅保存目录和文件的当前状态,还能够保存每一个提交过的历史状态。

  • 版本管理

在保存每一个版本的文件信息的时候要做到不保存重复数据,以节约存储空

间,提高运行效率。这方面 SVN采用的是增量式管理的方式,而 Git采取了文

件系统快照的方式。

  • 权限控制

对团队中参与开发的人员进行权限控制。

对团队外开发者贡献的代码进行审核——Git独有。

  • 历史记录

查看修改人、修改时间、修改内容、日志信息。

将本地文件恢复到某一个历史状态。

  • 分支管理

允许开发团队在工作过程中多条生产线同时推进任务,进一步提高效

4、Git 与 SVN 区别

  • 1、Git 是分布式的,SVN 不是:这是 Git 和其它非分布式的版本控制系统,例如 SVN,CVS 等,最核心的区别。
  • 2、Git 把内容按元数据方式存储,而 SVN 是按文件: 所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。
  • 3、Git 分支和 SVN 的分支不同: 分支在 SVN 中一点都不特别,其实它就是版本库中的另外一个目录。
  • 4、Git 没有一个全局的版本号,而 SVN 有: 目前为止这是跟 SVN 相比 Git 缺少的最大的一个特征。
  • 5、Git 的内容完整性要优于 SVN: Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

5、Git介绍

  • Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。官网地址:git-scm.com/
  • Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
  • Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
  • GIT优点有:
1
2
3
4
5
6
7
8
9
复制代码  (1)大部分操作在本地完成,不需要联网

(2)完整性保证

(3)尽可能添加数据而不是删除或修改数据

(4)分支操作非常快捷流畅

(5)与 Linux命令全面兼容

6、Git结构

·工作区: 就是你在电脑里能看到的目录(写的代码存在工作区)。

暂存区: 英文叫stage, 或index。一般存放在 “.git目录下” 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。(计划要提交的文件)

版本库:(本地库) 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

image.png

7、Git常用命令

7.1 git init

git init 命令来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令。

在执行完成 git init 命令后,Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变(不像 SVN 会在每个子目录生成 .svn 目录,Git 只在仓库的根目录生成 .git 目录)。

补充命令:

ll –A -a/A 表示查看隐藏文件

image.png

ll .git/ 表示查看 . git 下的文件列表显示*

image.png

注意: . git目录是存放本地库相关的目录和文件,不要对其进行修改和操作。

7.2 git config

git config,签名命令,用于标识不同的开发人员

  • 项目级别(仓库) :仅在当前本地库范围有效
1
2
arduino复制代码 git config user.name username
 git config user.email 123456789@qq.com
  • 系统级别: 登录当前操作系统的用户范围有效

git config –global user.name username

git config –global user.email 123456789_global@qq.com

级别优先级:

就近原则:项目级别优先级大于系统(用户)级别签名

注意: 签名级别必须要设置。如果都不设置,GIT可能会导致命令出错,无法辨别。

7.3 Git status

git status命令用于显示工作目录和暂存区的状态。使用此命令能看到那些修改被暂存到了, 哪些没有, 哪些文件没有被Git tracked到。git status不显示已经commit到项目历史中去的信息。看项目历史的信息要使用git log

7.4 Git add

命令将文件内容添加到索引(将修改添加到暂存区)。也就是将要提交的文件的信息添加到索引库中。(将工作区写入暂存区)

7.5 Git rm

git rm命令用于从工作区和索引中删除文件。(用于将暂存区的文件恢复到工作区)*

7.6 Git commit

git commit命令用于将更改记录(提交)到存储库。将索引的当前内容与描述更改的用户和日志消息一起存储在新的提交中。(用于将暂存区的文件提交到本地仓库)*

另: git commit -m “备注信息” 文件名 //快速加入备注描述

7.7 Git checkout

git checkout命令用于切换分支或恢复工作树文件。git checkout是git最常用的命令之一,同时也是一个很危险的命令,因为这条命令会重写工作区。

7.8 Git log

git log命令用于显示提交日志信息。

查看日志简洁明了格式:

git log –-pretty=oneline

Git log –oneline*

7.9 Git reflog/reset

git reset命令用于将当前HEAD复位到指定状态。一般用于撤消之前的一些操作(如:git add,git commit等)。

通过git reset –hard [局部索引值] //跳到指定版本

7.10 Git diff

git diff命令用于显示提交和工作树等之间的更改。此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。 (默认是和暂存区文件进行比较)

(1)gid diff 将工作区中的文件和暂存区进行比较

1
2
3
js复制代码vim git.txt    (修改内容)

git diff git.txt

(2)gid diff HEAD暂存区中的文件和本地库进行比较

比较:git diff HEAD git.txt //HEAD代表本地库** 最新版本指针

7.11 Git branch

git branch命令用于列出,创建或删除分支。

总结

image.png

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Docker——部署 Nginx,Tomcat及可视化管理工

发表于 2021-11-27

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」

1、部署Nginx

1、搜索 nginx 镜像

命令搜索:

1
shell复制代码docker search nginx

在这里插入图片描述

或者使用DockerHub搜索,可以查看到版本号信息:

在这里插入图片描述

2、下载 nginx 镜像

使用 docker pull 命令下载nginx镜像(最新版):

1
shell复制代码docker pull nginx

在这里插入图片描述

如果想下载指定版本的nginx镜像,使用如下命令(以 1.20.2 为例):

1
shell复制代码docker pull nginx:1.20.2

3、创建并运行容器

以nginx镜像为模板创建一个名为 nginx01 容器,以后台运行,并配置端口映射:

1
2
shell复制代码# -p 9001:80 表示主机端口9001映射到容器内nginx的80端口
docker run -d --name nginx01 -p 9001:80 nginx

在这里插入图片描述

注意:要确保9001端口配置进安全组。

在这里插入图片描述

本机测试访问:

1
shell复制代码curl localhost:9001

在这里插入图片描述

通过本机9001端口成功访问到nginx!

再使用ip+端口进行测试:http://121.199.53.150:9001/

在这里插入图片描述

4、查看nginx的配置文件

进入上面创建的容器 nginx01:

1
shell复制代码docker exec -it nginx01 /bin/bash

找到nginx的配置文件:

1
2
3
bash复制代码whereis nginx
cd /etc/nginx
ls

在这里插入图片描述

查看配置文件:

1
bash复制代码cat nginx.conf

在这里插入图片描述

Nginx部署成功!

2、部署Tomcat

1、搜索 tomcat 镜像

命令搜索:

1
shell复制代码docker search tomcat

在这里插入图片描述

或者使用DockerHub搜索,可以查看到版本号信息:

在这里插入图片描述

2、下载 tomcat 镜像

使用 docker pull 命令下载指定版本tomcat 镜像(9.0版本):

1
shell复制代码docker pull tomcat:9.0

在这里插入图片描述

如果想下载最新版本的tomcat镜像,使用如下命令:

1
shell复制代码docker pull tomcat

3、创建并运行容器

以tomcat镜像为模板创建一个名为 tomcat01 容器,以后台运行,并配置端口映射:

1
2
shell复制代码# -p 9200:80 表示主机端口9200映射到容器内 tomcat 的8080端口
docker run -d --name tomcat01 -p 9200:8080 tomcat:9.0

在这里插入图片描述

注意:要确保9200端口配置进安全组。

在这里插入图片描述

4、这里出现问题,当我们配置完映射,测试访问的时候,发现访问不到页面:

使用ip+端口进行测试:http://121.199.53.150:9200/

在这里插入图片描述

这是因为阿里云下载镜像是下载最小的镜像,所有不必要的都剔除,保证最小可运行环境。

进入tomcat容器,发现webapps目录下没有东西:

在这里插入图片描述

然后再进入webapps.dist目录,发现ROOT文件在这里面:

在这里插入图片描述

把webapps.dist目录下的所有文件拷贝到webapps目录下:

1
shell复制代码cp -r webapps.dist/* webapps

再次查看webapps目录:拷贝成功!

在这里插入图片描述

继续访问请求:http://121.199.53.150:9200/

在这里插入图片描述

Tomcat部署成功!

3、安装 Portainer

Portainer 简介

Portainer是一个可视化的容器镜像的图形管理工具,利用Portainer可以轻松构建,管理和维护Docker环境。 而且完全免费,基于容器化的安装方式,方便高效部署。

官方地址:www.portainer.io/

安装 Portainer

安装步骤:

1
2
3
4
5
shell复制代码docker search portainer |head -n 3

docker volume create portainer_data

docker run -d -p 8000:8000 -p 9300:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

查看是否在运行:运行成功!

在这里插入图片描述

用浏览器访问:http://ip:9300,可以看到以下界面

在这里插入图片描述

设置admin用户密码,需要输入两次相同的密码,然后点击 Creat user

进入之后点击 Local,再点击 Connect:

在这里插入图片描述

查看主机信息:

在这里插入图片描述

查看控制面板:

在这里插入图片描述

管理容器和镜像:

在这里插入图片描述

在这里插入图片描述

Portainer帮助文档:docs.portainer.io/v/ce-2.9/

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Docker——容器的基本命令

发表于 2021-11-27

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」

1、下载测试镜像

容器是通过镜像创建出来的,先下载一个centOS镜像进行容器基本命令的测试:

下载centOS 7镜像:

1
shell复制代码docker pull centos:7

在这里插入图片描述

2、创建并运行容器

创建一个新的容器并运行(docker run)

语法:

1
shell复制代码docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

OPTIONS 说明:

  • -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
  • -d: 后台运行容器,并返回容器ID;
  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口,表示主机端口映射到容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • –name=”tomcat0”: 为容器指定一个名称,用来区分容器;
  • –dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
  • –dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
  • -h “mars”: 指定容器的hostname;
  • -e username=”ritchie”: 设置环境变量;
  • –env-file=[]: 从指定文件读入环境变量;
  • –cpuset=”0-2” or –cpuset=”0,1,2”: 绑定容器到指定CPU运行;
  • -m :设置容器使用内存最大值;
  • –net=”bridge”: 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
  • –link=[]: 添加链接到另一个容器;
  • –expose=[]: 开放一个端口或一组端口;
  • –volume , -v: 绑定一个卷

使用 centos7镜像启动一个容器,参数为以命令行模式进入该容器:

1
2
shell复制代码[root@CHENG /]# docker run -it centos:7 /bin/bash
[root@9ef42deafe5c /]#

参数说明:

  • -i: 交互式操作。
  • -t: 终端。
  • ubuntu: ubuntu 镜像。
  • /bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。

要退出终端,直接输入 exit:

1
2
3
shell复制代码[root@9ef42deafe5c /]# exit
exit
[root@CHENG /]#

查看当前正在运行的容器和运行过的容器

查看当正在运行的容器:

1
shell复制代码docker ps

在这里插入图片描述

参数选择:

  • -a :查看历史运行过的容器
  • -n:显示最近创建的n个容器
  • -q:只显示容器的编号

测试:

查看当正在运行的容器和历史运行过的容器:

1
shell复制代码docker ps -a

在这里插入图片描述

查看当正在运行的容器和历史运行过的容器,只显示2个:

1
shell复制代码docker ps -a -n=2

在这里插入图片描述

查看当正在运行的容器和历史运行过的容器,只显示容器编号:

1
shell复制代码docker ps -a -q

在这里插入图片描述

3、退出容器

退出容器

1
2
shell复制代码exit #退出并停止容器
CTRL + Q + P #退出但不停止容器

先运行并进入容器,然后同时按下 CTRL + Q + P 退出容器,再输入命令 docker ps 查看正在运行的容器:

在这里插入图片描述

4、删除容器

docker rm :删除一个或多个容器。

语法:

1
css复制代码docker rm [OPTIONS] CONTAINER [CONTAINER...]

OPTIONS说明:

  • -f : 通过 SIGKILL 信号强制删除一个运行中的容器。
  • -l : 移除容器间的网络连接,而非容器本身。
  • -v : 删除与容器关联的卷。

不加参数 -f 时,只能删除停止运行的容器,删除正在运行的容器会报错。

强制删除指定的容器,并返回被删除的容器id

1
2
shell复制代码# docker rm -f 容器id
docker rm -f 427775b0aba5

在这里插入图片描述

强制删除所有容器

方式一:

1
shell复制代码docker rm -f $(docker ps -aq)

在这里插入图片描述

方式二:

1
shell复制代码docker rm -a -q|xargs docker rm

在这里插入图片描述

5、启动容器和停止容器

启动一个或多个已经被停止的容器

1
shell复制代码docker start 容器id

重启容器

1
shell复制代码docker restart 容器id

停止一个运行中的容器

1
shell复制代码docker stop 容器id

q强制停止一个运行中的容器

1
shell复制代码docker stop -q 容器id

测试及说明:

在这里插入图片描述

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

CentOS7X安装MySQL80教程

发表于 2021-11-27

一、下载

  • 下载地址:dev.mysql.com/downloads/m…

01.CentOS7.X安装MySQL8.0教程07.jpg

目前下载的版本是mysql-8.0.27-1.el7.x86_64,本次安装使用的是mysql-8.0.23-1.el7.x86_64。

  • 如果需要安装mysql-8.0.23-1.el7.x86_64

在微信公众号【Java和大数据进阶】回复mysql即可。

二、卸载

2.1 查看mariadb的安装包

1
2
bash复制代码[root@hadoopserver ~]# rpm -qa | grep mariadb
mariadb-libs-5.5.44-2.el7.centos.x86_64

2.2 卸载mariadb

1
bash复制代码[root@hadoopserver ~]# rpm -e mariadb-libs-5.5.44-2.el7.centos.x86_64 --nodeps

2.3 再次查看mariadb确认是否卸载成功

三、安装MySQL 8.0

3.1 创建MySQL用户

1
2
3
bash复制代码[root@hadoopserver local]# groupadd mysql
[root@hadoopserver local]# useradd -g mysql mysql
[root@hadoopserver local]# passwd mysql

3.2 上传MySQL rpm包

1
perl复制代码[root@hadoopserver local]# rz

3.3 在MySQL安装位置创建文件夹

1
2
3
bash复制代码[root@hadoopserver local]# mkdir mysql
#设置权限分组
[root@hadoopserver local]# chown mysql:mysql ./mysql

3.4 解压mysql rpm包

1
2
bash复制代码#将文件解压到刚创建的mysql文件夹下
[root@hadoopserver local]# tar -xf mysql-8.0.23-1.el7.x86_64.rpm-bundle.tar -C ./mysql

3.5 授权

1
2
3
4
bash复制代码# 进入MySQL安装目录
[root@hadoopserver local]# cd mysql
# 全部授予最高权限(可读、写、执行)
[root@hadoopserver mysql]# chmod -R 777 *

3.6 安装MySQL

依次安装如下几个rpm包:

1
2
3
4
vbscript复制代码mysql-community-common-8.0.23-1.el7.x86_64.rpm
mysql-community-libs-8.0.23-1.el7.x86_64.rpm
mysql-community-client-8.0.23-1.el7.x86_64.rpm
mysql-community-server-8.0.23-1.el7.x86_64.rpm

执行如下命令

1
2
3
4
shell复制代码[root@hadoopserver mysql]# rpm -ivh mysql-community-common-8.0.23-1.el7.x86_64.rpm --nodeps --force
[root@hadoopserver mysql]# rpm -ivh mysql-community-libs-8.0.23-1.el7.x86_64.rpm --nodeps --force
[root@hadoopserver mysql]# rpm -ivh mysql-community-client-8.0.23-1.el7.x86_64.rpm --nodeps --force
[root@hadoopserver mysql]# rpm -ivh mysql-community-server-8.0.23-1.el7.x86_64.rpm --nodeps --force

命令 --nodeps --force 进行忽略缺少依赖强制安装

01.CentOS7.X安装MySQL8.0教程01.jpg

3.7 查看是否安装成功

1
2
3
4
5
bash复制代码[root@hadoopserver mysql]# rpm -qa|grep mysql
mysql-community-libs-8.0.23-1.el7.x86_64
mysql-community-common-8.0.23-1.el7.x86_64
mysql-community-client-8.0.23-1.el7.x86_64
mysql-community-server-8.0.23-1.el7.x86_64

四、MySQL配置

4.1 初始化mysql数据库

1
css复制代码[root@hadoopserver mysql]# mysqld --initialize --user=mysql

4.2 查看初始化随机密码

1
2
bash复制代码[root@hadoopserver mysql]# cat /var/log/mysqld.log 
2021-11-16T09:54:29.033732Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: bbZQqlUH2r&1

初始化密码为:bbZQqlUH2r&1

4.3 启动MySQL数据库

1
2
3
4
5
6
bash复制代码#启动mysql数据库服务
[root@hadoopserver mysql]# systemctl start mysqld.service
#检查mysql服务状态
[root@hadoopserver mysql]# systemctl status mysqld.service
#允许服务开机启动
[root@hadoopserver mysql]# systemctl enable mysqld.service

01.CentOS7.X安装MySQL8.0教程02.jpg

4.4 登录MySQL、重置root密码

1
2
3
4
5
6
bash复制代码#登录MySQL
[root@hadoopserver mysql]# mysql -u root -p
#重置密码
mysql> alter user 'root'@'localhost' identified by '123456';
#查看mysql版本
mysql>select version();

01.CentOS7.X安装MySQL8.0教程03.jpg

4.5 使用新密码登录

1
bash复制代码[root@hadoopserver mysql]# mysql -u root -p123456

01.CentOS7.X安装MySQL8.0教程04.jpg

五、外部连接MySQL

5.1 先检查防火墙是否关闭

1
2
3
4
5
6
bash复制代码#查看防火墙状态
firewall-cmd --state
#停止firewall
systemctl stop firewalld.service
#禁止firewall开机启动
systemctl disable firewalld.service

5.2 或者开放3306端口

1
2
3
4
5
6
bash复制代码# 开放指定端口
firewall-cmd --zone=public --add-port=3306/tcp --permanent
# 关闭指定端口
firewall-cmd --zone=public --remove-port=3306/tcp --permanent
# 重启防火墙
firewall-cmd --reloadl

5.3 修改mysql数据表user中的host

1
2
3
4
mysql复制代码mysql> use mysql;
mysql> update user set host='%' where user='root';
#该命令必须执行两次
mysql> Grant all privileges on root.* to 'root'@'%';

01.CentOS7.X安装MySQL8.0教程05.jpg

5.4 使用Navicat进行连接

01.CentOS7.X安装MySQL8.0教程06.jpg

测试连接成功!

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Docker——run 流程及镜像的基本命令

发表于 2021-11-27

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」

1、run 的工作流程

当我们在安装完Docker引擎的时候,都会通过运行hello-world 镜像验证 Docker Engine 是否已正确安装:

在这里插入图片描述

下面我们来分析 run 命令的执行流程:run的执行流程图如下

在这里插入图片描述

当我们尝试运行一个在本机和DockerHub都找不到的镜像时:

首先启动Docker 引擎:

1
shell复制代码systemctl start docker

然后进行测试:

1
shell复制代码docker run wanliguyicheng123456789

在这里插入图片描述

Docker返回错误,找不到该镜像。

2、镜像的基本命令

列出镜像列表

我们可以使用 docker images 来列出本地主机上的镜像。

在这里插入图片描述

各个选项说明:

  • REPOSITORY:表示镜像的仓库源
  • TAG:镜像的标签
  • IMAGE ID:镜像的ID,所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的 碰撞机率,所以服务器总是返回长ID。
  • CREATED:镜像的创建时间
  • SIZE:镜像的大小

注:同一仓库源可以有多个 TAG,代表这个仓库源的不同个版本。

可选参数:

名称,简写 描述
–all,-a 列出所有镜像(默认隐藏中间镜像)
–quiet,-q 只显示镜像的 id
1
2
shell复制代码docker images -q
feb5d9fea6a5

搜索镜像

我们可以从 Docker Hub 网站来搜索镜像,Docker Hub 网址为: hub.docker.com,比如我们要搜索mysql的镜像:

在这里插入图片描述

也可以使用 docker search 命令来搜索mysql镜像。

1
shell复制代码docker search mysql

在这里插入图片描述

各个选项说明:

  • NAME:镜像仓库源的名称
  • DESCRIPTION:镜像的描述
  • OFFICIAL:是否 docker 官方发布
  • STARS:类似 Github 里面的 star,表示点赞、喜欢的意思。
  • AUTOMATED:自动构建。

可选参数:

名称,简写 描述
–filter,-f 根据提供的条件过滤输出

搜索 STARS 超过3000的mysql镜像:

1
shell复制代码docker search mysql -f=stars=3000

在这里插入图片描述

下载镜像

语法:

1
shell复制代码docker pull [OPTIONS] NAME[:TAG|@DIGEST]

OPTIONS说明:

  • -a :拉取所有 tagged 镜像
  • --disable-content-trust :忽略镜像的校验,默认开启

测试:使用命令 docker pull 来下载 mysql 镜像

1
shell复制代码docker pull mysql

在这里插入图片描述

下载指定版本的mysql镜像:首先该版本要在Docker Hub中支持

1
shell复制代码docker pull mysql:5.7

在这里插入图片描述

再次用 docker images 命令查看下载的镜像:

在这里插入图片描述

删除镜像

通过镜像名删除:

1
shell复制代码docker rmi -f mysql

参数说明:-f :强制删除

通过镜像 ID 删除:

1
shell复制代码docker rmi -f 8b43c6af2ad0

删除多个镜像:多个镜像id间用空格隔开

1
shell复制代码docker rmi -f 镜像id 镜像id 镜像id 镜像id

删除所有镜像:先查出所有镜像id,然后通过镜像id逐个删除镜像

1
shell复制代码docker rmi -f $(docker images -aq)

在这里插入图片描述
镜像已全部删除!

注意:当要删除的镜像中有正在运行的容器时,需要先删除容器。

Docker命令大全:docs.docker.com/engine/refe…

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Docker——Docker 架构和centOS下安装Doc

发表于 2021-11-27

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」

1、Docker 架构

Docker 三个基本概念

  • 镜像(Image):Docker 镜像是用于创建 Docker 容器的模板,通过这个镜像可以创建多个容器。
  • 容器(Container):镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。容器是独立运行的一个或一组应用。
  • 仓库(Repository):仓库可看成一个代码控制中心,用来保存镜像。一个 Docker Registry 中可以包含多个仓库(Repository),每个仓库可以包含多个标签(Tag),每个标签对应一个镜像。通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

Docker 架构图:

在这里插入图片描述

Docker 架构图名词介绍:

Docker 使用客户端-服务器 (C/S) 架构模式,使用远程API来管理和创建Docker容器。

Docker 客户端(Client):Docker 客户端通过命令行或者其他工具使用 Docker SDK与 Docker 的守护进程通信。

Docker 主机(Host):一个物理或者虚拟的机器用于执行 Docker 守护进程和容器。

Docker Hub

Docker Hub:Docker Hub提供了庞大的镜像集合供使用。

Docker Hub地址:hub.docker.com

2、centOS 安装 Docker

操作系统要求

1、需要 CentOS 7 或 8 的维护版本。不支持或测试存档版本。

在这里插入图片描述

2、必须启用CentOS Extras存储库。默认情况下,此存储库已启用,但如果已禁用,则需要 重新启用它。

3、建议使用overlay2存储驱动程序。

卸载旧版本

如有以前安装的老版本(Docker名称是docker 或docker-engine),需要先删除。

1
2
3
4
5
6
7
8
shell复制代码yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

如果 yum报告没有安装这些软件包,那也没关系。

上述操作只会删除docker本身,但老版本保存在/var/lib/docker/的内容,包括镜像、容器、卷和网络需要手动删除。

安装:使用仓库(repository)安装(推荐)

1、安装yum-utils包

1
shell复制代码yum install -y yum-utils

在这里插入图片描述

2、设置镜像仓库

1
2
3
shell复制代码yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #使用阿里国内源安装docker,速度快

在这里插入图片描述

3、更新yum软件包索引

1
shell复制代码yum makecache fast

在这里插入图片描述

4、安装 Docker CE(社区版)

4.1、安装最新的Docker CE版本:

1
shell复制代码yum install docker-ce docker-ce-cli containerd.io

如果这是您第一次从最近添加的存储库安装软件包,系统将提示您接受GPG密钥,并显示密钥的指纹。 验证指纹是否正确,如果是,请接受密钥。 指纹应该匹配

1
shell复制代码060a 61c5 1b55 8a7f 742b 77aa c52f eb6b 621e 9f35

4.2、安装特定版本的 Docker CE

在生产系统上,应该安装特定版本的Docker CE,而不是始终使用最新版本。

查询可用版本:yum list docker-ce –showduplicates | sort -r

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
shell复制代码[root@CHENG /]# yum list docker-ce --showduplicates | sort -r
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror
Installed Packages
docker-ce.x86_64 3:20.10.9-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.8-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.7-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.6-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.5-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.4-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.3-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.11-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.11-3.el7 @docker-ce-stable
docker-ce.x86_64 3:20.10.10-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.0-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.9-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.8-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.7-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.6-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.5-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.4-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.3-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.15-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.14-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.13-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.12-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.11-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.10-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.0-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.9-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.8-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.7-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.6-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.5-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.4-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.3-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.3.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.2.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.3.ce-1.el7 docker-ce-stable
docker-ce.x86_64 17.03.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
* centos-sclo-sclo: mirrors.163.com
* centos-sclo-rh: mirrors.163.com
Available Packages

安装指定版本:

1
shell复制代码yum install docker-ce-18.03.1.ce-1.el7.centos -y

5、启动Docker

1
shell复制代码systemctl start docker

6、查看Docker 版本

1
shell复制代码docker version

在这里插入图片描述

7、通过运行hello-world 映像验证 Docker Engine 是否已正确安装

1
shell复制代码docker run hello-world

此命令下载测试镜像并在容器中运行它。当容器运行时,它会打印类似发下的消息,则说明安装成功。

在这里插入图片描述

8、查看上面下载的 hello-world 镜像

1
shell复制代码docker images

在这里插入图片描述

3、Docker 引擎的卸载

1、卸载 Docker Engine、CLI 和 Containerd 包:

1
shell复制代码yum remove docker-ce docker-ce-cli containerd.io

2、主机上的映像、容器、卷或自定义配置文件不会自动删除。删除所有镜像、容器和卷:

1
2
shell复制代码rm -rf /var/lib/docker   #docker的默认工作路径
rm -rf /var/lib/containerd

4、配置阿里云镜像加速

1、登录阿里云,找到 容器镜像服务

在这里插入图片描述

2、找到镜像加速地址

在这里插入图片描述

3、配置使用

1
2
3
4
5
6
7
8
9
10
11
shell复制代码sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://lidtl20v.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

在这里插入图片描述

阿里云镜像加速配置完成。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

Docker——Docker 概述及容器部署发展介绍

发表于 2021-11-27

「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」

1、Docker 概述

Docker 简介

Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

一个完整的Docker有以下几个部分组成:

  1. DockerClient客户端
  2. Docker Daemon守护进程
  3. Docker Image镜像
  4. DockerContainer容器

Docker 的优点

Docker 是一个用于开发,交付和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分开,从而可以快速,一致的交付软件。借助 Docker,您可以与管理应用程序相同的方式来管理基础架构。通过利用 Docker 的方法来快速交付,测试和部署代码,您可以大大减少编写代码和在生产环境中运行代码之间的延迟。

Docker 版本简介

Docker有两个版本:社区版Community Edition (CE) 和 企业版Enterprise Edition (EE)

Docker Community Edition(CE)主要是适合单个开发人员和小团队使用Docker容器进行应用程序的开发。Docker CE有三种更新通道:稳定的(Stable)、测试中的(Test)和每日夜间更新(Nightly)。

  • Stable提供了最新的通用稳定的版本。Test 提供了准备好测试的预发布版本,可能bug较多。Nightly提供正在进行开发的最新版本,每日夜间发布一次。一般情况下,为了避免一些不必要的麻烦使用稳定版本.

Docker Enterprise Edition(EE)是为企业开发和大的IT团队设计的,并用于生产环境中大规模地构建、交付和运行关键业务应用程序。

我们使用社区版就可以了。

Docker 官网:www.docker.com

Docker官方文档:docs.docker.com/desktop

Github Docker 源码:github.com/docker/dock…

2、容器部署发展简史

互联网企业生产环境的应用部署所经历的过程,大致可分三个阶段:

  • 物理机部署
  • 虚拟机部署
  • 容器化部署

2.1、物理机部署

在这里插入图片描述

用纯粹的物理机部署应用,这是所有早期物联网公司必然经历的一个阶段。一台服务器,至少32核CPU、64G内存,如果只部署一个应用,那就太浪费了。于是,多个应用进程,DB,缓存进程等等都部署在同一个机器上。这样部署固然能高效的利用好昂贵的物理机,但是这种简单粗暴的方式有一个最大的痛点:进程间资源抢占。如果某个进程耗用了100%的CPU资源,其他的进程无法提供服务。或者如果一个进程因为突发异常很多,日志把磁盘打满了,所有的进程都要挂掉。进程间抢占资源导致其他进程无法提供服务所导致的血案数不胜数。这样的问题相信很多同学的遇到过。
  既然因为资源共享导致的问题,那么解决方式就是:进程间硬件资源隔离。虚拟机技术的出现解决了这个棘手的问题。

2.2、虚拟机部署

在这里插入图片描述

虚拟机通过硬件虚拟化,即每台虚拟机事先从物理机分配好cpu核数,内存, 磁盘,每台虚拟机一般只部署一个应用。从而解决了进程间资源隔离的问题。不同的进程在不同的虚拟机上跑,大家相安无事,老死不相往来,自然没有资源冲突。一台物理机会部署多台虚拟机,物理机里的所有虚拟机则依靠虚拟机管理系统进行管理。

虚拟机技术解决了物理机部署的痛点。但是虚拟机并不是完美的,他也有自己的缺点。大集群部署情况下,软件的版本和配置文件容易碎片化。

大应用集群的虚拟机第一次安装时,由于操作系统镜像是一样的,所以刚开始,软件的版本和库依赖是统一的。随着时间的推移,开源的软件(tomcat, jdk, nginx)需要逐步升级,于是运维同学开始批量升级集群的软件版本,批量升级可能有遗漏或升级失败。同时有些开发同学会自己登陆机器修改软件的版本或者配置,以满足自己的需求。长此以往,一个应用的集群的虚拟机的软件版本和配置逐渐碎片化。当线上出现问题,需要排查到基础软件层面时,由于软件版本碎片化的问题,导致排查变得很棘手。

为了解决虚拟机部署的痛点,容器技术应运而生。

2.3、容器化部署

在这里插入图片描述

容器技术不仅限于docker,但是docker目前最为流行,我以docker为例讲容器。docker容器技术的核心之一在于镜像文件。
镜像文件,通俗的理解就是一个进程运行时依赖的软件文件的集装箱。
  应用集群部署时,每台机器首先会拉取指定版本的镜像文件。安装镜像后产生了docker容器。由于所有机器的镜像文件一样,容器的软件版本故而一样。即使开发或运维中途修改了容器的软件版本,但是容器销毁时,软件的改动会随容器的销毁一起湮灭。当应用用已有的镜像文件重新部署时,生成的docker容器跟修改之前的容器完全一样。这也是Infrastructure as code思想带来的好处。

容器如果要升级软件版本,那就修改镜像文件。这样部署时集群内所有的机器重新拉取新的镜像,软件因此跟着一起升级。软件版本混乱的问题,到docker这里,也就得到了完美的解决。

容器内的应用是直接运行在宿主机的内核中,容器没有自己的内核,也没有虚拟我们的硬件,所以就轻便了,并且每个容器间相互隔离。

一个疑问:有了容器技术,生产环境为何还需要部署虚拟机?

虚拟机能做到硬件资源的彻底隔离,docker不行。虚拟机 和 docker各取长处,最佳CP。

参考文章:www.coonote.com/docker/cont…

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

1…159160161…956

开发者博客

9558 日志
1953 标签
RSS
© 2025 开发者博客
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%