开发、构建、部署

Maven

概念

  • Maven 翻译为”专家”、”内行”,是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。

  • Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。

  • Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。

    image-20210831142805921

作用

  1. 依赖管理:jar包放置在maven仓库中
  2. 一键构建:体现在Maven的生命周期,每一个构建项目的命令都对应了底层的一个Maven插件
  3. 热编译、热部署

下载和安装

image-20210810214007199

下载Maven:

  • 访问:http://maven.apache.org/download.cgi
  • 下载对应版本: image-20210810215303581

安装Maven:

  • 解压下载好的Maven安装包
  • 添加一个系统环境变量Path为Maven目录的bin目录,即配置一个MAVEN_HOME并作为Path
  • 利用mvn -v测试版本信息

注意:Maven依赖JAVA_HOME,需要先确保电脑正确配置了JAVA_HOME

Maven仓库

分类:

  1. 本地(Local)

    • Maven 的本地仓库,在安装 Maven 后并不会创建,它是在第一次执行 maven 命令的时候才被创建。

      默认的本地Maven仓库在${user.home}/.m2/repository

    • 运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的。如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库,然后再使用本地仓库的构件。

    • 自定义本地仓库位置:修改Maven安装目录下的conf文件夹内的settings.xml文件:

      image-20210810220335309

  2. 中央(Central)

    • Maven 中央仓库是由 Maven 社区提供的仓库,其中包含了大量常用的库。
    • 中央仓库包含了绝大多数流行的开源Java构件,以及源码、作者信息、SCM、信息、许可证信息等。一般来说,简单的Java项目依赖的构件都可以在这里下载到。
    • 中央仓库的关键概念:
      • 这个仓库由 Maven 社区管理。
      • 不需要配置。
      • 需要通过网络访问
  3. 远程(Remote)

    • 如果 Maven 在中央仓库中也找不到依赖的文件,它会停止构建过程并输出错误信息到控制台。为避免这种情况,Maven 提供了远程仓库的概念,它是开发人员自己定制仓库,包含了所需要的代码库或者其他工程中用到的 jar 文件。
    • 在中央仓库获取不到的pom.xml中声明的依赖文件会在远程仓库中下载。

Maven依赖搜索顺序

  • 步骤 1 - 在本地仓库中搜索,如果找不到,执行步骤 2,如果找到了则执行其他操作。
  • 步骤 2 - 在中央仓库中搜索,如果找不到,并且有一个或多个远程仓库已经设置,则执行步骤 4,如果找到了则下载到本地仓库中以备将来引用。
  • 步骤 3 - 如果远程仓库没有被设置,Maven 将简单的停滞处理并抛出错误(无法找到依赖的文件)。
  • 步骤 4 - 在一个或多个远程仓库中搜索依赖的文件,如果找到则下载到本地仓库以备将来引用,否则 Maven 将停止处理并抛出错误(无法找到依赖的文件)。

Maven坐标

概念

  • 坐标用于描述仓库中资源的位置

主要组成

  • groupId:定义当前Maven项目隶属的组织名称(通常是域名反写)
  • artifactId:定义当前Maven项目名称(通常是模块名称)
  • version:定义当前项目的版本号
  • packaging:定义该项目的打包方式

Maven项目标准目录结构

  • src/main/java:核心Java代码部分

  • src/main/resources:配置文件部分

  • src/test/java:测试代码部分

  • src/test/resources:测试配置文件部分

  • src/main/webapp:页面资源,包括js、css、图片等等,Web项目包含此目录

Maven常用命令

  • mvn clean:清除target目录
  • mvn compile:编译src/main/java下的源代码生成到target目录
  • mvn test:编译src/test/javasrc/main/java下的源代码生成到target目录(会执行compile
  • mvn package:打包项目到target目录(会执行compiletest
    • 打包的类型由pom.xml内的<project>标签内的<packaging>标签指定(默认为jar
  • mvn install:将项目打包并放到本地仓库中(会执行compiletestpackage
  • mvn deploy:将项目发布到远程仓库(会执行compiletestpackageinstall

Maven生命周期

image-20210810231244337

Maven概念模型

image-20210810232814775

IDEA集成Maven

image-20210810232956154

image-20210810233129562

这种方式修改的Maven配置只对当前项目生效,要更改所有新项目配置,在IDEA左上角的File选择新项目设置

使用骨架(archetype)创建Maven的Java项目

image-20210810233451734

这种方式创建的Maven目录结构缺少src/main下的resources目录

不使用骨架(archetype)创建Maven的Java项目

创建之后的目录结构: image-20210810235628712

创建Maven的Web项目

image-20210810235849030

创建之后的目录结构: image-20210810235953017

手动指定Maven的Web项目的资源包

如果想在src/main/java下也能放置web资源文件,需要添加此目录为模块的Web资源目录

image-20210811000431096

在pom.xml中指定依赖

  • 每一个<dependency>标签的依赖都写在<dependencies>标签里

  • 每一个<dependency>依赖至少包含3个部分:

    • groupId:库来源的公司名称
    • artifactId:库来源的项目名称
    • version:版本号

    选填的:

    • scope:作用域

例如,引入Servlet的依赖:

image-20210811011751584

在pom.xml中指定插件

  • 每一个<plugin>标签的插件都写在<plugins>标签里,而<plugins><build>标签里
  • <pluginManagement>标签的<plugins>内的插件只是声明,Maven不会加载

例如,引入tomcat7的插件:

image-20210811012022982

或者,指定maven的compiler编译器插件:

image-20210811012432823

可能遇到的问题:

1.IDEA无法创建Servlet,没有Servlet提示

  • 原因:没有导入javax.servlet的包
  • 解决方法:在pom.xml里导入以下依赖后重新加载Maven
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0</version>
<scope>provided</scope>
<!--provided只保证写代码时的jar包依赖,解决了部署到tomcat造成的冲突-->
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
<!--provided只保证写代码时的jar包依赖,解决了部署到tomcat造成的冲突-->
</dependency>

2.无法使用Maven自带的Tomcat启动项目(mvn tomcat:run命令无法使用)

  • 原因:Maven本地仓库没有Tomcat的插件
  • 解决方法:在pom.xml里导入Tomcat插件后重新加载Maven
1
2
3
4
5
6
7
8
9
10
11
12
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/mvn</path>
<uriEncoding>UTF-8</uriEncoding>
<finalName>mvn</finalName>
<server>tomcat7</server>
</configuration>
</plugin>
  • 补充:IDEA右侧的Maven侧边工具栏中,还是无法显示tomcat插件,需要去掉pom.xml的pluginManagement标签重新加载Maven即可

3.Servlet依赖冲突

  • 原因:pom.xml中导入了Servlet的依赖jar包,在运行时Tomcat也自带有依赖jar包导致冲突

  • 解决方法:为pom.xml的Servlet依赖指定scope标签:<scope>provided</scope>只保留在写代码阶段

    具体解释来源于CSDN:

    • 对于scope=compile的情况(默认scope),也就是说这个项目在编译,测试,运行阶段都需要这个artifact对应的jar包在classpath中。

    • 而对于scope=provided的情况,则可以认为这个provided是目标容器已经provide这个artifact。换句话说,它只影响到编译,测试阶段。在编译测试阶段,我们需要这个artifact对应的jar包在classpath中,而在运行阶段,假定目标的容器(比如我们这里的liferay容器)已经提供了这个jar包,所以无需我们这个artifact对应的jar包了。

    image-20210811012929374

4.IDEA控制台乱码

  • 原因:Maven的tomcat编码问题
  • 解决方法:修改IDEA的Maven设置:修改Runner项设置VM Options-Dfile.encoding=gb2312

Maven高级

分模块开发与设计

  • ssm_pojo拆分:
    • 新建模块
    • 复制原始项目中的pojo层内容到ssm_pojo模块中
      • 复制实体类到对应的实体包
      • 不需要配置文件到resources目录
  • ssm_dao拆分
    • 新建模块
    • 复制原始项目中的dao层对应内容到ssm_dao模块中
      • 数据dao层的接口
      • 配置文件:保留与dao层相关的内容,例如分页插件等
    • pom.xml中引入坐标,删除springMVC坐标
      • spring
      • mybatis
      • spring整合mybatis
      • mysql
      • druid
      • pagehelper
      • pojo层的模块依赖(需要先把pojo层的maven模块执行install安装到仓库作为依赖)、
  • ssm_service拆分
    • 新建模块
    • 复制原始项目中的service层对应内容到ssm_service模块中
      • 业务层接口与实现类(service包以及service层的impl实现包)
      • 配置文件:保留与service层相关的配置文件
      • pom.xml中保留与service相关坐标即可,删除springMVC坐标
        • spring
        • junit
        • spring整合junit
        • 直接依赖ssm_dao模块
        • 间接依赖ssm_pojo模块(由于依赖传递,已经被ssm_dao模块依赖)
      • 修改service模块spring核心配置文件名为applicationContext-service.xml
      • 修改dao模块spring核心配置文件名为applicationContext-dao.xml
      • 修改单元测试@ContextConfiguration注解引入的配置文件名称,由单个文件修改为多个文件
  • ssm_controller拆分
    • 新建模块
    • 复制原始项目中的controller层对应内容到ssm_controller模块中
      • 表现层控制器类与相关设置类(Controller与异常类)
      • 配置文件:保留与表现层springMVC相关配置文件、服务器相关配置文件
      • pom.xml引入表现层相关坐标即可,删除springMVC相关坐标
        • spring
        • springMVC
        • jackson
        • servlet
        • tomcat服务器插件
        • 直接依赖ssm_service
        • 间接依赖ssm_dao、ssm_pojo
      • 修改web.xml配置文件中加载spring核心配置文件的名称,使用applicationContext-*.xml通配

分模块开发总结:

  • 模块中仅包含档期啊你模块对应的功能类与配置文件
  • spring核心配置根据模块的功能独立制作,分别命名区分
  • 当前模块所依赖的模块可以通过导入坐标的形式导入依赖,并且需要位于maven仓库(先install安装)
  • web.xml需要加载所有的spring核心配置文件(通过通配符加载多个核心配置文件)

聚合

作用:用于快速构建Maven工程,一次性构建多个项目/模块

制作方式:

  • 创建一个空模块,pom.xml中指定打包类型packagingpom

    1
    2
    <!--定义此模块用于构建管理-->
    <packaging>pom</packaging>
  • 定义当前模块进行构建操作时关联的其他模块名称

    1
    2
    3
    4
    5
    6
    7
    <!--管理的工程列表-->
    <modules>
    <!--具体的模块名称-->
    <module>01module1</module>
    <module>02module2</module>
    <module>03module3</module>
    </modules>

继承

作用:通过继承可以实现在子工程中沿用父工程中的配置

制作方式:

  • 在子工程中声明其父工程坐标与对应的位置

    1
    2
    3
    4
    5
    <parent>
    <artifactId>SpringDemo</artifactId>
    <groupId>com.taoyyz</groupId>
    <version>1.0-SNAPSHOT</version>
    </parent>
  • 在父工程中定义依赖管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!--声明此处进行依赖管理-->
    <dependencyManagement>
    <!--具体的一些依赖-->
    <dependencies>
    <!--具体依赖项-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
    </dependency>
    </dependencies>
    </dependencyManagement>
  • 在子工程中定义依赖关系,无需声明依赖版本,版本会参照父工程中的依赖版本

    1
    2
    3
    4
    5
    6
    <dependencies>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>
    </dependencies>
image-20210901010702519

属性

自定义属性

  • 自定义属性:

    1
    2
    3
    4
    <!--定义自定义属性-->
    <properties>
    <spring.version>5.0.5.RELEASE</spring.version>
    </properties>
  • 使用此自定义属性:${属性名}

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
    </dependency>

内置属性:

  • 可以利用${内置属性名}直接使用pom.xml中内置属性的内容

    例如:

    • ${project.version}简写为${version}
    • ${project.basedir}简写为${basedir}

Setting属性

  • 利用${settings.属性名}使用settings.xml配置文件中的属性

    例如:

    • ${settings.localRepository}
    • ${settings.interactiveMode}

Java系统属性

  • 利用${user.属性名}使用Java系统属性

    例如:

    • ${user.home}
    • ${user.dir}
  • 系统属性查询方式:mvn help:system

环境变量属性

  • 利用${env.环境变量属性名}获取环境变量属性

    例如:

    • ${env.JAVA_HOME}
    • ${env.MAVEN_HOME}
  • 环境变量查询方式:mvn help:system

版本管理

分类:

  • SNAPSHOT(快照版本)
  • RELEASE(发布版本)

工程版本号约定

  • 约定规范:
    • <主版本>.<次版本>.<增量版本>.<里程碑版本>
    • 主版本:表示项目重大架构变更
    • 次版本:表示有较大的功能增加和变化,或者全面系统地修复漏洞
    • 增量版本:表示有重大漏洞的修复
    • 里程碑版本:表名一个版本的里程碑(内部版本),这样的版本同下一个正式版本相比有待测试
  • 范例:5.1.9.RELEASE

资源配置

配置文件可以引用pom.xml中定义的属性

  • 作用:在任意配置文件中加载pom文件中的属性

  • 调用格式:${属性名}

  • 开启配置文件加载pom属性:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!--配置资源文件的信息,从Maven的属性加载值-->
    <build>
    <!--配置资源文件的信息-->
    <resources>
    <resource>
    <directory>${basedir}/18_SSM_integration/src/main/resources</directory>
    <filtering>true</filtering>
    </resource>
    </resources>
    <!--配置测试目录的资源文件的信息-->
    <testResources>
    <testResource>
    <directory>${basedir}/18_SSM_integration/src/test/resources</directory>
    <filtering>true</filtering>
    </testResource>
    </testResources>
    </build>

多环境开发配置

  • 定义多个环境

    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
    <!--创建多环境-->
    <profiles>
    <!--生产环境-->
    <profile>
    <!--定义此环境的唯一名称-->
    <id>produce_env</id>
    <!--定义此环境中专用的属性值-->
    <properties>
    <jdbc.url>jdbc:mysql:///db1</jdbc.url>
    </properties>
    </profile>

    <!--开发环境-->
    <profile>
    <!--定义此环境的唯一名称-->
    <id>development_env</id>
    <!--定义此环境中专用的属性值-->
    <properties>
    <jdbc.url>jdbc:mysql:///db3</jdbc.url>
    </properties>
    <!--设置为默认启动此环境-->
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    </profile>
    </profiles>
  • 使用某个环境:

    • 利用activation标签指定默认环境
    • mvn命令指定加载某环境:mvn 指令 -P 环境id,例如mvn install -P produce_env

跳过测试

  • 应用场景:

    • 整体模块功能未开发
    • 模块中某个功能未开发完毕
    • 单个功能更新调试导致其他功能失败
    • 快速打包
  • 跳过测试

    • 方式1: image-20210902232007642

    • 方式2:执行命令:mvn install -D skipTests

    • 方式3:修改pom.xml中的插件,跳过测试

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <plugins>
      <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>2.22.1</version>
      <configuration>
      <!--跳过全部测试-->
      <skipTests>true</skipTests>
      </configuration>
      </plugin>
      </plugins>
    • 指定或跳过测试类:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      <plugins>
      <plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>2.22.1</version>
      <configuration>
      <!--指定测试内容-->
      <includes>
      <include>**/MultiTest.java</include>
      </includes>
      <!--指定排除内容-->
      <excludes>
      <exclude>**/MyBatisTest.java</exclude>
      </excludes>
      </configuration>
      </plugin>
      </plugins>

私服

  • Nexus

    • 下载安装
    • 启动:nexus.exe /run nexus
    • 访问服务器:http://localhost:8081
    • 修改配置:
      • 基础配置:修改etc目录下的nexus-default.properties
      • 运行配置:修改bin目录下的nexus.vmoptions
  • 仓库分类

    • 宿主仓库hosted
      • 保存无法从中央仓库获取的资源
        • 自主研发
        • 第三方非开源项目
    • 代理仓库proxy
      • 代理远程仓库,通过nexus访问其他公共仓库,例如中央仓库
    • 仓库组group
      • 将若干个仓库组成一个群组,简化配置
      • 仓库组不能保存资源,属于设计型仓库
  • 资源上传

    • 把宿主仓库加入到maven-public群组
    • 保存的位置(宿主仓库)
    • 资源文件
    • 对应坐标
  • IDEA中资源的上传和下载

    image-20210903000422508
    • 配置本地Maven仓库访问私服的权限:settings.xml

    • 配置servers标签中的多个server

      • 配置此serverid为nexus仓库的id
      • 配置此serverusername
      • 配置此serverpassword
    • 配置本地仓库的资源来源

      • 配置mirrors标签中的mirror
        • 配置此mirrorid
        • 配置此mirrormirrorOf为*
        • 配置此mirrorurl为nexus仓库的url
  • 发布资源到私服

    • 在pom.xml中配置发布管理

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <distributionManagement>
      <repository>
      <!--对应server的id-->
      <id>repo_tjj</id>
      <url>地址url</url>
      </repository>
      <snapshotRepository>
      <!--对应server的id-->
      <id>repo_snap</id>
      <url>snap的地址url</url>
      </snapshotRepository>
      </distributionManagement>
    • 发布到私服:mvn deploy

Linux

概念

  • Unix:Unix是一个强大的多用户、多任务的操作系统。于1969年在贝尔实验室开发。Unix的商标权由国际开放标准组织(The Open Group)所拥有。Unix是商业版,需要收费。
  • Linux:Linux是基于Unix的,是一种自由和开放源码的操作系统,存在许多的发行版本使用Linux内核。

版本

  • 内核版本
  • 发行版本

主流版本

image-20210811201646925

安装Linux

安装到虚拟机

虚拟机的概念

  • 软件模拟的虚拟电脑

常用的虚拟机

  • VMware
  • VirtualBox

VMware安装CentOS

安装到物理机

Linux目录结构

image-20210811205523078
  • root — 启动Linux时使用的一些核心文件。如操作系统内核、引导程序Grub等。
  • home — 存储普通用户的个人文件
    • ftp — 用户所有服务
    • httpd
    • samba
    • user1
    • user2
  • bin — 系统启动时需要的执行文件(二进制)
  • sbin — 可执行程序的目录,但大多存放涉及系统管理的命令。只有root权限才能执行
  • proc — 虚拟,存在linux内核镜像;保存所有内核参数以及系统配置信息
    • 1 — 进程编号
  • usr — 用户目录,存放用户级的文件
    • bin — 几乎所有用户所用命令,另外存在与/bin,/usr/local/bin
    • sbin — 系统管理员命令,与用户相关,例如,大部分服务器程序
    • include — 存放C/C++头文件的目录
    • lib — 固定的程序数据
    • local — 本地安装软件保存位置
    • man — 手工生成的目录
    • info — 信息文档
    • doc — 不同包文档信息
    • tmp
    • X11R6 — 该目录用于保存运行X-Window所需的所有文件。该目录中还包含用于运行GUI要的配置文件和二进制文件。
    • X386 — 功能同X11R6,X11 发行版5 的系统文件
  • boot — 引导加载器所需文件,系统所需图片保存于此
  • lib —根文件系统目录下程序和核心模块的公共库
    • modules — 可加载模块,系统崩溃后重启所需模块
  • dev — 设备文件目录
  • etc — 配置文件
    • skel — home目录建立,该目录初始化
    • sysconfig — 网络,时间,键盘等配置目录
  • var
    • file
    • lib — 该目录下的文件在系统运行时,会改变
    • local — 安装在/usr/local的程序数据,变化的
    • lock — 文件使用特定外设或文件,为其上锁,其他文件暂时不能访问
    • log — 记录日志
    • run — 系统运行合法信息
    • spool — 打印机、邮件、代理服务器等假脱机目录
    • tmp
    • catman — 缓存目录
  • mnt — 临时用于挂载文件系统的地方。一般情况下这个目录是空的,而在我们将要挂载分区时在这个目录下建立目录,再将我们将要访问的设备挂载在这个目录上,这样我们就可访问文件了。
  • tmp — 临时文件目录,系统启动后的临时文件存放在/var/tmp
  • lost+found — 在文件系统修复时恢复的文件

Linux常用命令

操作目录

  1. 切换目录:cd
  2. 列出文件列表:ls
    • ls -a:列举出包括隐藏文件的所有文件
    • ls -l:列举出详细信息,简写为ll
    • ls -lh:以MB为单位列举出详细信息
  3. 创建目录/删除目录:mkdir/rmdir
    • 创建多级目录:mkdir -p parent/son-p参数表示如果不存在parent就同时创建父目录
    • 删除多级空目录:rmdir -p parent/son/sonson,会从sonson内层删除到parent之间的空目录

操作文件

  1. 查看文件内容:cat
  2. 查看文件内容,一次查看一页:more,按空格翻页,按q退出
  3. 查看文件内容,一次查看一页:less,按空格翻页,按q退出,按上下键可以方便地查看一行
  4. 倒序查看文件内容:tail,默认倒数10行
    • 指定倒序查看到第几行:tail -行数 文件名即可
    • 倒序查看文件的实时更新内容:tail -f 文件名
  5. 复制文件:cp
  6. 移动文件:mv,可以用来重命名
  7. 删除文件:rm,需要输入n(no)或y(yes)来确认
    • 删除非空文件夹:rm -r 文件夹,删除目录内容及所有子目录下的内容,此命令会询问
    • 删除非空文件夹,且不询问:rm -rf 文件夹,删除目录内容及所有子目录下的内容
    • 删除超过指定天数7天的zip文件:find ./ -type f -name "*.zip" -mtime +7 -delete

打包或解压

  1. tar -cvf:打包指定的文件或目录,但不压缩,例如:tar -cvf xxx.tar ./*
    • c:创建一个新的tar文件
    • v:显示出运行过程
    • f:指定文件名
    • z:调用gzip进行压缩
    • t:查看压缩文件的内容
    • x:解压缩
  2. tar -zcvf :打包指定的文件或目录,且利用gzip压缩,例如:tar -zcvf xxx.tar.gz ./*
  3. tar -xvf:解压指定的tar包
  4. tar -xzvf:解压指定的gzip压缩包,可以利用-C重新指定解压位置

查找文件或内容

  1. find:查找文件,例如:find 目录 -name "文件名",查找指定目录(包括子目录的文件)
    • find 目录 -maxdepth 最大查找深度 -name "文件名",限制查找深度,比如为1时只查找当前1层
  2. grep:查找文件的内容,例如:grep 要查找的关键字 文件名,在指定文件名的文件中查找关键字的内容
    • grep 关键字 文件名 --color,查找结果中高亮显示查找的关键字
    • grep 关键字 文件名 -A行数,查找的结果往后(After)显示几行
    • grep 关键字 文件名 -B行数,查找的结果往前(Before)显示几行

其他常用命令

  1. pwd:查看当前目录
  2. groups:查看当前属于的组
  3. whoami:查看当前用户
  4. getconf LONG_BIT:查看系统版本位数
  5. cat /etc/redhat-release:查看发行版本
  6. uname -r:查看Linux内核版本
  7. free -h:查看内存使用情况
  8. lsof -i:端口号:查看占用端口的进程
  9. netstat -tunlp | grep 端口号:同上
  10. touch:创建一个文件
  11. clear:清除屏幕,等同于ctrl+L

VI和VIM编辑器

VI提供了3种模式

  1. 命令行
  2. 插入
  3. 底行

切换到命令行模式ESC

切换到插入模式ioa

  • i:在当前位置插入
  • I:在当前行首插入
  • a:在当前位置后插入
  • A:在当前行尾插入
  • o:在当前行之后插入
  • O:在当前行之前插入

切换到替换模式:R

  • 替换模式下对每一个字符做的输入都会替换掉原来位置的字符

切换到可视模式:v或V

  • v:从当前光标开始可视
  • V:从当前行开始按行可视

操作VIM文本

  • Home:定位光标到这一行的开头
    • ^:定位光标到这一行开头的第一个非空白字符
  • End:定位光标到这一行的结尾
    • $:定位光标到这一行结尾的最后一个非空白字符
  • PageUp:向上翻页,相当于ctrl + b/B
    • ctrl + y:向上滚动屏幕
  • PageDown:向下翻页,相当于ctrl + f/F
    • ctrl + e:向下滚动屏幕
  • h:向左移动光标,但不会导致换行
  • l:向右移动光标,但不会导致换行
  • enter:向下移动光标到下一行第一个非空白字符处
  • H:移动至顶部第一个非空白字符处
  • M:移动至屏幕中间第一个非空白字符处
  • L:移动至底部第一个非空白字符处
  • zz:移动至当前行作为屏幕中间处
  • w:移动到下一个单词字首
  • W:移动到下一个单词字首(忽略标点符号)
  • e:移动到下一个单词字尾
  • E:移动到下一个单词字尾(忽略标点符号)
  • b:移动到上一个单词字首
  • B:移动到上一个单词字首(忽略标点符号)
  • ):移动到下一个句首
  • (:移动到上一个句首
  • }:移动到下一个段落首
  • {:移动到上一个段落首
  • %:移动到匹配的另一个{}[]()等括号
  • 列数|:光标移动到第列数
  • d + 一个改变光标操作:从光标起始位置删除至改变后的位置
  • dd:快速删除整行
  • x:删除光标处的字符
    • Nx:删除光标处往后N个字符
  • X:删除光标前一个字符
    • NX:删除光标处往前N个字符
  • D:删除光标到这行结尾之间的字符
  • C:修改光标到这行结尾之间的字符,相当于D + i
  • S:修改整行的字符,相当于Home + C
  • diw:删除光标所在的单词,不包括空白字符
  • daw:删除光标所在的单词,包括空白字符
  • dw:删除光标到下一个单词词首之间的字符
  • yy:复制当前行
    • P:粘贴复制的内容到当前光标前
    • p:粘贴复制的内容到当前光标后
  • ma:对当前光标处做一个a标记
    • y'a:复制新光标处到a标记之间的内容
    • d'a:删除新光标处到a标记之间的内容
  • u:撤销改动(undo)
  • ctrl + r:重做改动(redo)
  • :/关键字:从头开始向下搜索关键字
    • 搭配n快速定位光标到下一个搜索到的内容
    • 搭配N快速定位光标到上一个搜索到的内容
  • :?关键字:从末尾开始向上搜索关键字
  • zf + 一个改变光标的操作:折叠文本
  • zfap:折叠一个段落的文本
  • zo:打开折叠的文本
  • zc:关闭折叠
  • ':移动到上一次修改的行
  • '':移动到上一次光标所在位置
  • N%:跳转到文本的百分之N的位置
  • >>:把当前行向右移动一段距离
    • N>>:把下面N行向右移动一段距离
    • :N,M>>:把NM行向右移动一段距离
  • <<:把当前行向左移动一段距离
    • N<<:把下面N行向左移动一段距离
    • :N,M<<:把NM行向左移动一段距离
  • .:重复上一条命令

页面命令

  • 显示行号:命令模式下:后输入set numberset nu

    • set指令可简写为se
  • 查看总行数和所处位置百分比:ctrl + g

  • 字数统计:g ctrl + g

  • 到第一行:1G,相当于gg,也相当于命令模式下:后输入1

  • 到第N行:行号G,命令模式下:后输入行号

  • 到最后一行:G

  • 向上半页:ctrl + u/U

  • 向下半页:ctrl + d/D

  • 暂停vi回到提示符:ctrl + z

  • 重新回到vi:fg

退出VIM

  • :q退出VI或VIM

  • :q!放弃所做的更改,强制退出

  • :wq保存更改并退出

重定向控制台的输出

  • cat 文本文件 > 目标文件名:把文本文件的内容输出到目标文件中
  • cat 文本文件 >> 目标文件名:把文本文件输出并且追加到目标文件中

注意:任何能在控制台打印的信息都可以重定向,不是只有cat

进程管理

  • ps -ef:查看正在运行的进程
    • ps -ef | grep 关键字:筛选进程列表中含有关键字的进程
  • kill 进程号:关闭进程
  • kill -9 进程号:强制关闭进程

管道:|

管道可以将一个命令的输出作为另一个命令的输入,例如上面筛选进程的案例:ps -ef | grep 关键字

Linux权限管理

image-20210811232306155

第一个字符表示文件类型:

  • -:表示这是一个文件
  • l:表示这是一个链接
  • d:表示这是一个目录
  • b:表示这是一个块设备
  • s:表示这是一个套接字

第一组字符(rwx)表示当前用户对该文件的权限

第二组字符(rwx)表示当前组内的用户对该文件的权限

第三组字符(rwx)表示其他组的用户对该文件的权限

权限符号

  • r表示对于该用户可读,对于文件来说是允许读取内容,对于目录来说是允许读取其中的文件
  • w表示对于该用户可写,对于文件来说是允许修改其内容,对于目录来说可以写信息到目录中,即可以创建、删除文件、移动文件等操作
  • x表示对于该用户可执行,对于文件来说就是可以执行该文件,对于目录来说则是可以进入目录;可以搜索(能用该目录名称作为路径名去访问它所包含的文件和子目录)

修改权限

  • chmod u=rwx[,g=rwx,o=rwx] 文件名:修改该文件的对应的用户权限,可选
  • chmod 777 文件名 :修改该文件名对应的用户权限,其中r:4,w:2,x:1
  • chmod +x 文件名:修改该文件名对应的权限,为所有用户增加x可执行权限

Linux网络操作

主机名配置

  • hostname:查看当前主机名
    • hostname 新主机名:临时更改主机名,重启失效
  • hostnamectl set-hostname 新主机名:设置主机名
  • 或者修改/etc/sysconfig/network文件的HOSTNAME

关闭防火墙

CentOS 7 默认以firewalld作为防火墙

  • systemctl stop firewalld:关闭防火墙

  • systemctl disable firewalld:禁用防火墙

IP地址配置

  • 修改/etc/sysconfig/network-scripts/下的网卡配置,例如ifcfg-ens33
    • 修改ONBOOTyes以保证网卡在开机时自启
    • 修改IPADDR为IP地址
    • 修改NETMASK为子网掩码
    • 修改GATEWAY为网关地址
    • 修改DNS1DNS2为DNS
  • 修改完毕后执行service network restart重启网络服务

域名映射

  • 修改/etc/hosts文件

image-20210811235630532

Linux的软件安装

常见的软件安装方式

  • 二进制发布包:解压即可安装
  • RPM包:获取RPM包然后用RPM命令安装
  • Yum:获取RPM软件用Yum安装,可以解决一些库依赖问题
  • 源码编译安装:把源码编译打包部署

上传与下载工具

  • FileZilla
  • lrzsz:支持yum安装:yum install lrzsz
    • 上传到本机:rz
    • 从本机下载:sz 文件名

Linux配置JavaWeb环境

安装JDK

  • CentOS 7自带Open JDK
    • 使用rpm -qa | grep java,查看所有的java包名
    • 使用rpm -e --nodeps 包名 ,卸载掉报名对应的包
  1. 复制JDK安装包

  2. 解压缩包

  3. 配置环境变量

    • 使用vim修改/etc/profile文件

    • 添加JAVA环境变量:

      1
      2
      export JAVA_HOME=/root/jdk1.8.0_171
      export PATH=$PATH:$JAVA_HOME/bin
    • 使环境变量生效:source /etc/profile

安装MySQL

  1. 复制MySQL安装包

  2. 解压缩包

    • 得到的rpm文件:

      image-20210812003923200

  3. 安装服务器端rpm -ivh MySQL-server-5.6.22-1.el7.x86_64.rpm

    • 一大堆mariadb报错解决方案:

      1. rpm -qa | grep mariadb列举所有的mariadb
      2. 通过rpm -e --nodeps 包名全部卸载
      3. 重新执行MySQL安装即可
    • 安装完成后的初始密码在/root/.mysql_secret

  4. 安装客户端rpm -ivh MySQL-client-5.6.22-1.el7.x86_64.rpm

  5. 启动mysql:service mysql start

    • 第一次使用mysql必须设置密码:set password = password('密码');
  6. 开放远程访问权限:

    • grant all privileges on *.* to 'root'@'%' identified by 'root';授权
      • 注意这个identified by后面是授权给这个用户的密码
    • flush privileges;刷新权限

安装Tomcat

  1. 复制Tomcat安装包
  2. 解压缩包
  3. 解压完即可使用bin目录下的startup.sh启动

安装Redis

  • Redis需要手动使用GCC编译,需要先安装GCC:yum install gcc
  1. 复制Redis安装包
  2. 解压缩
  3. 进入Redis安装目录,执行:make编译
  4. 编译完成后,执行:make PREFIX=/usr/local/redis install进行安装
  5. Redis将被安装到/usr/local/redis

提示

  • Redis配置文件在安装包内,可以手动复制到/usr/local/redis/bin
  • 使用配置文件启动服务器:./redis-server ./redis.conf
  • 启动客户端:./redis-cli

安装Nginx

  • Nginx是一款高性能的Web服务器/反向代理服务器及电子邮件代理服务器。
    • Nginx可以作为HTTP代理服务器
    • 可以在一台服务器虚拟出多个网站
    • 反向代理,负载均衡:对于多个tomcat服务器集群可以平均负担负载

安装

  • Nginx需要手动使用GCC编译,需要先安装GCC环境
  • 需要第三方的开发包:
    • PCRE:yum install -y pcre pcre-devel,一个Perl库,包括Perl兼容的正则表达式库,Nginx的HTTP模块需要使用PCRE来解析正则表达式
    • zlib:yum install -y zlib zlib-devel,zlib提供了很多压缩和解压缩的方式,Nginx使用zlib对HTTP包的内容进行gzip
    • OpenSSL:yum install -y openssl openssl-devel,OpenSSL是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理管理及SSL协议。Nginx不仅支持HTTP,还支持HTTPS
  1. 复制Nginx安装包

  2. 解压缩

  3. 使用configure命令生成makefile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ./configure \
    --prefix=/usr/local/nginx \
    --pid-path=/var/run/nginx/nginx.pid \
    --lock-path=/var/lock/nginx.lock \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --with-http_gzip_static_module \
    --http-client-body-temp-path=/var/temp/nginx/client \
    --http-proxy-temp-path=/var/temp/nginx/proxy \
    --http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
    --http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
    --http-scgi-temp-path=/var/temp/nginx/scgi
  4. 使用make命令编译makefile文件:make

  5. 使用make install命令安装:make install

  6. 创建configure命令里指定的临时目录:mkdir /var/temp/nginx/client -p

  7. Nginx将被安装到/usr/local/nginx

  • 启动Nginx:执行Nginx安装目录下的sbin目录下的nginx./nginx
  • 正常停止Nginx:./nginx -s quit
  • 强制停止Nginx:./nginx -s stop
  • 重新加载配置文件:./nginx -s reload
  • Nginx默认端口:80

部署静态资源

第一种方式:
  • 放置html资源到Nginx安装目录的html文件夹,Nginx默认部署html文件夹的index.html
    • nginx.conf指定server { }配置的location / { }里的站点路径
第二种方式:配置虚拟主机
  • 配置Nginx安装目录下的配置文件:可以指定多个server { }端口
    • nginx.conf指定server { }配置的listen后的端口号,通过不同端口访问不同的server
  • 配置Nginx安装目录下的配置文件:可以指定多个server { }域名
    • nginx.conf指定server { }配置的server_name后配置域名或IP地址,以此访问不同的server
      • 域名需要通过DNS服务器解析,否则就要手动修改电脑的hosts文件

反向代理与负载均衡

  • 正向代理:正向代理,架设在客户机与目标主机之间,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中。
  • 反向代理:反向代理服务器架设在服务器端,通过缓冲经常被请求的页面来缓解服务器的工作量,将客户机请求转发给内部网络上的目标服务器;并将从服务器上得到的结果返回给请求连接的客户端,此时代理服务器与目标主机一起对外表现为一个服务器。
反向代理

修改nginx.conf配置:

  1. http { }内配置一个upstream:

    1
    2
    3
    upstream 代理的名称 {
    server 被代理的服务器ip:端口;
    }
  2. 定义一个server:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    server {
    listen 80; #用于访问的端口号
    server_name localhost; #用于访问的域名或IP地址

    location / {
    proxy_pass http://代理的项目名称; #反向代理的访问路径
    index index.jsp; #访问的文件名
    }
    }
  3. 重启nginx:./nginx -s reload

负载均衡
  1. 为每一个被代理的tomcat服务器和端口配置为server:此时访问被代理的项目,3台server被Nginx随机分配

    1
    2
    3
    4
    5
    upstream 代理的名称 {
    server 被代理的服务器1ip:端口;
    server 被代理的服务器2ip:端口;
    server 被代理的服务器3ip:端口;
    }
  2. 为每一个被代理的tomcat服务器和端口配置为server,并且指定权重

    1
    2
    3
    4
    5
    upstream 代理的名称 {
    server 被代理的服务器1ip:端口 weight=权重1;
    server 被代理的服务器2ip:端口 weight=权重2;
    server 被代理的服务器3ip:端口 weight=权重3;
    }

    注意:由于每次访问的tomcat服务器不确定,可能导致session问题,建议使用ip_hash方式分配负载

  3. 为此upstream代理指定为按照请求的ip的hash结果分配

    1
    2
    3
    4
    5
    6
    upstream 代理的名称 {
    ip_hash;
    server 被代理的服务器1ip:端口;
    server 被代理的服务器2ip:端口;
    server 被代理的服务器3ip:端口;
    }
  4. 为此upstream代理指定为按照访问url的hash结果分配,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效:

    1
    2
    3
    4
    5
    6
    7
    upstream 代理的名称 {
    hash $request_uri;
    hash_method crc32;
    server 被代理的服务器1ip:端口;
    server 被代理的服务器2ip:端口;
    server 被代理的服务器3ip:端口;
    }

    注意:此时不能指定weight等其他参数,hash_method后为hash算法

  5. 为此upstream代理的server指定其他参数:

    • down:此server暂时不参与负载

    • backup:当其他所有的非backup服务器为down或者忙的时候才请求backup服务器

      1
      2
      3
      4
      5
      6
      upstream 代理的名称 {
      ip_hash;
      server 被代理的服务器1ip:端口 down; #不参与负载
      server 被代理的服务器2ip:端口 weight=2; #权重为2
      server 被代理的服务器3ip:端口 backup; #备用服务器
      }

Linux部署项目案例

  • Maven项目进行package命令后生成的包名过长,可以在build标签内指定finalName标签设置名称

  • 指定数据库连接配置的字符集

    • 修改druid.propertiesurl=jdbc:mysql://localhost:3306/db1?characterEncoding=utf-8
  • 修改项目中的绝对路径为相对路径

  • 修改无误后利用Maven进行打包,执行Maven的:package

  • 复制打包好的war文件到服务器上,在运行tomcat的情况下直接复制到webapps目录下即可自动部署

可能遇到的问题

  • Web项目获取不到服务器端的验证码,日志显示服务器500错误:根本原因:java.awt.AWTError:Can't connect to X11 window server using localhost as the value of the DISPLAY variable.

    • 原因:这种情况是由于用到了java.awt包下的Image等对象导致的问题

    • 解决方法:修改tomcat的bin目录下的catalina.sh

      在最上方添加:JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true"即可解决图片500问题

Docker

使用背景

项目部署的问题:

image-20210925152744642

Docker解决依赖的兼容问题:

image-20210925152950772

Docker解决不同系统环境问题:

image-20210925153350716

Docker解决大型项目依赖关系复杂、不同组件依赖的兼容性问题:

  • Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像

  • Docker应用运行在容器中,使用沙箱机制,相互隔离

Docker解决开发、测试、生产环境的差异问题:

  • Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意的Linux系统上运行

image-20210925154120533

概念

Docker与虚拟机

image-20210925154814518

image-20210925155029677

镜像和容器

image-20210925155316704

Docker和DockerHub

image-20210925155421943

Docker架构

image-20210925155643573

image-20210925155741092

快速入门

安装Docker

企业部署一般都是采用Linux操作系统,而其中又数CentOS发行版占比最多,所以安装Docker到CentOS下

  1. 卸载Docker(可选)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    yum remove docker \
    docker-client \
    docker-client-latest \
    docker-common \
    docker-latest \
    docker-latest-logrotate \
    docker-logrotate \
    docker-selinux \
    docker-engine-selinux \
    docker-engine \
    docker-ce
  2. 安装yum工具

    1
    2
    3
    yum install -y yum-utils \
    device-mapper-persistent-data \
    lvm2 --skip-broken
  3. 更新本地镜像源

    1
    2
    3
    4
    5
    6
    7
    8
    # 设置docker镜像源
    yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

    sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

    yum makecache fast
  4. 安装Docker-CE

    1
    yum install -y docker-ce

启动Docker

  1. 启动前要关闭防火墙

    1
    2
    3
    4
    5
    6
    # 关闭
    systemctl stop firewalld
    # 禁止开机启动防火墙
    systemctl disable firewalld
    # 查看防火墙状态
    systemctl status firewalld
  2. 启动Docker

    1
    2
    3
    4
    systemctl start docker  # 启动docker服务

    systemctl stop docker # 停止docker服务
    systemctl restart docker # 重启docker服务
  3. 查看状态可以通过:

    • systemctl status docker
    • docker -v

配置镜像加速

参考阿里云容器镜像服务:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors

配置/etc/docker/daemon.json

1
2
3
4
5
6
7
8
9
10
sudo mkdir -p /etc/docker

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

sudo systemctl daemon-reload
sudo systemctl restart docker

Docker基本操作

镜像名称

  • 镜像名称一般分为两部分组成:[repository]:[tag]

  • 如果没有指定[tag],默认为latest最新版本

image-20210925163641758

镜像操作命令

image-20210925163901563

拉取pull

案例:从DockerHub拉取一个镜像

  1. 在DockerHub搜索镜像名

    image-20210925172741128

  2. 复制拉取命令

    image-20210925172858950
  3. 执行拉取命令等待pull完成

    image-20210925173026244

导出save和加载load

案例:利用docker save将镜像导出磁盘,然后再通过load加载回来

  1. 利用docker 命令 –help查看docker savedocker load的语法

  2. 使用docker tag创建新镜像mynginx1.0

  3. 使用docker save导出到磁盘

    1
    2
    docker save -o mynginx.tar nginx:latest
    # 导出成-o后面的mynginx.tar,镜像为nginx的最新版本
  4. 使用docker load导入镜像

    1
    2
    docker load -i mynginx.tar
    # 导入的来源为-i后的mynginx.tar
    image-20210925183121919

容器命令

image-20210925222930569

案例1:创建运行Nginx容器

  1. 去DockerHub查看Nginx的容器运行命令

    image-20210925224318458

  2. 在80端口运行nginx容器映射到80端口上,可以通过ip:80端口访问此nginx容器

    docker run --name 容器名 -p 80:80 -d nginx

  3. 查看访问日志:

    • docker logs 容器名
    • 刷新查看日志:docker logs -f 容器名
  4. 清理日志

    • 进入容器目录:cd /var/lib/docker/containers/容器ID
    • 查看大小:ls -lh
    • 清空日志:cat /dev/null > 容器ID-json.log

image-20210925225033757

案例2:进入容器修改内容

要求:进入Nginx容器,修改HTML内容,添加一行文本

image-20210925225825090

image-20210925230547503

同理:操作redis容器

  1. 创建redis容器:

    1
    docker run --name myredis -p 80:80 -d redis redis-server --appendonly yes
  2. 进入容器:

    • 进入bash命令进入然后启动redis-cli

      1
      2
      [root@master docker]# docker exec -it myredis bash
      root@d5ae50394a6d:/data# redis-cli
    • 直接进入redis-cli命令

      1
      [root@master docker]# docker exec -it myredis redis-cli
  3. 现在即可使用redis的命令

查看已部署的容器信息

  • 查看正在运行的容器:docker ps
  • 查看所有容器,包括没有运行的:docker ps -a
  • 查看容器信息并且不省略:docker ps --no-trunc

数据卷

image-20210925232700504

概念

数据卷(volume)是一个虚拟目录,指向宿主机文件系统中的某个目录

image-20210925233238823

基本语法

image-20210925233205970

image-20210925233633952

image-20210925233706310

挂载数据卷

image-20210925233812608

案例1:创建一个nginx容器,修改容器内的html目录内的index.html内容

image-20210925234939623

执行docker run时利用-v指定了volume时若不存在,会自动创建此volume

image-20210925235114407

案例2:创建并运行一个MySQL容器,将宿主机目录挂载到容器

image-20210926000524650

  1. 创建启动容器

    1
    2
    3
    4
    5
    6
    7
    8
    docker run \
    --name mysql \
    -e MYSQL_ROOT_PASSWORD=123 \
    -p 3306:3306 \
    -v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
    -v /tmp/mysql/logs:/var/log/mysql \
    -v /tmp/mysql/data:/var/lib/mysql \
    -d mysql:5.7.25
  2. 启动后/etc/docker/mysql子目录会同步mysql的数据卷,并且可以通过3307端口登录root用户,密码123

    注意:自定义mysql端口需要给容器配置文件中指定port=3307 image-20211122014300152

修改mysql时区:

  • 进入容器:docker exec -it 容器名 bash
  • 查看当前系统时区:date -R
  • 修改时区:cp /usr/share/zoneinfo/PRC /etc/localtime
  • 退出容器后重启容器:docker restart 容器名

redis容器案例

1
2
3
4
5
6
7
docker run  \
-p 6379:6379 \
--name redis_tjj \
-v /etc/redis/redis.conf:/etc/redis/redis.conf \
-v /etc/redis/data:/data \
-d redis:latest \
redis-server /etc/redis/redis.conf

image-20210926002503970

自定义镜像

镜像结构

image-20210926005342122

  • 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成

image-20210926005407454

Dockerfile

Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer

image-20210926005710948

案例:基于Ubuntu镜像构建一个新镜像,运行一个java项目

image-20210926011218197

简化:基于java:8-alpine镜像,将一个Java项目构建为镜像

image-20210926011547599

image-20210926011929772

DockerCompose

  • Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器
  • Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行

image-20210926012924275

安装Docker Compose

  1. 下载安装Docker Compose

    1
    2
    # 安装
    curl -L https://github.com/docker/compose/releases/download/1.23.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

    或者通过上传本地的docker-compose到/user/local/bin目录

  2. 修改文件权限:添加可执行权限

    1
    chmod +x docker-compose
  3. Bash自动补全命令

    1
    2
    # 补全命令
    curl -L https://raw.githubusercontent.com/docker/compose/1.29.1/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
    • 可能需要修改hosts:echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts

image-20210926014150151

案例:部署微服务集群

要求:将cloud-demo的order、user微服务项目利用Docker Compose部署

image-20210926125314530

Docker镜像仓库

常见镜像仓库服务

镜像仓库(Docker Registry)有公共的和私有的两种形式:

  • 公共仓库:例如Docker官方的DockerHub,国内也有一些云服务商提供类似于DockerHub的公开服务,例如网易云镜像服务、DaoCloud镜像服务、阿里云镜像服务等
  • 私有仓库:用户可以在本地搭建私有Dcoker Registry。

搭建镜像仓库

简化版镜像仓库

Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,但是没有图形化界面。搭建方式比较简单,命令如下:

1
2
3
4
5
6
docker run -d \
--restart=always \
--name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry

命令中挂载了一个数据卷registry-data到容器内的/var/lib/registry 目录,这是私有镜像库存放数据的目录。

访问http://YourIp:5000/v2/_catalog 可以查看当前私有镜像服务中包含的镜像

带有图形化界面版本

使用DockerCompose部署带有图形界面的DockerRegistry,命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: '3.0'
services:
registry:
image: registry
volumes:
- ./registry-data:/var/lib/registry
ui:
image: joxit/docker-registry-ui:static
ports:
- 8080:80
environment:
- REGISTRY_TITLE=这是私有仓库名字
- REGISTRY_URL=http://registry:5000
depends_on:
- registry

由于私服采用的是http协议,默认不被Docker信任,所以需要做一个配置:

1
2
3
4
5
6
7
8
# 打开要修改的文件
vi /etc/docker/daemon.json
# 添加内容:
"insecure-registries":["http://192.168.150.101:8080"]
# 重加载
systemctl daemon-reload
# 重启docker
systemctl restart docker

部署成功后访问:ip:8080即可访问Docker Registry UI

在私有镜像仓库推送或拉取镜像:

image-20210929005648444

image-20210929005733712

Kubernetes

介绍

应用程序部署方式的演变

  • 物理机部署:应用程序直接部署在物理机上
    • 缺点:很难合理分配资源,应用程序之间容易产生影响
  • 虚拟机部署:在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
    • 应用程序之间独立,但浪费了系统资源
  • 容器化部署:与虚拟机类似,但是共享了操作系统
    • 优点:
      • 可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等
      • 运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
      • 容器化的应用程序可以跨云服务商、跨Linux操作系统版本进行部署

容器化部署方式的问题:

  • 一个容器故障停机,怎么样让另一个容器立刻启动去替补停机的容器
  • 当并发访问量变大的时候,怎么做到横向扩展容器数量

这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,产生了一些容器编排的软件:

  • Swarm:Docker自己的容器编排根据
  • Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
  • Kubernetes:Google开源的容器编排工具

Kubernetes简介

Kubernetes是一个全新的基于容器技术的分布式架构领先方案,是谷歌严格保密十几年的秘密武器——Borg系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本

Kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。它的目的是实现资源管理的自动化,主要提供了以下功能:

  • 自我修复:一旦某个容器崩溃,能够在1秒左右迅速启动新的容器
  • 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
  • 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
  • 负载均衡:如果一个服务启动了多个容器,能够自动实现请求的负载均衡
  • 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
  • 存储编排:可以根据容器自身的需求自动创建存储卷

Kubernetes组件

一个Kubernetes集群主要是由**控制节点(master)工作节点(node)**构成。每个节点上都会安装不同的组件。

  • master:集群的控制平面,负责集群的决策
    • ApiServer:资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
    • Scheduler:负责集群资源调度,按照预订的调度策略将Pod调度到相应的node节点上
    • ControllerManager:负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
    • Etcd:负责存储集群中各种资源对象的信息
  • node:集群的数据平面,负责为容器提供运行环境
    • Kubelet:负责维护容器的生命周期,即通过控制docker来创建、更新、销毁容器
    • KubeProxy:负责提供集群内部的服务发现和负载均衡
    • Docker:负责节点上容器的各种操作

image-20211210234316472