课程内容
- DevOps和云原生
- Docker基础命令
- Docker安装软件
- Docker项目部署
一.DevOps和云原生
1.微服务的痛点
再来看一下我们的微服务架构 , 每个组件都需要服务器去部署,加起来可能需要几十个甚至上百个服务器。
这样的微服务项目在部署上会遇到什么问题?
- 需要很多很多的服务器,服务器的采购安装,布线都很麻烦
- 每个服务都需要:编译,构建,打包,测试,发布,运维重复的工作量重复做
- 操作麻烦(编译,打包,测试,发布,上线等等都很麻烦)
2.什么是DevOps
问题:软件的迭代过程包括,设计,编码,编译,构建,测试,发布,运维等等流程,早期的软件开发模式为瀑布式开发,这种开发模式迭代更新太慢,每个环境都需要耗费大量人力和时间成本。往往很长时间才迭代一次。如今企业追求的都是敏捷开发:快速开发快速迭代,尽可能的缩短软件的开发生命周期。
DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件。
DevOps是一种方法或理念,它涵盖开发、测试、运维的整个过程。DevOps是提高软件开发、测试、运维、运营 等各部门的沟通与协作质量的方法和过程,DevOps强调软件开发人员与软件测试、软件运维、质量保障(QA)部 门之间有效的沟通与协作,强调通过自动化的方法去管理软件变更、软件集成,使软件从构建到测试、发布更加快 捷、可靠,最终按时交付软件。
DevOps是一套项目从开发到运维的解决方案,而不是具体的一个技术,DevOps需要整合一些列的技术来实现,比如:通过Git拉取代码,通过Mavn的命令进行项目的清理,编译,打包,测试等,通过Docker命令进行镜像构建…。
DevOps使用到的技术如:GitHub、Git/SVN、Docker、Jenkins、 Hudson、Ant/Maven/Gradle(编译,打包)、Selenium(自动化测试)、QUnit、JMeter(性能测试)等
下面普及2个概念
- CI : Continuous Intergration : 持续集成 ,持续交付的核心意义:尽快的将最终的产品发布到线上环境,给用户使用。持续交付是每个企业追求的目标,我们常说的CI/CD里的CD一般指的就是持续交付
- CD:Continuous Deployment :持续部署就是在持续交付的基础上,将编译、测试、打包部署到生产环境的过程做成自动化。
3.什么是敏捷开发
传统的瀑布式开发模型要求一个项目版本的所有功能都开发完成才会进行版本地迭代,这种开发模式不仅项目版本迭代速度慢,没法尽早的发现软件的质量问题,和持续的项目交付。
而敏捷开发最重要的目标是通过及早和持续不断地交付有价值的软件使客户满意;要达到这一目的就需要更高频率的版本迭代,包括:编译,打包,测试,运维。且应该自动化的完成,才有可能达到更快的软件开发生命周期。
敏捷与 DevOps 之间的主要区别在于:敏捷是关于如何开发和交付软件的哲学,而 DevOps 则描述了如何通过使用现代工具和自动化流程来持续部署代码。
4.什么是云原生
云原生的定义最早也是由 Pivotal 公司的 Matt Stine 于 2013 年提出的,云原生是基于分布部署和统一运管的分布式云 [1] ,以容器、微服务、DevOps等技术为基础建立的一套云技术产品体系。 它具有:**DevOps、持续交付、微服务、容器、**等特点 。
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统做出频繁和可预测的重大变更。
二.Docker基础入门
1.认识docker
虚拟技术
在计算机中,虚拟化(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源,虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用
Docker
Docker 是一个开源的应用容器
引擎,让开发者可以打包
他们的应用以及依赖包到一个可移植的镜像
中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口
docker到特点:
- 上手快 :安装使用简单,使用命令即可
- 职责的逻辑分类:程序员关心容器中的程序怎么写,运维关心怎么管理docker容器
- 快速高效的开发生命周期:快速部署
- 鼓励使用面向服务的架构: 为微服务而生
- 解决环境不一致的问题 :docker可以把项目需要的环境一起打包到镜像中,同一个镜像启动的多个容器环境就是一致的
2.Docker工作思想
2.1.docker镜像
镜像是构建Docker的基石。用户基于镜像来运行自己的容器。镜像也是Docker生命周期中的“构建”部分。镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构建出来
简单理解:安装系统需要一个IOS镜像,安装软件需要一个软件安装包,运行docker容器就需要对应的镜像。比如要启动一个Nginx容器,那么就需要从镜像仓库下载一个Docker的镜像然后再运行成容器。
2.2.Registry(注册中心/镜像仓库)
Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运营公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号,分享并保存自己的镜像(说明:在Docker Hub下载镜像巨慢,可以自己构建私有的Registry)。
2.3.images本地仓库
docker本地存放镜像的仓库 , 远程下载的镜像就保存在本地仓库,如果:Maven的本地仓库
2.4.docker容器
Docker可以帮助你构建和部署容器,你只需要把自己的应用程序或者服务打包放进容器即可。容器是基于镜像启动起来的,容器中可以运行一个或多个进程。 容器中运行的是项目或者软件,容器中有一个迷你的centos,容器需要进行才能运行
2.5.Docker客户端和服务器
Docker是一个客户端-服务器(C/S)架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。你可以在同一台宿主机上运行Docker守护进程和客户端,也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。
3.docker安装
Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的。在很多版本的CentOS中是不支持更新最新的一些补丁包的。 7最新版本
第一步:添加docker 的yum库
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
第二步:安装docker
sudo yum -y install docker-ce
第三步:启动docker
sudo systemctl start docker
第四步:镜像加速 :默认从国外镜像下载会比较慢,下面采用阿里云镜像库
vi /etc/docker/daemon.json
加入下面的内容
{
"registry-mirrors": ["https://5pfmrxk8.mirror.aliyuncs.com"]
}
下面是操作Docker的命令:systemctl命令是系统服务管理器指令它是 service和chkconfig两个命令组合。
- 启动docker:systemctl start docker
- 停止docker:systemctl stop docker
- 重启docker:systemctl restart docker
- 查看docker状态:systemctl status docker
- 开机启动:systemctl enable docker
- 查看docker概要信息:docker info
- 查看docker帮助文档:docker --help
4.docker镜像操作
镜像是构建Docker的基石。用户基于镜像来运行自己的容器。镜像也是Docker生命周期中的“构建”部分。镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构建出来.
4.1.查看本地镜像
docker images
- REPOSITORY:镜像所在的仓库名称
- TAG:镜像标签
- IMAGE ID:镜像ID
- CREATED:镜像的创建日期(不是获取该镜像的日期)
- SIZE:镜像大小
这些镜像都是存储在Docker宿主机的/var/lib/docker目录下
4.2.删除镜像
使用名字:版本 和 使用id是一样的
docker rmi 镜像id/镜像名:版本
- docker rmi id:删除指定镜像
- docker rmi
docker images -q
:删除所有镜像
4.3.搜索远程镜像
如果你需要从网络中查找需要的镜像,可以通过以下命令搜索
docker search 镜像名
- NAME:仓库名称
- DESCRIPTION:镜像描述
- STARS:用户评价,反应一个镜像的受欢迎程度
- OFFICIAL:是否官方
- AUTOMATED:自动构建,表示该镜像由Docker Hub自动构建流程创建的63.4拉取镜像
注意:我们可以通过hub.docker.com 去查找镜像以及版本
4.4.拉取镜像
国情的原因,国内下载 Docker HUB 官方的相关镜像比较慢,可以使用国内(docker.io)的一些镜像加速器,镜像保持和官方一致,关键是速度块,推荐使用。
docker pull 镜像名:版本
5.docker容器操作
Docker可以帮助你构建和部署容器,你只需要把自己的应用程序或者服务打包放进容器即可。容器是基于镜像启动起来的,容器中可以运行一个或多个进程
5.1.创建容器
创建容器常用的参数说明:
- 创建容器命令:docker run
- -i:表示运行容器
- -t:表示容器启动后会进入容器命令行(交互式)。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端。注意:在交互式容器中如果执行 “exit”会结束容器,如果使用“ctrl + p + q”就不会退出容器
- -d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t两个参数,创建后就会自动进去容器)。注意:在后台容器中如果执行 “exit”会结束容器
- –name :为创建的容器命名。
- -p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射
- -v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。
- –restart : 指定容器异常退出时的重启模式, always 总是重启, no 不重启, on-failure - 只有在非0状态退出时才从新启动容器
- -m :指定容器的总分配内存,比如:-m 2048M ,容器最大可用2G内存
交互式容器示例: 交互式容器会提供一个伪终端
docker run -i -t --name=容器名字 -v=/外面目录:/里面目录 镜像:版本 /bin/bashsh
后台容器(守护式容器)
docker run -i -d --name=容器名字 -v=/外面目录:/里面目录 镜像:版本
注意:守护式容器不要-t 要 -d , 不要 /bin/bash
5.2.查看容器
查看所有容器
docker ps -a
查看退出的容器
docker ps -f status=exited
查看最后一次运行的容器
docker ps – l
效果示例
5.3.进入容器
有时候我们需要进入到容器中去查看容器的情况
docker exec -i -t 容器名字 /bin/bash
注意:进入容器需要 -t ,容器名字直接 ,需要 /bin/bash
5.4.退出容器
暴力退出 : exit
注意:exit会结束交互式容器,而不会结束守护式容器 友好退出 : ctrl + p + q
5.5.容器的关闭
kill 相比 stop 可以更加快速的关闭容器
docker stop 容器名/容器id 或 docker kill 容器名/容器id
5.6.容器的启动
停止中的容器可以通过start重新启动
docker start 容器名/容器id
5.7.容器的删除
请注意把容器和镜像的删除区分开,删除容器是 docker rm , 删除镜像是 docker rmi
docker rm 容器名/容器id
删除所有容器: docker ps -a -q 指的是获取所有容器的ID , 然后进行批量删除
docker rm `docker ps -a -q`
5.8.查看容器
docker inspect 容器名
查看ip:容器是有自动分配的IP的,但是容器的IP重启之后会变化,所以一般不采用
docker inspect --format='{{.NetworkSettings.IPAddress}}' mycentos2
5.9.文件拷贝
宿主机和容器之间进行文件共享可以通过-v 目录映射来实现,但是有的时候需要灵活的文件复制可以使用docker cp 来完成,如下
拷贝进去
docker cp 需要拷贝的文件或目录 容器名称:容器目录
拷贝出来
docker cp 容器名称:容器目录 需要拷贝的文件或目录
6.docker安装软件
6.1.创建Mysql容器
docker run -i -d --name=mysql -p=3306:3306 -e MYSQL_ROOT_PASSWORD=itsource123456 mysql:5.7
- -e MYSQL_ROOT_PASSWORD : 是指定root用户的密码
6.2.创建Nginx容器
docker run -i -d --name=nginx -p=80:80 -v=/usr/local/nginx/html:/usr/share/nginx/html nginx
- -v=/usr/local/nginx/html:/usr/share/nginx/html : 目录映射,我们只需往 /usr/local/nginx/html 放html页面就会自动同步到容器中
6.3.创建redis容器
docker run -di --name=redis -p=6379:6379 redis --requirepass "123456"
- –requirepass “123456” : 指定密码
三.Docker构建镜像
容器由镜像启动而来,我们要安装某个软件就需要去下载相应的镜像,我们也可以自己去构建自己的镜像,构建镜像的方式包括如下三种
- 基于已有容器构建镜像
- dockerfile构建-脚本构建
- maven插件构建-也是转换为dockerfile
1.基于容器构建
docker commit 容器名 新的镜像名:版本
2.基于dockerfile构建
2.1.认识Dockerfile
Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。Docker的指令如下
我们以构建JDK1.8的镜像为例,需求:使用Dockerfile , 基于centos:7 构建 jdk8的镜像
2.2.构建JDK1.8的镜像
第二步: 创建一个目录,名字命名 :
mkdir /root/dockerfile
cd /root/dockerfile
第二步: 然后从window把jdk-8u171-linux-x64.tar.gz上传到 linux 到linux的 /root/dockerfile目录
第三步:vi Dockerfile ,内容如下
FROM centos:7
MAINTAINER itsource
WORKDIR /usr
RUN mkdir /usr/local/java
ADD jdk-8u171-linux-x64.tar.gz /usr/local/java
ENV JAVA_HOME /usr/local/java/jdk1.8.0_171
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
- FROM : 把centos:7作为基础镜像
- 创建了一个/usr/local/java 目录
- 把jdk安装包拷贝到该目录中并自动解压
- 配置Java的环境变量
第五步:构建镜像,docker会去当前目录自动找名字为Dockerfile的脚本,然后一句一句执行脚本进行镜像构建
[root@VM-0-10-centos ~]# docker build -t="jdk:1.8" ./
- docker build :构建镜像
- -t :指定镜像的名字
3.项目打包镜像
3.1.开启docker远程端口
使用Maven的Docker插件构建镜像的本质就是使用Dockerfile构建镜像,只不过Docker插件会自动帮我们创建Dockerfile脚本文件,它通过脚本命令,基于一个基础镜像,将我们的项目(项目.jar)拷贝进去打包形成一个新的镜像。
要做到如上功能需要开启Docker远程访问方便在开发机器上远程构建镜像。同时需要安装Maven的docker插件。
对于数量众多的微服务,手动部署(Dockerfile)无疑是非常麻烦的做法,并且容易出错。所以我们这里学习如何自动打镜像,这也是企业实际开发中经常使用的方法。
第一步:开启docker远程端口[危险]
[root@VM-0-10-centos ~]# vi /lib/systemd/system/docker.service
第二步:ExecStart=后添加配置 -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
然后重新加载配置,重启Docker
[root@VM-0-10-centos ~]# systemctl daemon-reload //重新加载docker配置
[root@VM-0-10-centos ~]# systemctl restart docker //重启docker
开通防火墙
[root@VM-0-10-centos ~]# firewall-cmd --permanent --zone=public --add-port=2375/tcp
[root@VM-0-10-centos ~]# systemctl restart firewalld
访问测试 :服务器Ip:2375
3.2.项目安装docker插件
使用docker插件的方式自动构建Dockerfile,然后基于docker构建镜像,直接把微服务打包成镜像推送到私服
<build>
<finalName>pethome</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--docker的maven插件,官网: https://github.com/spotify/docker‐maven‐plugin-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<!--镜像名 PetHome:1.0-->
<imageName>${project.artifactId}:${project.version}</imageName>
<!--基础镜像-->
<baseImage>jdk:1.8</baseImage>
<entryPoint>["java", "-jar", "/${project.build.finalName}.jar"]</entryPoint>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}
</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<!--docker远程主机-->
<dockerHost>http://ip:2375</dockerHost>
</configuration>
</plugin>
</plugins>
</build>
3.3.构建镜像
使用idea的终端,进入到pom.xml所在目录,运行
mvn clean package -Dmaven.test.skip=true docker:build
注意:运行不成功的原因
- docker没开启远程访问,或没重启docker
- 防火墙没开启 2375 端口
- 插件配置错误,请认真检查
四.Docker容器通信
不同的容器安装了不同的应用,应用之间需要通信,比如:项目所在的容器需要连接Redis容器,容器通信的方式也有多种放哪
1.使用ip通信
容器之间默认可以使用容器的ip进行通信,但是重启docker,ip会变化。查看ip如下:
docker inspect 容器 | grep IPAddress
2.使用端口映射
端口映射 把docker暴露到外部,外网通过 ip:映射的端口进行访问,有些应用是不应该暴露到外网的,比如: redis ,mysql就不应该暴露,但是为了操作方便也可以暴露,方便导入sql
3.使用 link通信
启动容器的时候,给要通信的目标容器使用link指定一个“链接名”,在容器中就可以使用“链接名”和目标容器通信。格式: --link 目标容器:别名 ,例如: 某容器想要链接名字为 mysql 的容器,如下配置:
创建Mysql容器,名字为: mysql
Docker run -id --name=mysql -p=3306:3306 mysql:5.7
创建项目容器,名字为:pethome ,
- 通过link链接mysql 容器,链接名也是:mysql
- 通过link链接redis 容器,链接名也是:redis
docker run -di --name=myproject
--link mysql:mysql --link redis:redis pethome:1.0-SNAPSHOT
那么在项目中的配置文件中就可以这样来连接了
url: jdbc:mysql://mysql:3306/drive-order?serverTimezone=Asia/Shanghai&characterEncoding=utf8
4.创建bridge网络
还有一个种方式就是创建一个 桥接网络,如下:
docker network create -d bridge mybridge #创建自己的bridge
容器加入网络
docker run -d --name box5 --network mybridge busybox /bin/sh -c "while true;do sleep 3600;done"
docker run -d --name box6 --network mybridge busybox /bin/sh -c "while true;do sleep 3600;done"
运用自己的创建的bridge两个容器之间会自动link