【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控

SpringBoot

内容管理

    • Linux Redis Connnect
      • 设置服务器redis开机自启动
      • 修改Redis配置文件
      • 关闭防火墙
      • 关闭selinux
      • 连接Redis
    • Docker
      • Docker安装
        • 基础环境配置【配置源】
        • 网卡配置发放【内核流量转发】
        • yum快速安装
        • 镜像加速器【配置ustc的加速器】
      • Docker生命周期
      • 镜像images原理
        • 在虚拟机上灵活替换不同的Linux发行版【相关发行版镜像】
        • docker镜像解决问题【迁移,不依赖】
        • images分层原理
        • docker镜像【每一个镜像都包含完整的层,至少包含base】
      • Docker快速使用【nginx运行
      • Docker镜像管理常用命令
        • docker search XXX 在regisry镜像站中搜索XXX镜像
        • docker pull XXX (:tag)
        • docker images (image ls)【-q】 【名称 + tag】 查看本地镜像
        • docker rmi [docker ID前三位就可] 删除本地ID为XX的镜像【不依赖记录rm】
        • docker image save XXX > XXX.tgz 导出镜像为压缩包,指定路径
        • docker image load -i XXXX.tgz 从指定路径下导入镜像
        • docker image inspect 镜像ID 显示镜像的详细信息
      • Docker容器管理命令
        • docker run 【参数 -p -v -d -i t --rm】 镜像名称/ID 【bash等】 运行镜像生成容器(还可进入容器)
        • docker logs 【-f】 容器ID 查看容器日志
        • docker container inspect 容器ID 查看容器详细信息
        • docker exec -it 容器ID bash 进入容器内的发行版终端
        • exit (容器内执行) 退出容器
        • docker ps 【-a】 查看本地容器运行情况
        • docker port 容器ID 查看容器的端口转发情况
        • docker commit 容器ID diy的镜像名 将容器提交为镜像放到本地镜像库
        • docker rm 镜像ID 删除镜像记录
        • docker stop 容器ID 停止容器的运行
        • docker start 容器ID 开启容器的运行【stop的】
        • docker restart 容器ID 重启容器yunx
        • docker version 查看docker的版本
        • docker info 查看docker的基本信息【存储镜像位置...】
        • docker build Dockerfile文件位置
        • docker tag 容器ID 自定义容器Name
      • dockerfile 常用指令
        • FROM 指定base image【不一定从发行版开始构建,可以直接在任何镜像】
        • MAINTAINER 指定维护者信息【可以没有】
        • RUN 构建镜像时执行的...命令
        • ADD 复制宿主机文件进入容器内, 会自动解压
        • COPY 复制...和ADD一样
        • WORKDIR 设置当前工作目录【类似cd的作用】
        • USER 改变环境,切换用户
        • VOLUME 设置卷,挂载主机目录【目录映射】
        • EXPOSE 打开门,指定对外的端口,暴露端口
        • ENV 【ARG】 设置容器的环境变量
        • CMD 指定容器启动后需要执行的事情
        • ENTRYPOINT【传入的只是当作参数,而CMD形式为覆盖】
      • Dockerfile快速实践
      • 容器内运行程序 docker只是进程
    • Boot项目发布部署
      • 多环境配置 spring Profile
      • springBoot内置Tomcat ---- 打包为可执行jar文件
      • 基于传统的web容器 ---- 打包为war可执行文件
      • 现代化发布 ---- 基于Docker发布
      • 现代化发布 ---- 基于RPM发布
    • 运行监控
      • 使用Spring Boot Actuator 查看运行指标
      • Prometheus --- 系统监控警报工具 docker拉取
      • Grafana ----- 可视化监控【补充Prometheus 强大UI】
    • Spring Boot devtools
      • 自动配置【devtools自动】
      • 热部署
      • LiveReload 插件支持静态资源的更新
      • 全局配置
      • 远程应用


SpringBoot开发技术 — 现代化部署与运维、docker、运行监控,Grafana


技术无止境… 简单的测试部分主要就是@SpringBootTest,接下来就是介绍部署运维了,简单介绍Docker容器和基于docker的发布部署

程序编写了完备的测试用例之后,软件开发生命周期到达最终阶段— 部署运维;随着开发和项目交付模式的改变,现代的开发讲究高效敏捷,方便快捷部署并且稳定运行十分重要 【依赖项的变化之类】

Linux Redis Connnect

设置服务器redis开机自启动

每次手动开启redis服务不是很方便,设置开机自启动就是交给Systemctl管理,主要就是编写service文件,mysql也是,编写其中的ExecStart

还是和mysql的目录一级创建service, touch /usr/lib/systemd/system/redis.service

[root@localhost system]# touch redis.service
[root@localhost system]# vim redis.service
[root@localhost system]# cat redis.service 
[Unit]
Description=The redis-server Process Manager
After=syslog.target network.target


[Service]
Type=simple
PIDFile=/var/run/redis_6379.pid
ExecStart=/usr/local/redis-6.2.6/src/redis-server /usr/local/redis-6.2.6/redis.conf         
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID


[Install]
WantedBy=multi-user.target

这样就可以使用systemctl管理redis服务

systemctl enable redis

之前数据库直接使用的Windows Redis,但是实际场景中使用的是Linux版本,这里要进行远程连接,需要进行相关的配置

修改Redis配置文件

cd usr/local/redis.XXX
vim redis.conf
  • 修改bind127.0.0.0 为 bind 0.0.0.0 ----> 允许所有IP访问
  • 修改daemonize 为yes —> 允许后台运行redis
  • 修改protected-mode 为no ----> 关闭保护模式

启动redis server使用修改过的配置文件

./redis-server   ../redis.conf

如果不是 redis.conf,那么需要 ./redis-server …/redisXXX.conf

启动后,可以通过 ps -ef|grep redis查看进程

[root@localhost ~]# ps -ef|grep redis
root       4555   4404  0 10:55 pts/0    00:00:00 ./redis-server *:6379

可以看到端口从127.0.0.0.redis变为了*.redis,允许多ip访问

关闭防火墙

要访问redis,需要关闭虚拟机防火墙,docker下载也需要关闭

systemctl stop firewalld

关闭selinux

SELinux时安全增强Linux,内核模块,安全子系统,最大限度减少系统中服务进行可访问的资源

而有的软件对于SELinux的安全规则支持不够好,所以就建议把selinux关闭

三种状态:

  • enforceing: 强制模式,运行安全规则
  • permissive: 宽容模式,警告但是不会限制
  • disabled: 永久关闭,没有运行

查看状态:

getenforce

临时关闭:

setenforce 0  就是变为宽容模式permissive

永久关闭

//进入配置文件中修改

cd /etc/selinux

vim conf

将其状态 变为disabled,然后重启机器

docker安装时状态getenforce 为disabled

连接Redis

上面已经按照自定义配置运行server,可以进行远程访问,【可以多测试几次,i之前卡住了】,在项目中配置application-dev.yml

redis:
    port: 6379
    host: 192.XX8.XX4.100  #连接远程redis
    database: 1
    timeout: 1000
    password:
    jedis:
      pool:
        max-active: 10
        max-idle: 8
        min-idle: 1
        max-wait: 1

这里为了快速连接没有设置密码,直接连接

    /**
     * 测试远程连接redis
     */
    @Test
    public void testJedis_WithRemoteServer() {
        redisCache.set("xiaohuan","isPig");
        System.out.println(redisCache.get("time"));
    }

//连接成功Success!

we 还可以进入配置文件修改log file

而iptables的规则之前全部都清理掉了【iptables -F】这里不需要设置

yum install iptables-services //最新的服务

systemctl enable iptables //开机自启动

systemctl restart iptables //重启

Docker

Docker是平台即服务的产品PaaS,使用操作系统级别的虚拟的容器化技术帮助实现软件服务以互相隔离的方式进行,三个基本概念: Dockerfile,镜像,容器; Docker其实就是一个虚拟化容器

Docker和redis类似,主要是在Linux系统上面使用,可以直接安装Docker提供的docker for Windows【必须为64位并且需要启动Hyper-V操作】硬件虚拟化操作

直接进入Windows系统的 【启用或关闭Windows功能】,选择hyper-v即可,但是普通的家庭版Windows没有,自己选择

家庭版没有可以写脚本运行,插入电脑,但是为了安全,所以还是在centOs7上面安装

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第1张图片

Docker的安装采用: 虚拟化 + 容器: Infrastructure可能笔记本或者服务器,GuestOs就是安装的虚拟机比如CentOs,虚拟机上面再安装Docker

Docker安装

基础环境配置【配置源】
  • 要安装Docker,首先就是要将虚拟机配置一下,配置之后要关闭防火墙
[root@localhost ~]# systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
  • 之后就是设置yum源,Docker源为国外,为了更快,所以需要配置国内的镜像

在XShell中复制为CTRL + INSERT ,粘贴为SHIFT + INSERT

除了yum源之外,还有epel额外源

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

执行之后:

[root@localhost ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
--2022-07-28 18:23:32--  http://mirrors.aliyun.com/repo/Centos-7.repo
正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)... 113.141.190.102, 113.141.190.103, 113.141.190.105, ...
正在连接 mirrors.aliyun.com (mirrors.aliyun.com)|113.141.190.102|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:2523 (2.5K) [application/octet-stream]
正在保存至:/etc/yum.repos.d/CentOS-Base.repo”

100%[=======================================================================================================================================================================>] 2,523       --.-K/s 用时 0s      

2022-07-28 18:23:32 (5.07 MB/s) - 已保存 “/etc/yum.repos.d/CentOS-Base.repo” [2523/2523])

[root@localhost ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
--2022-07-28 18:23:53--  http://mirrors.aliyun.com/repo/epel-7.repo
正在解析主机 mirrors.aliyun.com (mirrors.aliyun.com)... 113.141.190.100, 113.141.190.105, 113.141.190.104, ...
正在连接 mirrors.aliyun.com (mirrors.aliyun.com)|113.141.190.100|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:664 [application/octet-stream]
正在保存至:/etc/yum.repos.d/epel.repo”

100%[=======================================================================================================================================================================>] 664         --.-K/s 用时 0s      

2022-07-28 18:23:53 (99.3 MB/s) - 已保存 “/etc/yum.repos.d/epel.repo” [664/664])

  • 清理缓存和生成新的缓存
yum clean all   
yum makecache 
  • 清空防火墙规则 : iptables -F
  • 查看SElinux状态: getenforce
  • 关闭防火墙: systemctl stop firewalld
网卡配置发放【内核流量转发】

docker必须安装在CentOS7 、 内核版本不低于3.10才可以, uname -r 查看虚拟机版本

要想Docker支持,所以必须开启linux内核的流量转发

所以就是创建docker.conf文件写入相关的网络配置【cat重定向】

cat <<EOF>   /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_forward = 1
EOF

执行完毕后,ls就可以看到文件创建成功

  • 要想写入内核的配置文件生效,必须加载参数
sysctl -p /etc/sysctl.d/docker.conf

这里执行完毕如果出现错误: sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: 没有那个文件或目录
sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: 没有那个文件或目录

那么就先执行

modprobe br_netfilter

添加目录之后再执行上面的加载操作

yum快速安装

首先需要配置好yum仓库

配置阿里云自带的仓库: 安装docker

  • 查看当前源中的可用的版本
yum list docker-ce --showduplicates | sort -r

如果直接查询,因为当前没有docker-ce,会报错: 错误:没有匹配的软件包可以列出
已加载插件:fastestmirror, langpacks

  • 配置阿里云提供的docker专属的repo仓库
curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

curl -o /etc/yum.repos.d/CentOS-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo

之后执行yum clean all && yum makecache 更新缓存

[root@localhost ~]# curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/cocker-ce/linux/centos/docker-ce.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2318  100  2318    0     0  10580      0 --:--:-- --:--:-- --:--:-- 10633
[root@localhost ~]# curl -o /etc/yum.repos.d/CentOS-7.repo http://mirrors.aliyun.com/repo/Centos-7.repo
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2523  100  2523    0     0  40723      0 --:--:-- --:--:-- --:--:-- 47603
[root@localhost ~]# yum clean all && yum makecache
已加载插件:fastestmirror, langpacks
Repository base is listed more than once in the configuration
Repository updates is listed more than 
  • 查看镜像源中可用版本
yum list docker-ce --showduplicates | sort -r

出现问题: File contains no section headers.
file: file:///etc/yum.repos.d/docker-ce.repo, line: 1
‘\n’ 说明yum docker-ce源没有配置,可以删除原文件重新下载 【这里的错误就是i 的写错了】

rm -f  /etc/yum.repos.d/docker-ce.repo  

curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

这里就可以看到

可安装的软件包
 * updates: mirrors.aliyun.com
Loading mirror speeds from cached hostfile
 * extras: mirrors.aliyun.com
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.17-3.el7                    docker-ce-stable
docker-ce.x86_64            3:20.10.16-3.el7                    docker-ce-stable
docker-ce.x86_64            3:20.10.15-3.el7                    docker-ce-stable
docker-ce.x86_64            3:20.10.14-3.el7                    docker-ce-stable
docker-ce.x86_64       
  • yum安装docker
yum install docker-ce-20.10.6 -y
  • yum卸载docker
yum remove -y docker-xxx

安装之后就可以使用了

镜像加速器【配置ustc的加速器】

使用docker首要操作就是获取镜像文件,默认是从Docker hub下载,网速慢,国内的云服务更快

  • 创建修改docker配置文件,选用七牛云镜像站
mkdir  -p /etc/docker

touch /etc/docker/daemon.json

vim  /etc/docker/daemon.json

再其中粘贴 :wq  可以配置其他的
{
  "registry-mirrors": [
  	"https://docker.mirrors.ustc.edu.cn"
  ]
}


cat /etc/docker/daemon.json

------看到结果:
[root@localhost ~]# cat /etc/docker/daemon.json
{
    "registry-mirrors": [
	"https://docker.mirrors.ustc.edu.cn"
    ]
}
  • 配置 加速器之后重新读取配置文件,并设置docker服务开机自启动
systemctl daemon-reload

systemctl enable docker  //设置开机自启动

systemctl restart  docker  //启动docker

这个时候使用docker的命令docker version验证安装是否成功

[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@localhost ~]# systemctl restart  docker
[root@localhost ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.17
 API version:       1.41
 Go version:        go1.17.11
 Git commit:        100c701
 Built:             Mon Jun  6 23:05:12 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community

可以使用ps -ef|grep docker 查看docker进程; 查看之后可以使用

  • docker ps
  • docker images
  • docker version

Docker生命周期

docker整个生命周期由三部分组成: 镜像image + 容器container + 仓库repository

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第2张图片

可以以Git的思维来思考这个过程,gitHub ---- dockerHub

  • Dockerfile: 构建docker镜像的文件,通过douckerfile 可以build自定义的镜像,而使用的各种基础服务的镜像比如redis等直接从registry上面拉取
  • Images: 镜像,类似于虚拟机镜像,是一个只读的模板【理解为静态文件】,一个独立文件系统,包括容器运行的数据,可以用来创建新的容器,images类似于java的类,容器就是其实例化对象【一个image可以有多个container】; 获取镜像的方式: Build from dockerfile; pull from registry 【镜像实际上有一层一层的文件组成,层级文件系统UnionFS
  • Containers: 容器是由镜像创建的运行实例,类似虚拟机,可以run,stop,start,容器内可以运行不同的服务,容器有自己的网络空间和自己的网络IP环境以及文件系统,和宿主机是隔离的,类似于本机上面的虚拟机,容器除了内核,软件运行的其余依赖都有, 但是对于用户来说,直接访问的是宿主机,所以需要进行端口映射和文件映射-p,-v 容器不是虚拟机(操作系统),容器就只是宿主机一个进程
  • Docker Registry: Docker Hub仓库,分为公有仓库和私有仓库【类似于之前的码云,可以设置私有的和公共的,公共的都可以pull拉取源代码】 在网络环境中管理docker images
  • 网络管理镜像

可以从图中看出,images和containers默认都在本地,要remote交互,就必须利用仓库进行交互,和git类似,向hub中提交镜像为 docker push , 拉取镜像为docker pull

  • 本地管理镜像

使用docker save 导出镜像为一个backup.tar压缩文件,这样将文件直接传送给别人再通过docker load生成镜像

  • 本地镜像和容器管理

使用docker run可以利用固定的image生成运行一个具体的容器实例,容器的管理就是stop,start,restart等;

同时可以根据一个具体的容器实例通过docker commit 容器ID 生成一个镜像;

1. 比如获取了一个centos镜像,最小化没有软件
2.docker run centos,运行了一个带有centos服务的容器,可以进入容器内
3. 再容器内安装了一个vim
4. docker commit 容器ID   生成了一个带有vim软件的centos镜像

镜像images原理

images就是一个分层管理的文件系统

之前pull nginx的时候就可以发现细节

[root@localhost ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 
b4df32aa5a72: Pull complete 
a0bcbecc962e: Pull complete 
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

【不加tag,默认tag : latest】pull时一共pull complete了6次,最终进行Hash校验,最终完成下载一个nginx镜像

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   7 months ago   141MB

通过docker images查看本地镜像发现其SIZE比普通的安装包大了许多,普通的安装包就几M

操作系统的镜像文件

网上下载的超过4G的镜像文件实际上包括两个部分: Linux内核(内核只是提供操作系统最基础的比如内存管理,进程调度,文件管理等功能】,以及上层的发行版(各厂商定制化不同的功能,比如Centos发行版)

比如可以使用cat /etc/redhat-realse 查看发行版,通过uname -r查看内核

[root@localhost ~]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
[root@localhost ~]# uname -r
3.10.0-1160.el7.x86_64

linux内核 + centos发行版 组成完整的镜像文件

在虚拟机上灵活替换不同的Linux发行版【相关发行版镜像】

宿主机本体: 笔记本+ vmware(centos7)共用宿主机的内核,使用不同发行版的docker是实现灵活切换

利用docker容器获取不同发行版的镜像,基于该镜像运行出各种不同的容器使用; 镜像只是发行版,没有内核,所以使用的是之前刻录的虚拟机映像(包含内核 和 发行版)所以占用存储大得多

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第3张图片

首先就是下载不同的发行版, 运行docker容器并进入容器内终端执行bash命令解释命令

docker pull ubuntu

docker run -it XXXXX(ID) bash

之后就可以查看一下发行版和内核

[root@localhost ~]# docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete 
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   7 months ago   141MB
ubuntu       latest    ba6acccedd29   9 months ago   72.8MB
[root@localhost ~]# docker run -it ba6acccedd29 bash
root@80daf145fcdb:/# cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
root@80daf145fcdb:/# uname -r
3.10.0-1160.el7.x86_64

可以看到运行之后就进入了容器内部的linux的Ubuntu发行版操作系统,看到发行版已经切换了,但是内核还是没有发生改变

root@80daf145fcdb:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@80daf145fcdb:/# cd etc
root@80daf145fcdb:/etc# ls
adduser.conf            cron.d          deluser.conf  gai.conf   hosts      ld.so.cache    login.defs   mtab           pam.conf   rc0.d  rc5.d        security  subgid       terminfo
alternatives            cron.daily      dpkg          group      init.d     ld.so.conf     logrotate.d  networks       pam.d      rc1.d  rc6.d        selinux   subuid       update-motd.d
apt                     debconf.conf    e2scrub.conf  gshadow    issue      ld.so.conf.d   lsb-release  nsswitch.conf  passwd     rc2.d  rcS.d        shadow    sysctl.conf  xattr.conf
bash.bashrc             debian_version  environment   host.conf  issue.net  legal          machine-id   opt            profile    rc3.d  resolv.conf  shells    sysctl.d
bindresvport.blacklist  default         fstab         hostname   kernel     libaudit.conf  mke2fs.conf  os-release     profile.d  rc4.d  rmt          skel      systemd
root@80daf145fcdb:/etc# exit
exit
[root@localhost ~]# 

使用exit就可以退出容器内的终端,回到原本的虚拟机容器;这个时候也停止了该容器

docker镜像解决问题【迁移,不依赖】

如果没有docker,就需要直接在宿主机安装很多软件,可能造成的问题就是占用存储、环境不兼容,会破环当前系统的环境,卸载麻烦,迁移非常麻烦,因为系统不一样,只能在次进行各种配置

如果安装docker,解决环境问题:在容器中运行各种发行版,并且不想使用软件,直接删除容器即可,不影响宿主机 【windows + docker + 不同的容器】

如果想要将mysql容器内的数据配置全部迁移到服务器,只需要提交该容器为镜像,镜像放到服务器再运行run容器即可

images分层原理

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第4张图片

通过docker pull下载的一个镜像就是上述的分层结构,最终识别为一个文件是依赖的UnionFS 联合文件系统,将上述的不同的每一层整合为一个文件系统,隐藏多层的视角

上面的图中就是构建一个普通的web应用需要构建Linux内核(宿主机提供),需要运行的Linux发行版基础镜像,和更上层的jdk镜像,上面的tomcat容器依赖,最终的web程序的镜像写入可写程序,就可以直接运行web程序

  • bootfs: boot file system主要包括bootloader和kernel,bootloader引导加载kernel,Linux刚启动时会加载bootfs文件, 依赖于宿主机提供的Linux内核;所以会首先加载宿主机的内核
  • rootfs: 基础镜像: root-file system,获取发行版,docker获取基础镜像,rootfs就是各种不同的发行版
  • 镜像: 依赖环境,比如使用centos提供的软件管理,yum install curl/nginx
  • 可写容器: 具体程序运行位置,可以写入想运行的代码程序,容器层和可写层如代码修改后重启容器生效

可以看到一个镜像是包括从最底层的Linux内核、使用的发行版,和上面运行该程序需要的其他的依赖,更上层的依赖,最上层才是可写层的自定义代码,下面的几层都是只读的,不可写,只有自定义的是可写的,整个构成一个镜像;dockerfile就是一层一层构建;

  1. dockerfile的作用: 自定义docker镜像每一层的作用【每一层的选择】
  2. 当通过image启动容器,docker会在容器最顶层,添加一个读写文件系统作为容器,然后运行该容器
  3. docker的基础镜像很小 是因为 内核是由宿主机提供,基础镜像只是系统的发行版
  4. 下载nginx镜像 比安装包大 是因为 docker的nginx镜像分层,依赖于父镜像(上一层)和基础镜像,所以最终下载下来就很大【启动容器就可以运行,不用再担心环境 nginx只能运行在Linux系统上面,不能运行在windows上面】
docker镜像【每一个镜像都包含完整的层,至少包含base】

we如果自定义镜像,docker镜像不包含Linux内核,和宿主机公用;比如如果要自定义mysql8的镜像,需要先获取基础镜像,选择一个发行版平台,之后在centOS镜像中安装mysql8软件,导出镜像,命名为mysql8镜像文件

镜像从下层向上层不断添加,底层centos镜像,上层是mysql镜像,centos为父镜像

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第5张图片

所以说我们pull拉取的每一个镜像都是包含完整的几层的,都是具有相关的依赖环境的,比如拉取的nginx肯定是包括运行nginx的发行版的,可以通过exec进入容器内部查看【】

[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   7 months ago   141MB
ubuntu       latest    ba6acccedd29   9 months ago   72.8MB

这里就可以解释为什么nginx镜像比ubuntu大,是因为越下层的镜像的依赖越少; 而nginx需要依赖发行版镜像,除了debian的镜像之外还有就是其他的镜像依赖

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
ab456314fbc6   nginx     "/docker-entrypoint.…"   5 seconds ago   Up 3 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   naughty_yalow
[root@localhost ~]# docker exec -it ab456314fbc6 bash
root@ab456314fbc6:/# cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
root@ab456314fbc6:/# exit
exit
[root@localhost ~]#

可以看到这个容器依赖的发行版为Debian

分层的好处

镜像分层的好处就是共享资源,比如多个镜像来自同一个base镜像,那么在docker host主机只需要存储一份base镜像即可; 内存中也只需要加载一份host为多个容器服务,多容器共享

多容器共享同一个base镜像==,某个容器修改了base镜像的内容,比如/etc下面的配置文件,其他的容器中的是不会修改的 ----- 写入时复制性==,Copy on write; 修改动作基于当个容器【CopyOnWriteArrayList也是修改时复制一份修改,最后才替换】

可写的容器层 Copy On Write

当容器启动后,一个新的可写容器会挂在到镜像的顶部,这一层被称为可写容器层,容器层下面都是只读镜像层

在容器运行时,所有对容器的修改操作,都只会发生在容器层里,其余不可修改,比如文件操作:

  • 添加文件: mkdir再touch文件,新文件会添加到容器中,不会修改底层的Debian系统
  • 读取文件:当需要cat文件,docker会从上到下个镜像层查找文件,一旦找到,立刻复制到容器层,打开并读入内存 【查看的只是副本】
  • 修改文件,当需要修改文件,ocker会从上到下个镜像层查找文件,一旦找到,立刻复制到容器层,然后修改,【修改的只是副本】
  • 删除文件: 在容器中删除文件,也是自上而下查找,找到后,在容器中记录下此删除操作 【只是记录】,不会真正删除

分层的镜像最终通过docker的UnionFS功能让用户只感知到一个完整的镜像

Docker快速使用【nginx运行

Docker的CS架构,分为客户端和服务端,客户端向服务端发命令【redis】

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第6张图片

we通过客户端向服务端进程docker daemon发起请求,获取到镜像images,之后通过镜像加载容器containers

比如这里演示使用Nginx【web服务器,进行转发的负载均衡,运行出80端口的网站】,首先就是获取镜像,之后运行运行镜像、生成容器

如果不使用docker,在宿主机上想要运行nginx

  1. 开启服务器
  2. 在服务器上安装ngix所需要的依赖关系
  3. 安装nginx, 直接yum install nginx -y
  4. 修改nginx配置文件
  5. 启动nginx
  6. 客户端访问nginx

这比较耗费时间,还有比如安装redis,mongoDB等

使用docker方式就非常便捷:

  • 从镜像站中搜索镜像
docker search nginx


--------------------搜索结果---------------
[root@localhost ~]# docker search nginx
NAME                                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                                             Official build of Nginx.                        17165     [OK]       
linuxserver/nginx                                 An Nginx container, brought to you by LinuxS…   169                  
bitnami/nginx                                     Bitnami nginx Docker Image                      137                  [OK]
ubuntu/nginx                                      Nginx, a high-performance reverse proxy & we…   55                   
bitnami/nginx-ingress-controller                  Bitnami Docker Image for NGINX Ingress Contr…   19                   [OK]
rancher/nginx-ingress-controller                                                                  10                   
ibmcom/nginx-ingress-controller                   Docker Image for IBM Cloud Private-CE (Commu…   4                    
bitnami/nginx-ldap-auth-daemon                                                                    3                    
rancher/nginx                                                                                     2                    
bitnami/nginx-exporter                                                                            2                    
rapidfort/nginx                                   RapidFort optimized, hardened image for NGINX   2                    
vmware/nginx                                                                                      2                    
rancher/nginx-ingress-controller-defaultbackend                                                   2                    
circleci/nginx                                    This image is for internal use  
  • 从上面配置的镜像站: regisrty 中拉取下载nginx镜像
docker pull nginx  
  • 运行该nginx镜像,运行出具体的nginx服务
docker run  -d -p 80:80  nginx

运行的结果可以看到容器的创建时间,还有端口的映射情况

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                               NAMES
4bf6ce6a687d   nginx     "/docker-entrypoint.…"   21 seconds ago   Up 17 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   pedantic_joliot
  • 查看宿主机的端口active,运行的服务 netsat -tunlp
[root@localhost ~]# netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      798/rpcbind         
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      1541/dnsmasq        
tcp        0      0 0.0.0.0:22      

这样虚拟机上面就完整跑了一个nginx服务
【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第7张图片

Docker镜像管理常用命令

docker search XXX 在regisry镜像站中搜索XXX镜像

这里的镜像站regisry(dockerhub,包括提供的优质的镜像和用户自己上传的镜像)就是上面镜像加速配置的json文件中的regisry,可以修改为其他的,i 使用的ustc的

[root@localhost ~]# docker search nginx
NAME                                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                                             Official build of Nginx.                        17165     [OK]       
linuxserver/nginx                                 An Nginx container, brought to you by LinuxS…   169                  
bitnami/nginx                                     Bitnami nginx Docker Image                      137                  [OK]
......  第一个的为最优选项,可以看到点赞数STARS最多并且OFFICIAL授权
docker pull XXX (:tag)

从镜像站拉取下载镜像,可以加上标签tag,不加就会默认加上latest也就是最新的软件;默认加上:latest 版本号 比如 :8.8.9

docker images (image ls)【-q】 【名称 + tag】 查看本地镜像
  • -q: quit 简略显示本地的镜像

可以通过docker image ls或者docker images查看本地有所有镜像;加上具体的名称就可以进行过滤得到精确的查找结果

[root@localhost ~]# docker image ls
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

会按照上面的标签进行显示: tag为版本号, IMAGE ID为镜像的唯一标识ID

还可以使用–format进行更精确的匹配:

docker images --format "{{.ID}}--{{.Repository}}"  格式化显示(docker模板语言)只显示id和repository

docker images --format "table {{.ID}\t{{.Repository}}/t{{.Tag}}" 表格形式显示
docker rmi [docker ID前三位就可] 删除本地ID为XX的镜像【不依赖记录rm】

rmi为remove image,删除本地ID为XXX的镜像

[root@localhost docker-learn]# docker rmi 406d335e4ee6
Untagged: my-nginx:latest
Deleted: sha256:406d335e4ee65ae3a2cddb6ca78b61008438bbd65c3416b68cd30eb744b81c32
Deleted: sha256:5a0b88df2decb9221e09e728bce6b686900f6f982d6a3a2697a84b5102f1ab8a

还可以直接批量删除:

docker rmi `docker images -aq`

需要注意的是删除的镜像不能依赖于任何的容器记录,如果有,先rm相关的容器记录

docker image save XXX > XXX.tgz 导出镜像为压缩包,指定路径

导出镜像,比如默认运行的centos镜像,不提供vim功能,所以可以运行容器后,在容器内可以安装vim,然后导出为压缩包给他人使用

比如:
docker run -it centos:XXX  bash
---> 进入容器内centos发行的终端
~ : vim                       【bash: vim: command not found】
~ : yum install vim -y    【安装最新版的vim,直接yum install下载】
~ : vim  有功能了
~ : 退出返回

docker ps -a: 
会显示上面关闭的容器,直接docker commit 该记录为镜像

docker image save centos:XXX > /opt/centos.XX.tgz    保存为压缩文件在/opt目录下

docker image load -i XXXX.tgz 从指定路径下导入镜像

XXXX.tgz为一个完整路径,该路径下存在导出的镜像的压缩包,导入该压缩包即可

docker image inspect 镜像ID 显示镜像的详细信息

docker info查看的是docker进程的详细信息,要查看image的详细信息,使用inspacet命令,显示的都是JSON格式的信息

[root@localhost ~]# docker image inspect 605
[
    {
        "Id": "sha256:605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85",
        "RepoTags": [
            "nginx:latest"
        ],
        "RepoDigests": [
            "nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-12-29T19:28:29.892199479Z",
        "Container": "ca3e48389f7160bc9d9a892d316fcbba459344ee3679998739b1c3cd8e56f7da",
        "ContainerConfig": {
            "Hostname": "ca3e48389f71",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
......

Docker容器管理命令

docker run 【参数 -p -v -d -i t --rm】 镜像名称/ID 【bash等】 运行镜像生成容器(还可进入容器)

使用docker run就可以运行镜像生成容器,运行结果就是生成一个容器的ID 等同于创建+ 启动,如果镜像不存在于本地,则会在线下载镜像,容器内的进程必须处于前台运行状态(默认情况下,不加-d) ----- 也就是CTRL + C会退出【redis直接启动的状态】 比如这里,否则会直接退出;如果容器内什么都没做,容器也会挂掉

参数如下:

  • -d : 后台运行容器,就类似redis的后台运行,不会占用当前终端
  • -p: portmap 端口映射, 格式: -p 宿主机端口:容器端口; 比如-p 80:80 就是访问宿主机的80端口就是访问容器的80端口
  • -v: 目录映射,容器有自己的文件系统和网络环境,宿主机也是,但是访问的时候直接访问的是宿主机,而不是容器,所以网络环境需要端口映射,文件系统需要目录映射,目录映射就是访问宿主机的某目录 就会 自动映射访问容器内的某目录 -v 宿主机目录:容器目录, 在容器内访问挂载目录就是访问宿主机某个目录,二者文件夹内内容相同
  • -P: 随机端口映射,随机找到宿主机的一个端口【空闲的】
  • -i : 交互式命令操作,进入容器进行交互式操作
  • -t: 开启一个终端
  • –rm: 容器退出时自动删除容器
  • –name: 给容器起名称 【会显示在docker ps中】
  • bash : 进入容器后执行的命令,Linux的命令的解释必须依赖bash,也可以是执行其他的命令 docker run --rm centos:XXX ping www.baidu.com 就是运行容器之后执行容器内执行ping命令(不会进入容器)

比如: docker -run -d -p 80:80 nginx docker -run -it XXX(Ubantu发行版的镜像ID) bash

------------------------------------------
|            _________________________   |
|			|	容器                 |  |
|		    |  内部运行80端口的nginx  |   |
|			========================|   |
|    宿主机,无服务    ↑  端口隐射,转发访问|
-------------------------------------------
                 ↑
                 |
                 |   客户端client发起对宿主机80端口nginx服务的访问
此时宿主机80端口实际运行的是容器docker-proxy代理
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      6854/docker-proxy 

如果容器不是前台运行状态,则挂掉(默认情况下,不加-d)会占用一个终端

docker run nginx
xxxxx
xxxxx

CTRL + C 退出

执行docker ps 发现容器没有运行

如果容器内没有任何前台运行的进程,则挂掉

docker run centos:XX
什么都不会发生,因为centos为一个base,里面没有其他执行的进行,不会前台运行,只会记录容器记录
docker logs 【-f】 容器ID 查看容器日志

如果想要知道容器干了什么事情,就可以查看容器的日志,通过docker logs完成

  • -f: 实时刷新日志,CTRL + C退出
[root@localhost ~]# docker logs ab456314fbc6
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
docker container inspect 容器ID 查看容器详细信息

之前查看镜像详细信息也是inspect命名,docker image inspect ID ,这里就是container

[root@localhost ~]# docker container inspect ab456314fbc6
[
    {
        "Id": "ab456314fbc613751201f30ff99d953fb3048a67af1963c805d2c0ef3381b724",
        "Created": "2022-07-29T10:07:34.080160197Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
....

这里也是显示的是JSON格式的数据

docker exec -it 容器ID bash 进入容器内的发行版终端

进入到正在运行的容器内,-it还是进入交互打开终端,bash就是加载发行版Linux的基本命令的解释器,所以该命令实际就是进入到容器内运行的发行版的中终端上面

exit (容器内执行) 退出容器

如果通过 run -it进入了容器,可以直接通过exit退出容器

docker ps 【-a】 查看本地容器运行情况

这个命令可以查看本地容器的运行情况

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

可以看到包含容器的ID,镜像,创建时间,端口和状态、名称等信息,只是查看正在运行的容器的信息

  • -a 加上该参数可以显示所有的记录,包括正在运行的和stop的【docker ps -a】
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                   PORTS                               NAMES
ab456314fbc6   nginx          "/docker-entrypoint.…"   57 minutes ago   Up 57 minutes            0.0.0.0:80->80/tcp, :::80->80/tcp   naughty_yalow
80daf145fcdb   ba6acccedd29   "bash"                   2 hours ago      Exited (0) 2 hours ago                                       brave_chatterjee
4bf6ce6a687d   nginx          "/docker-entrypoint.…"   3 hours ago      Exited (0) 2 hours ago                                       pedantic_joliot
docker port 容器ID 查看容器的端口转发情况

要想查看容器内的端口映射情况,就使用port查看

[root@localhost ~]# docker port ab456314fbc6
80/tcp -> 0.0.0.0:80
80/tcp -> :::80
docker commit 容器ID diy的镜像名 将容器提交为镜像放到本地镜像库

这里的容器ID可以通过docker ps -a 查询, diy镜像名一般是 github账号/镜像名

docker rm 镜像ID 删除镜像记录

通过该命令可以直接删除上面的-a查询到的所有的记录

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                   PORTS                               NAMES
ab456314fbc6   nginx          "/docker-entrypoint.…"   57 minutes ago   Up 57 minutes            0.0.0.0:80->80/tcp, :::80->80/tcp   naughty_yalow
80daf145fcdb   ba6acccedd29   "bash"                   2 hours ago      Exited (0) 2 hours ago                                       brave_chatterjee
4bf6ce6a687d   nginx          "/docker-entrypoint.…"   3 hours ago      Exited (0) 2 hours ago                                       pedantic_joliot
[root@localhost ~]# docker rm 4bf6ce6a687d 
4bf6ce6a687d
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED             STATUS                   PORTS                               NAMES
ab456314fbc6   nginx          "/docker-entrypoint.…"   About an hour ago   Up About an hour         0.0.0.0:80->80/tcp, :::80->80/tcp   naughty_yalow
80daf145fcdb   ba6acccedd29   "bash"                   2 hours ago         Exited (0) 2 hours ago                                       brave_chatterjee

批量删除: -q 都是简化显示

docker -rm `docker ps -aq`  
docker stop 容器ID 停止容器的运行

容器运行就相当于是容器内的服务运行着,想要停止容器的运行,就使用该命令就可以停掉服务

docker start 容器ID 开启容器的运行【stop的】

docker start 容器是将stop的容器开启,和run有区别,start是用于开启,而run是创建运行

docker restart 容器ID 重启容器yunx

将正在运行的容器重启,一般就是修改配置后需要重启

docker version 查看docker的版本

可以使用该命令查看下载的docker,通过yum下载的docker,可用于验证是否下载成功

docker info 查看docker的基本信息【存储镜像位置…】

可以通过docker info查看信息,当然:信息非常多,可以通过grep进行过滤

[root@localhost ~]# docker info| grep Root
 Docker Root Dir: /var/lib/docker
 
 下面的image文件夹下面的...../sha256记录的就是镜像和容器的配置关系

可以看到docker的文件存放目录在var下面的lib下面的docker

docker build Dockerfile文件位置

可以通过该命令利用Dockerfile构建出镜像

docker tag 容器ID 自定义容器Name

dockerfile构建的容器默认情况下名称为空,指定名称就使用docker tag命令即可

docker tag XXXX my-nginx

dockerfile 常用指令

镜像是一个分层的文件系统,dockfile相当于一个脚本,通过dockerfile自己的指令,来构建软件依赖、存储…; 镜像多层存储,每一层都是在前一层的基础上进行修改,容器也是多层存储,以镜像为基础层,基础上再加一层作为容器运行时的存储层,所有的修改都保存再这一层,形成的最终的自定义的容器

定制docker镜像的方式有两种:

  • 手动修改容器内容,导出新的镜像 exec -it进入,修改,commit提交为镜像
  • 基于Dockerfile自行编写指令,基于指令流程创建镜像

dockerfile主要组成部分:

  • 基础镜像信息: 比如 FROM centos:7.xxx
  • 制作镜像操作指令: RUN yum install openssh-server -y 万能只能
  • 容器启动时执行指令 : CMD【“/bin/bash”】 docker run 容器时容器内会执行的命令,比如开启服务等
需求: 虚拟机安装mysql并启动

虚拟机部署:
1. 开启虚拟机,centos7
2. 安装mysql    yum install mysql-server  【部署缓慢,会占用3306端口,修改了宿主机环境,删除麻烦 --- linux】
3. 通过脚本或者命令,启动mysql

docker部署:
1. 开启虚拟机,centos7(宿主机)
2. 安装docker【如果没有】
3. 自己编写dockerfile 【或者pull定制好的镜像,但是无法自由控制base镜像,比如bae为debian】
4.运行镜像,通过端口映射  run XXX   
5. 访问宿主机的映射端口,访问到容器内的mysql

dockerfile常用的指令如下:

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第8张图片

FROM 指定base image【不一定从发行版开始构建,可以直接在任何镜像】

内核是宿主机提供,所以需要关注的最底层就是Linux的发行版,FROM就是指定base image,这里的base image不一定是发行版环境,还可以是其他的镜像的基础上继续搭建;

比如 FROM nginx; 就是在nginx这个官方镜像的基础上继续搭建属于自己的服务

MAINTAINER 指定维护者信息【可以没有】

使用MAINTAINER可以指定项目的维护者信息,用则重要,不用则不重要

RUN 构建镜像时执行的…命令

这个是最重要的指令,基础进行由FROM指定,但是上面运行的其他的依赖,都是需要下载的,还有指定yum源或者其他的安装源; 比如yum install mysql-server ----> RUN yum install mysql-server

ADD 复制宿主机文件进入容器内, 会自动解压

宿主机文件系统和容器文件系统是隔离的,再windows和linux虚拟机传递文件使用Xftp,而再宿主机和容器内使用的是ADD指令【都是隔离的,不会影响】,和COPY简单复制不同,会自动解压; gzip,bzip2,xz,tar等都会解压

  • ADD 源文件 镜像目录

源文件支持URL,docker引擎会自动下载连接,放入目标路径,权限自动为600,如果为压缩文件,不会自动解压,只能RUN

ADD  ceng.tgz   /home/

RUN tar -zxf /opt/XXXX.tgz     //会报错,因为会自动解压,没有这个压缩文件了
COPY 复制…和ADD一样

COPY命令和ADD命令的作用是相同的,只是COPY指定复制的文件仅仅复制

复制宿主机文件/目录到新的一层的镜像中

COPY指令可以保留源文件的元数据,比如权限、访问时间

  • COPY 宿主机文件目录【通配,1…*】 镜像目录
COPY cfeng*  /tmp/cc?.class  /home/
WORKDIR 设置当前工作目录【类似cd的作用】

很多容器进入后默认是根目录,但是有些进入则是其他的目录,实现的方式就是WORKDIR

  • WORKDIR /opt 改变linux下工作目录
USER 改变环境,切换用户
  • USER 用户

比如USER cfeng ; 相当于在镜像操作内切换用户,和Linux直接操作命令su类似

VOLUME 设置卷,挂载主机目录【目录映射】

容器有自己的网络空间和文件系统【base image】,只是内核和宿主机共享,访问时直接访问的是宿主机的文件目录,所以需要进行目录映射,将宿主机目录挂载

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第9张图片

容器在运行时,应该保证在存储层不写入任何数据,运行时容器内产生的数据,推荐挂载写入宿主机内,进行维护

  • VOLUME 容器目录 容器运行时,自动和宿主机目录进行映射

比如 VOLUME /data 将容器内/data文件夹,容器运行时,自动挂载为匿名卷,任何向该目录写入数据的操作,都不会被容器记录,保证状态

FROM centos
MAINTAINER cfeng
VOLUME ["/data1","/data2"]  容器运行时,会自动映射到宿主机
EXPOSE 打开门,指定对外的端口,暴露端口

容器的网络空间独立,要能够进行端口映射,需要容器暴露一个端口,不暴露那容器就是一个封闭的容器,不能通过网络访问到其内部的内容

比如nginx就可以暴露80端口: EXPOSE 80

指定容器运行时对外提供的端口

ENV 【ARG】 设置容器的环境变量

env可以设置环境变量

环境变量就是整个系统都可以设置和调用的变量,在spring项目中we就是使用properties设置变量,同时可以在maven中设置变量,使用@XXXX@引用maven设置的变量

在windows系统中,在查看高级系统设置中配置环境变量,这样就可以在windows系统中使用, 使用%xxx%引用变量, 永久设置变量就在查看高级系统中设置,比如这里色湖之了

C:\Users\OMEY-PC>echo %path%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0;D:\MySQL\MySQL Server8.0.27\bin;D:\jdk-16\bin;";D:\Tomcat 9.0\bin;D:\Tomcat 9.0\lib";D:\Tomcat 9.0\bin;C:\Program Files\Microsoft Network Monitor 3\;D:\Maven\apache-maven-3.8.4\bin;D:\nodejs\;D:\nodejs\node_global;C:\Windows\System32\OpenSSH\;:\Windows\System32\OpenSSH;D:\git\Git\cmd;D:\Springboot-cli\spring-2.3.1.RELEASE\bin;D:\MongoDB\Server\4.2\bin;D:\jdk-16\bin;D:\mudelsim\modelsim 10.4 crack\modelsim exe\win64;";D:\Tomcat 9.0\bin;D:\Tomcat 9.0\lib";;D:\JetBrains\IntelliJ IDEA 2019.3.2\bin;;C:\Users\OMEY-PC\AppData\Roaming\npm

这里时直接将变量给引入了,在设置的时候是使用了变量的比如: 在上面的path路径设置中就是替换了D:\jdk-16
C:\Users\OMEY-PC>echo %JAVA_HOME%
D:\jdk-16

在Linux系统中也需要设置环境变量; 比如指定安装的软件的版本

比如
yum install mysql-${mysql_version}
  • ENV 变量名 变量值 通过$NAME获取变量值
ENV MYSQL_VERSION = 8.2.4

维护时直接调用即可

ARG和ENV都是设置环境变量;

ENV设置的变量,在镜像构建时,还有容器运行时都可以使用

ARG设置的变量,只能在镜像构建时使用,容器运行时消失

CMD 指定容器启动后需要执行的事情

比如nginx就是启动后执行一个entrypoint脚本文件; docker run指定的命令会覆盖CMD中指定的命令

  • CMD [“参数1”,“参数2” …]
CMD["/bin/bash"]   进入容器后执行/bin下面的bash命令

执行后查看系统版本,  cat /etc/os-release是两条命令
CMD["cat","/etc/os-release"]
等同于 docker run XXXX cat  /etc/os-release

在指定entrypoint之后,用CMD指定具体的参数; docker不是虚拟机,容器就只是一个进程,既然是进程,程序启动时需要指定运行参数,由CMD完成

之前run 命令结尾指定的bash就是进入容器后执行的命令,如果不指定任何命令,那么就会使用设置的CMD默认命令

centos镜像默认的CMD就是/bin/bash, docker run -it centos会直接进入bash解释器,等同于docker run -it centos bash

ENTRYPOINT【传入的只是当作参数,而CMD形式为覆盖】

和RUN指令类似,分两种格式: exec和shell, 作用和CMD一样,都是指定容器启动程序以及参数

但是当指定ENTRYPONT之后,CMD指令语义发生变化, 把CMD指令的内容当作参数传递给ENTRYPONIT指令

//这里简单指定一个EntryPoint,rebuilddb代表更换yum源
FROM centos:7.8.2003
RUN rpm --rebuilddb && yum install epel-release -y
RUM rpm --rebuilddb && yum install curl -y
CMD["curl","-s","http://ipinf.io/ip"] //不会运行前台运行任何程序,所以得到结果后容器挂掉,docker ps无


启动容器
docker run centos_curl -I  该形式无法传入参数,是覆盖了dockerfile中的CMD,但是没有-I,所以就会报错

如果想要正确完成curl -s http://ipinfo.io/ip -I
  • 可以直接run时传入完整的命令【覆盖】 docker run centos_curl curl -s http://ipinfo.io/ip -I
  • 使用ENTRYPOINT代替CMD, CMD run时传入的只是参数
FROM centos:7.8.2003
RUN rpm --rebuilddb && yum install epel-release -y
RUM rpm --rebuilddb && yum install curl -y
ENTRYPOINT["curl","-s","http://ipinf.io/ip"] 

重新构建镜像后,就可以直接传入参数使用了

docker run centos_curl -I

Dockerfile快速实践

这里我们就利用dockerfile自定义一个nginx,个性化的显示:容器启动后,生成自定义的页面

  1. 构建Dockerfile,文件名必须是这个
[root@localhost /]# cd ~
[root@localhost ~]# ls
anaconda-ks.cfg  cfeng  initial-setup-ks.cfg  公共  模板  视频  图片  文档  下载  音乐  桌面
[root@localhost ~]# cd cfeng
[root@localhost cfeng]# mkdir docker-learn
[root@localhost cfeng]# cd docker-learn/
[root@localhost docker-learn]# vim Dockerfile

这里vim Dockerfile就会创建一个Dockerfile文件,进入编辑

  1. 在Dockerfile中定义操作,这里比较简单,可以直接在官方的nginx基础上构建,修改nginx服务的index.html ;这里可以在Xshell中直接使用shift + insert就可以将内容粘贴到vim打开的文件中

FROM指定基础镜像,如果本地存在,就会直接使用,如果没有,那么就会去hub下载

可以看懂build过程中就直接使用了本地的ID的nginx镜像

FROM指定基础镜像,如果本地存在,就会直接使用,如果没有,那么就会去hub下载

FROM nginx  
RUN echo 'Cfeng nginx

Welcom to Nginx, Cfeng

'
> /usr/share/nginx/html/index.html ============================== [root@localhost docker-learn]# vim Dockerfile [root@localhost docker-learn]# cat Dockerfile FROM nginx RUN echo 'Cfeng nginx

Welcom to Nginx, Cfeng

'
> /usr/share/nginx/html/index.html
  1. build 镜像 可以直接使用docker build . 因为当前目录下面就有Dockerfile,所以.即可指定, 成功后会返回要给镜像的ID
[root@localhost docker-learn]# ls
Dockerfile
[root@localhost docker-learn]# docker build .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx
 ---> 605c77e624dd
Step 2/2 : RUN echo 'Cfeng nginx

Welcom to Nginx, Cfeng

'
> /usr/share/nginx/html/index.html ---> Running in df2d56974bab Removing intermediate container df2d56974bab ---> 406d335e4ee6 Successfully built 406d335e4ee6
  1. 创建出的镜像只有id,没有name,所以使用docker tag指定 名称
[root@localhost docker-learn]# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
           406d335e4ee6   About a minute ago   141MB
nginx        latest    605c77e624dd   7 months ago         141MB
ubuntu       latest    ba6acccedd29   9 months ago         72.8MB
[root@localhost docker-learn]# docker tag 406d335e4ee6 my-nginx
[root@localhost docker-learn]# docker image inspect 406d335e4ee6
[
    {
        "Id": "sha256:406d335e4ee65ae3a2cddb6ca78b61008438bbd65c3416b68cd30eb744b81c32",
        "RepoTags": [
            "my-nginx:latest"
        ],

  1. 本地运行镜像 docker -d run -p 80:80 my-nginx
[root@localhost docker-learn]# docker run -d -p 80:80 406d335e4ee6
b59b5b181bcdae17b4de0a8e94fb197b4348e73e9915994f7efe0dceedb2d346
[root@localhost docker-learn]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                               NAMES
b59b5b181bcd   406d335e4ee6   "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   zen_austin

现在就可以直接访问了,容器内部的窗口开放等都是原本nginx的服务,只是在其基础上进行了改动

[root@localhost docker-learn]# docker exec -it b59b5b181bcd bash
root@b59b5b181bcd:/# cd /usr/share/nginx/html
root@b59b5b181bcd:/usr/share/nginx/html# ls
50x.html  index.html
root@b59b5b181bcd:/usr/share/nginx/html# cat index.html
<meta charset="utf-8"></span>Cfeng nginx<span class="token filehandle symbol"><body style="background-color: aquamarine;">

Welcom to Nginx, Cfeng

root@b59b5b181bcd:/usr/share/nginx/html# exit exit

可以看到是成功自定义镜像

容器内运行程序 docker只是进程

docker不是虚拟机,虚拟机内部的程序运行,基本都是后台运行,利用systemctl可以管理运行,但是容器内没有后台进程的概念,必须前台运行

容器就是为了主进程而存在,主进程退出了,容器失去意义,自动退出

而前面的-d参数 是让容器这个作为宿主机的进程后台运行,和redis一样,但是对于容器内部而言,没有操作系统的概念

CMD systemctl start nginx    这样写错误,容器立刻退出
因为systemctl start nginx是以守护进程(后台运行)形式启动nginx ---- 错误,且CMD命令转化为
CMD["sh","-c","systemctl start nginx"]  sh解释器,执行完毕立刻结束,容器退出

正确写法:
CMD["nginx","-g","daemon off"] 前台运行启动

docker简单介绍到这里,了解到docker的核心概念和常用命令,其余的深入的部分以后再开

接下来就介绍java项目的部署运行监控,当然会使用Docker进行发布部署

Boot项目发布部署

spring boot程序的发布部署方式非常多,有基本的打包部署,Docker部署和RPM部署

多环境配置 spring Profile

开发过程中可能会: 一个程序在软件开发的不同阶段需要部署到不同的环境中:开发环境,测试环境,演示环境、生产环境; 各个环境的配置项存在差异; 比如开发环境和测试环境使用的数据库不同,如果配置只是手工修改,非常难以手动维护

在Spring Boot开发中,Spirng 提供了Spring Prifile功能,允许将环境变量抽离出来,每一种profile对应一套配置,指定某种profile之后,配置文件内容将会只是启用对应的配置文件,再结合maven profile功能,可以完美实现需求

针对不同的环境,创建不同的配置文件 applications-${env}.yml

这里演示基本的开发环境dev和生产环境prod; 不同的环境端口号不同

application-prod.yml

server:
  port: 8082  #生产环境对应的端口和开发环境不同
  ......

application-dev.yml

server:
  port: 8081
 ......

同时再创建一个总的application.yml 管理不同环境的yml文件,使用profiles指定active的文件

application.yml

##### 管理各环境配置文件active的总yaml文件#########
spring:
  profiles:
    active: @activatedProperties@   #自定义参数使用maven管理

这里配置的active的文件使用maven来进行管理,使用@XXXX@定义maven中的properites中

在pom.xml添加profile以及对应activatedProperties变量

	<profiles>
		<profile>
			<id>devid>
			<activation>
				<activeByDefault>trueactiveByDefault>
			activation>
			<properties>
				<activatedProperties>devactivatedProperties>
			properties>
		profile>
		<profile>
			<id>prodid>
			<properties>
				<activatedProperties>prodactivatedProperties>
			properties>
		profile>
	profiles>

这里设置的mvn profile,配置不同的profile,将id为dev的设置activationDefault,各profile的activatedProperties与id名称相同,这个参数在项目打包时会自动注入到application.yml的spring.profile.active中

【开发技术】2万字详细介绍Docker 和 web项目的部署监控,docker部署,拉取kafana,prometheus镜像监控_第10张图片

这样可以直接在旁边的maven工具中勾选对应的profile,打包可以直接指定不不同的profile-id

mvn clean package -P

启动程序,可以看到启动日志中看到使用的profile

 main] com.Jning.cfengtestdemo.DemoApplication  : The following 1 profile is active: "prod"
 Tomcat started on port(s): 8082 (http) wi

springBoot内置Tomcat ---- 打包为可执行jar文件

spirng boot自身支持的打包方式: 可执行的jar格式和部署在传统的web容器中的war格式

jar文件是后缀为jar的文件格式,打包文件包含工程已编译的依赖库,资源文件等、以及压缩的应用程序类文件【application】

应用程序类会放在BOOT-INF/classes目录,依赖以jar形式放在BOOT-INF/lib中

要将应用打包为jaf文件,首先依赖中要设置打包格式:

<packaging>jarpackaging>

将项目打包为可执行的jar,如果基于Maven构建,使用spring-boot-maven-plugin插件就可以完成,在pom.xml中增加该插件

<plugins>
			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombokgroupId>
							<artifactId>lombokartifactId>
						exclude>
					excludes>
				configuration>
			plugin>
		plugins>

i 这里是spring init构建项目添加lombok依赖自动添加的插件,需要排除Lombok依赖, 注意配置一下镜像,因为仓库下载资源,中央仓库很慢,可以配置国内镜像; 注意setting.xml中已经有mirrors标签,就不要重复定义,将mirror放在原mirros中即可

之后执行命令mvn package完成工程打包

这个时候可能因为测试的问题出现打包失败的问题;可以直接使用命令

mvn package -DskipTests

代表跳过测试,但是会编译测试用例; 打包完成之后就可以便捷部署,部署的方式就是环境只要有对应版本的JDK/JRE即可

将jar文件放在部署目录,在部署目录下面执行命令就可以启动程序

java -jar XXX.jar

执行之后就相当于启用该springBoot项目,会开启内嵌的tomcat,启用容器,成功部署在本机上面

PS D:\softVM\javaSkillGit\cfeng-test-demo\target> java -jar cfeng-test-demo-0.0.1-SNAPSHOT.jar

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.2)

2022-07-28 09:16:46.384  INFO 9152 --- [           main] com.Jning.cfengtestdemo.DemoApplication  : Starting DemoApplication v0.0.1-SNAPSHOT using Java 16 on DESKTOP-4A4BD0R with PID 9152 (D:\softVM\javaSkillGit\cfeng-test-demo\target\cfeng-test-demo-0.0.1-SNAPSHOT.jar started by OMEY-PC in D:\softVM\javaSkillGit\cfeng-test-demo\target)
2022-07-28 09:16:46.393  INFO 9152 --- [           main] com.Jning.cfengtestdemo.DemoApplication  : No active profile set, falling back to 1 default profile: "default"
2022-07-28 09:16:48.380  INFO 9152 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-07-28 09:16:48.538  INFO 9152 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 133 ms. Found 1 JPA repository interfaces.
2022-07-28 09:16:50.401  INFO 9152 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2022-07-28 09:16:50.424  INFO 9152 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-07-28 09:16:50.424  INFO 9152 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-07-28 09:16:50.591  INFO 9152 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-07-28 09:16:50.591  INFO 9152 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4057 ms
2022-07-28 09:16:51.193  INFO 9152 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-07-28 09:16:51.352  INFO 9152 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.10.Final

可以看到其实和在IDEA中运行开发环境的项目类似的

基于传统的web容器 ---- 打包为war可执行文件

war文件和jar文件类似,都是归档文件,区别就是jar是可以单独执行的,也可以是类库文件; 但是war文件是依赖于Servlet容器的

在war文件中,依赖项是放在WEB-INF/lib中,运行时要部署到Servlet容器中,不需要的依赖项(provided)放置在WEB-INF/lib-provided中

war打包不是默认选项(jar),需要在默认的基础上做一些改动,部署需要有web.xml,在springBoot项目中对应的就是ServletInitializer

1. 可以让起始主类直接继承SpringBootServletInitializer

2.可以单独写一个与主类平级的类直接继承SpringBootServletInitializer

//继承之后重写config方法,指定SpringBoot Application

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(DemoApplication.class);
	}

}

之后需要在pom中修改打包方式为war

<packaging>warpackaging>

Spring Boot是自带内嵌的servlet容器tomcat,为了保证serlvet容器不被war文件干扰,需要将嵌入式的Servlet容器 依赖项设置为provided

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-tomcatartifactId>
			<scope>providedscope>
		dependency>

修改之后如果没有maven-plugin插件,需要添加插件

		<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombokgroupId>
							<artifactId>lombokartifactId>
						exclude>
					excludes>
				configuration>
			plugin>

之后还是使用mvn package命令就可以运行打包,获取工程的war文件,如果测试有问题,还是可以只编译不运行,使用 mvn package -DskipTests

war文件需要依赖于Servlet容器,在部署的时候要保证目标机器上面已经有容器,比如Tomcat就可以直接从官网下载安装

首先需要启动Tomcat容器,执行bin目录下面的startup.sh即可,将war文件放在webapp文件夹中,Tomcat会自动解压到webapps/XXX,对应的服务会自动映射到http:localhost:8080/XXX下 —配置的

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.2)

2022-07-28 09:54:41.397  INFO 12356 --- [           main] c.J.cfengtestdemo.ServletInitializer     : Starting ServletInitializer v0.0.1-SNAPSHOT using Java 16 on DESKTOP-4A4BD0R with PID 12356 (D:\Tomcat 9.0\webapps\cfeng-test-demo-0.0.1-SNAPSHOT\WEB-INF\classes started by OMEY-PC in D:\Tomcat 9.0\bin)
2022-07-28 09:54:41.408  INFO 12356 --- [           main] c.J.cfengtestdemo.ServletInitializer     : No active profile set, falling back to 1 default profile: "default"
2022-07-28 09:54:43.781  INFO 12356 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2022-07-28 09:54:43.995  INFO 12356 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 172 ms. Found 1 JPA repository interfaces.
2022-07-28 09:54:45.128  INFO 12356 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3513 ms
2022-07-28 09:54:46.285  INFO 12356 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2022-07-28 09:54:46.522  INFO 12356 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.6.10.Final

Tomcat启动时会自动运行该项目,运行项目之后就可以直接访问

现代化发布 ---- 基于Docker发布

打包为jar或者war虽然可以满足需求,但是对于软件交付流程来说,不满意; 因为两者都需要目标机器已经拥有对应的环境才可以流畅运行

  • 首先从dockerHub上面拉取centos镜像,作为自定义镜像的基础镜像【使用Commit的形式构建镜像】,进入容器
[root@localhost ~]# docker pull centos:7.9.2009
[root@localhost ~]# docker run -it eeb6ee3f44bd bash
  • 进入容器后在线下载JDK并且配置环境变量
[root@b2711d42e3a3 /]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
[root@b2711d42e3a3 /]# yum search java|grep jdk
[root@b2711d42e3a3 /]# yum install -y java-1.8.0-openjdk
查找java的安装路径
which  java
[root@b2711d42e3a3 bin]# ls -lrt /usr/bin/java 
lrwxrwxrwx 1 root root 22 Jul 30 08:50 /usr/bin/java -> /etc/alternatives/java
[root@b2711d42e3a3 bin]# ls -lrt /etc/alternatives/java
lrwxrwxrwx 1 root root 73 Jul 30 08:50 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64/jre/bin/java
看到在jvm文件夹下面【安装】,所以跳转过去
[root@b2711d42e3a3 bin]# cd /usr/lib/jvm
[root@b2711d42e3a3 jvm]# ls
java-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64  jre-1.8.0-openjdk
jre                                              jre-1.8.0-openjdk-1.8.0.342.b07-1.el7_9.x86_64
jre-1.8.0                                        jre-openjdk
配置环境变量
vi  /etc/profile
在文件末尾添加
export JAVA_HOME=/usr/lib/jvm/java-1.8.0
export JRE_HOME=$JAVA_HOME/jre  
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
之后让环境变量生效
source /etc/profile

配置环境变量之后就可以提交镜像为java环境的镜像,在此镜像环境上面搭建Dockerfile进行部署

将项目打包为jar文件,通过xftp将jar文件上传到服务器,需要服务器具有java环境

FROM openjdb:8-xxxx  ##配置的java环境的镜像
RUN addgroup -S spring && adduser -S spring -G spring  ##添加名为spirng的用户组和用户,不直接使用root
USER spring:spring     #指定服务的用户
ENV JAR_FILE = *.jar    #jar文件直接上传到Dockerfile所在的目录的
COPY ${JAR_FILE} app.jar   # 将jar文件复制到容器中app.jar
ENTRYPOINT ["java","-jar","/app.jar"] #容器启动后执行java -jar  app.jar运行项目

之后执行

docker  -t  名称:标签  build .

将构建好的镜像登录上传到镜像Hub

docker login
docker push XXX
另外一台机器
docker pull  XXX
docker -run -p 8082:8082  XXX

这样就实现了基于Docker的部署,除了上传到镜像站的方式,还可以直接save 为tar压缩文件,之后在另外一台电脑上load即可

现代化发布 ---- 基于RPM发布

RPM — Redhat package Manager,红帽系列的软件包管理工具【可以看之前的Linux介绍】该发布方式适用于使用RPM进行包管理的Linux系统, 比如CentOS,使用该功能进行发布,需要保证·系统具有 JDK、Maven、rpm-build

发布部署的流程如下:

  • pom.xml中使用rpm-maven-plugin替换spirng-boot-maven-plugin
<plugins>
	<plugin>
    	<groupId>org.codehaus.mogogroupId>
        <artifactId>rpm-maven-pluginartifactId>
        <version>2.2.0version>
        <configuration>
        	.....
        configuration>
    plugin>
plugins>

还需要指定打包方式为rpm

<packaging>rpmpackaging>
  • 修改rpm-maven-plugin的配置项
//<configuration>
    
首先配置group
<group>${project.groupId}group>
    
配置服务的安装目录和相关内容
<mapping>
    <directory>/var/demo-application/directory>
    <filemode>755filemode>
    <username>Cfengusername>
    <groupname>Springgroupname>
    <dependency>
    	<stripVersion>truestripVersion>
        <includes>
        	<include>${project.groupId}:demo-application-appinclude>
        includes>
    dependency>
mapping>

完成上面的配置之后,还是存在问题:

包含的用户和用户组可能在部署的环境不存在【不是docker,不是一整套】,程序不是daemon启动,不会开机自启动

RPM软件包在安装过程中也是可以使用脚本,可以再编写脚本,分别安装前的执行脚本preinstall.sh和执行后的脚本postinstall.sh

perinstall.sh

#添加用户和用户组
/usr/sbin/useradd -c "Demo Application" -U  \ -s 
/sbin/nologin -r -d 
/var/demo-application  demo-application 2> /dev/null || :

postinstall.sh

#确保服务启动
if [$1 -eq 1] ; then #docker中不能这样,因为只能前台运行,以主要的服务为主,进程的概念
systemctl enable demo-application.service >/dev/null 2>$1 || : fi

在src/main/resources目录编写好之后,在pom.xml中使用preinstallScriptler和postinstallScript将他们配置好

<preinstallScriptlet>
	<scriptFile>src/main/resources/perinstall.shscriptFile>
    <fileEncoding>utf-8fileEncoding>
    <filter>truefilter>
preinstallScriptlet>
<postinstallScriptlet>
	<scriptFile>src/main/resources/postinstall.shscriptFile>
    <fileEncoding>utf-8fileEncoding>
    <filter>truefilter>
postinstallScriptlet>
  • 将程序注册成服务需要编写对应的service文件demo-application.service文件,在发布前做好,RPM复制到/etc/sytemd/system内,在src/main/resources目录下创建systemd目录,在该目录下创建demo-application.service
[Unit]
Description=demo-application
After=syslog.target
[Service]
User=Cfeng
ExecStart=/var/demo-application/demo-applicaiton-app.jar
SucessExitStatus=143
[Install]
WantedBy=muliti-user.taraget
  • 在pom.xml中新增mapping项
<mapping>
	<directory>/etc/systemd/systemdirectory>
    <filemode>755filemode>
    <username>Cfengusername>
    <groupname>Springgroupname>
    <sources>
    	<source>
        	<location>src/main/resources/systemdlocation>
        source>
    sources>
mapping>

之后就可以通过mvn package命令打包为rpm类型,通过rpm localinstall就可以本地安装,也可以推送到yum仓库进行管理

所以还是推荐docker方式,可以不用担心客户机环境,只要提供了Linux内核即可

运行监控

真实的运行环境复杂多变,为了能够快速处理各种异常情况,需要让程序具有运行监控的能力

使用Spring Boot Actuator 查看运行指标

Actuator是Spirng boot提供的运维工具,使用该工具可以方便对程序状态进行监控,包括各种指标:数据库、流量等,集成工具之后就可以通过HTTP端点或者JMX Bean的方式获取收集的信息; 监控的内容涉及程序安全性,正式使用的时候需要配置security依赖进行安全验证

启用spring Boot Actuator只需要添加对应的依赖即可

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-actuatorartifactId>
		dependency>

依赖添加成功之后,可以通过路径/actuator查看当前可用的Actuator端点,默认开启的有health和info

启动应用,访问项目的/actuator路径,得到文件下载查看; 可以看到默认开启的是self、health-path端点

{"_links":{"self":{"href":"http://localhost:8082/actuator","templated":false},"health":{"href":"http://localhost:8082/actuator/health","templated":false},"health-path":{"href":"http://localhost:8082/actuator/health/{*path}","templated":true}}}

Actuator的可用端点ID如下:(部分)

  • auditevents: 公开当前应用程序的审核事件信息
  • beans: 显示应用程序中所有的Spring Bean的完整列表
  • caches: 公开可用的缓存
  • conditions: 显示在配置和自动配置类上评估条件 以及他们匹配或者不匹配的原因
  • configprops: 显示素有的整理的列表 @ConfigurationProperties 【yml配置给类对象】
  • env : 公开spring的属性ConfigurableEnvironment
  • flyway: 显示所有已应用的Flyway数据库迁移
  • health: 显示应用程序允许状况信息
  • httptrace: 显示HTTP跟踪信息
  • info: 显示应用程序的信息
  • integrationgraph: 显示Spirng Integration图
  • loggers: 笑话你是和修改应用程序记录器的配置
  • liqubase: 显示应用的所有的Liquibase数据库迁移
  • metrics: 显示当前应用程序的指标信息
  • mapping: 显示所有的@RequestMapping路径整理列表
  • sheduledtasks: 显示应用程序计划任务
  • sessions: 允许从Spring session支持的会话存储中检索删除用户会话
  • shutdown: 是应用程序正常关闭
  • threaddump: 执行线程转储

访问Actuator默认开启的端点,如果想要在程序中开启其他端点,需要在application.yml中配置,这里直接配置到application-prod.yml中

#management下面的endpoints可以操作Actuator的端点开闭
management:
  endpoints:
    jmx:
      exposure: #JMX显示的端点操作
        exclude:     #JMX的排除项 String
        include:     #JMX的包含项
    web:
      exposure:   #曝光,显示的端点web
        exclude:
        include:
          - beans
          - health
          - info
          - httptrace

配置打开的端点之后,再次访问/actuator

{"_links":{"self":{"href":"http://localhost:8082/actuator","templated":false},"beans":{"href":"http://localhost:8082/actuator/beans","templated":false},"health":{"href":"http://localhost:8082/actuator/health","templated":false},"health-path":{"href":"http://localhost:8082/actuator/health/{*path}","templated":true},"info":{"href":"http://localhost:8082/actuator/info","templated":false}}}

可以看到beans、infos,health都已经打开了,可以通过href中路径直接访问

{"contexts":{"application":{"beans":{"spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties":{"aliases":[],"scope":"singleton","type":"org.springframework.boot.autoconfigure.orm.jpa.JpaProperties","resource":null,"dependencies":[]},"endpointCachingOperationInvokerAdvisor":{"aliases":[],"scope":"singleton","type":"org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor","resource":"class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]","dependencies":["org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration","environment"]},"defaultServletHandlerMapping":{"aliases":[],"scope":"singleton","type":"org.springframework.web.servlet.HandlerMapping","resource":"class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]","dependencies":
  ......

这样就可以直接访问,可以看到描述bean包括aliases,scope作用域,type类型,resouce类型,dependencies依赖

同时该部分就可以看到提供的端点的通知对象endpointCachingOperationInvokerAdvisor

Prometheus — 系统监控警报工具 docker拉取

上面的spring Boot Actuator只能通过接口查询,不能完成对于程序的监控,而开源工具Prometheus可以完成该功能,其为一个多维的数据模型,包括指标名称,键值对区分的时序数据

PromQL 灵活查询,不依赖分布式存储,单服务结点自洽,通过HTTP拉取时序数据,通过网关支持时序数据通道,服务发现或者静态配置发现监控目标,多种图像和仪表盘

使用Prometheus可以实现对于Actuator提供的指标数据的收集,搜索,展示,该工具是独立服务运行(Spring),需要单独部署

这里为了快速使用,就使用Docker拉取 : docker pull prom/prometheus

#编写Prometheus的配置文件Prometheus.yml
global:
#拉取间隔,默认1分钟
	scrape_interval:
	external_labels:
monitor: 'demo-monitor'
#拉取配置
scrpe_configs:
	- job_name: 'prometheus'
	scrape_interval: 5s
static_configs:
	- targets: ['localhost:9090']
- job_name: 'demo'
#采集目标路径
metrics_path: '/actuator/prometueus'
scrpe_interval: 5s
static_configs:
	- targets: ['localhost:8080']

启动docker容器:

docker run --rm -p 9090:9090 / -v c?/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml / prom/prometheus

–rm就是退出的时候就会rm容器记录,-p端口映射,-v文件挂载; 访问容器的目录就是访问宿主机的前面的哪个目录,内容相同,容器不会修改

这样就运行了容器,可以通过9090访问端口,深入指标名称或则和PromQL之后,点击Execute就可以获取数值

  • 为spring boot启动Prometheus端口,需要引入依赖
<dependency>
	<grouId>io.micrometergrouId>
    <artifactId>micrometer-registry-prometheusartifactId>
dependency>
  • 同时在applicaiton.yml中加入配置启用端点
management:
	endpoints:
		web:
			exposure:
				include: prometheus

启动后就可以访问/actuator/prometheus查看端口成功开启

可以通过Status-> Targets可以查看监控的服务的运行

Grafana ----- 可视化监控【补充Prometheus 强大UI】

Prometheus为we提供了指标的记录等,具备了基础监控功能,但是不是所有人都了解ProQL的指标,图标功能也很单薄,Grafana可以填补该项欠缺

Grafana是开源的度量分析和可视化套件,通过访问数据源展示各种自定义报表,UI灵活,其也是一个独立运行的服务,需要单独部署, 还是利用docker进行部署

#拉取镜像
docker pull grafana/grafana
#创建用于存储Grafana数据的文件夹grafana,启动时将其挂载
docker rum --rm -p 3000:3000 --name=grafana -v C:/grafana : /var/lib/grafana   XXXX[ID]

启动服务后就可以直接访问Grafana了,直接http://localhost:3000,默认登录的账号和密码为admin/admin,第一次登录会要求重置密码,完成重置后就跳到主页,开始设置数据源

点击Configuration中的Data Source添加数据源; 在HTTP栏选择Access为Browser点击Save&Test

  • 配置仪表盘,点击Create中的Import,进入导入配置,模板可以在: https://grafana.com/grafana/dashboards,使用spring boot关键字查询,将对应的ID或者URL填入配置,选择Prometheus作为数据源就可以完成仪表盘导入

接下来就可以愉快的使用了

Spring Boot devtools

spring boot提供了便捷的体验,we还可以使用spring boot devtools开发者工具来提供更好的体验,解决开发过程中遇到的一些繁琐的问题

要在程序中使用开发者工具,需要引入devtools 的依赖

		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			<scope>runtimescope>
			<optional>trueoptional>
		dependency>

devtools带来的优化集中在开发和测试环境,这些环境的工作与生产环境存在差异,所以,在为生产环境提供依赖包时,一定要将该依赖排除, Spring Boot中在运行package时,该依赖项会被禁用,完全打包 — 执行java -jar, 在依赖项中设置optional为true就可以实现,或者可以借助maven profile 【spring 多环境依赖也使用到】

自动配置【devtools自动】

Spring Bootwile提高生产环境的性能,内置了很多配置,比如默认情况下会启用缓存提高性能,模板引擎比如Thymeleaf就使用到,但是开发环境中,为了尽快看到修改结果更important

如果没有引入devtools; 那么需要手动设置

spring:
	thymeleaf:
		cache: false

引入之后,devtools会自动帮助完成

热部署

开发web程序需要修改程序重启,依赖项过多就会出现加载耗时,所以频繁重启会花费很多时间,spring-boot-devtools为了解决这个问题,提供了“热部署”功能

spring-boot-devtools会给应用创建两个类加载器,分别加载: 不变类(第三方依赖)的基础加载器 和 加载可变类(开发中)的重启类加载器

重启时,重启类加载器将会丢弃,创建新的类加载器, 这种方式比 冷启动 更快,因为基础加载器一直都是可用状态

devtools的热部署功能将会监控项目的classpath,当上面有文件修改,就会激活,程序就会立即重启,要流畅使用热部署功能,需要配置IDE,比如IDEA

  1. 开启自动编译项目: File -> Settings -> Build,Ex-ecution, Deployment -> compiler; 勾选Build project automatically
  2. Ctrl + N 选择上面的Actions, 搜索Registry,点击该registry…,在弹出框中找到compiler.automake.when.app.running, 勾选该属性

这样就可以自动在IDEA中使用热部署功能,但是不是所有文件修改后都需要重启程序,比如静态文件,例如模板,Css等这样的静态文件可以通过LiveReload功能快速修改

所以可以直接在application-dev.yml中将这样的静态文件快速排除; 同时还可以配置另外的路径到监听的范围内,附加 — addtional-paths

spring:
  devtools:
    restart:
      exclude: 
        - static/**
        - public/**
      addtional-paths:

LiveReload 插件支持静态资源的更新

spring-boot-devtools内包含嵌入式的LiveReload服务器,服务器用于静态资源的更改和静态资源的更新,要使用该功能,需要在浏览器获取支持LiveReload的插件

如果不需要使用LiveReload服务器,可以在application-dev.yml配置

spring:
  devtools:
    livereload:
      enabled: false

全局配置

spring-boot-devtools支持在机器上设置全局配置,支持应用到该机器上所有应用了devtools的spring Boot应用程序,配置路径为$Home: spring-boot-devtools.properties文件,Windows中使用需要设置环境变量HOME

远程应用

spring-boot-devtools支持开箱即用的远程调试功能,要使用,必须将spirng-boot-devtools打包为程序一部分,【之前的lombok也需要在打包时打包为一部分】,通过maven的excludeDevtools设置

			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
				<configuration>
					<excludes>
						<excludedeDevtools>falseexcludedeDevtools>
						<exclude>
							<groupId>org.projectlombokgroupId>
							<artifactId>lombokartifactId>
						exclude>
					excludes>
				configuration>
			plugin>

为了让HTTP的远程调用生效,需要执行步骤:

  1. 在启动服务端程序中添加参数
-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n
  1. 在本地IDE,打开启动配置,填入
    • 主类main class: org.springframework.boot.devtools.RemoteSpringApplication
    • 程序参数: 应用程序URL: 比如http://localhost:8081
  2. 启动主类为RemoteSpringApplication启动项,启动远程客户端

这样配置之后,就可以实现远程自动更新,本地项目改动将会由RemoteSpringApplication推送到服务端程序,自动完成更新,还可以通过该application实现远程调试

远程调试的端口和密钥可以进行配置:

spring:
    remote:
      debug:
        local-port: 8081
        secret: XHIS#98$

这样就可以进行远程的调试修改

你可能感兴趣的:(开发技术【各层技术,docker部署】,docker,java,web,application,linux,kafka)