【Docker】---Docker入门篇(1)

 Docker入门篇

    简单一句话: Docker 是一个便携的应用容器。

一、Docker的作用

网上铺天盖地的是这么说的:

    (1) Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多。

    (2) Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。

    (3) 更快速的交付和部署、更轻松的迁移和扩展.

道理呢是这个道理 但如果一点都没接触的人的不一定能够理解进去 。

   通俗解释一:

在Docker出世之前,作为一个java开发的我 在服务器上搭建java环境是如何做的呢?

首先在云服务器上安装jdk tomcat mysql数据库...... , 如果有多个项目,我们可以运行多个tomcat 每个tomcat里面一个java应用。

这样也确实没啥毛病 但有它的弊端:

(1)如果公司新买了一个云服务器 同时需要把项目部署到该服务器上。那你是不是需要又要在该服务器上安装jdk、tomcat、mysql等等.....是不是很繁琐?

(2)如果需要在服务器上搭建net环境、java环境 那么他们依赖的软件会不会产生冲突呢。

这张图解释的挺好的。

A1模式: 上面讲的就相当于这里的模式A1,所有的应用共享服务器的CPU、内存等资源,这时如果一个应用出现问题,比如CPU爆满等等,另一个应用也就玩完了。

           所以要这时就要做到资源独立, 一个应用一份资源。

A2模式: 一个服务器上装几个虚拟机,一个虚拟机一个应用。这时如果你要重启虚拟机,你想想你重启电脑要多久。而且你想迁移应用的话,你就又要装虚拟机,

           配环境等等,麻烦不?我是觉得麻烦。

A3模式: A3模式就是Docker,容器是什么概念我就不说了,这时一个服务器上运行多个容器,一个容器拥有独立的CPU、内存等资源,完全满足了应用隔离的需求。

           而且容器重启,1秒搞定!应用迁移的时候,这个大家应该也知道,所有装了Docker的服务器,只需把镜像pull或者load进去,run,一切OK,就是这么任性!

通俗解释二:

Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会

互相影响。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。docker就是类似的理念。

       1、不同的应用程序可能会有不同的应用环境,比如.net环境和php环境依赖的软件就不一样,如果把他们依赖的软件都安装在一个服务器上还可能会造成一些冲突。

常规来讲,我们可以在服务器上创建不同的虚拟机,但是虚拟机开销比较高。docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小。

      2、你开发软件的时候用的是Ubuntu,但是运维管理的都是centos,运这个时候就会遇到一些Ubuntu转centos的问题,比如:有个特殊版本的数据库,只有Ubuntu支持

centos不支持,这时候要是有docker你就可以把开发环境直接封装转移给运维,运维直接部署你给他的docker就可以了。而且部署速度快。

     3、在服务器负载方面,如果你单独开一个虚拟机,那么虚拟机会占用空闲内存的,docker部署的话,这些内存就会利用起来。总之docker就是集装箱原理。

【Docker】(2)---仓库、镜像、容器

    学习Docker,我觉得首先要了解的是仓库、镜像、容器到底是什么,他们有什么区别。

一、通俗理解

1、Docker 镜像 (images)

容器运行时的只读模板,操作系统+软件运行环境+用户程序

例如:一个镜像可以完全包含了Ubuntu操作系统环境,可以把它称作一个Ubuntu镜像。镜像也可以安装了Apache应用程序(或其他软件),可以把它称为一个Apache镜像。

我们可以大致的把镜像比喻成一个java类:

 class User{
        		 private String name;
				 private int age;
			 }

2、Docker 容器 (containers)

容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而这些容器都是相互隔离、互不可见的。Docker利用容器来运行和隔离应用。

我们可以大致理解容器是类实例出的对象:

  User user = new User()  

3、Docker 仓库(registeries)

Docker仓库(Repository)用来保存镜像,类似与代码仓库,是Docker集中存放镜像文件的场所

Docker 仓库有公有和私有仓库,好比Maven的中央仓库和本地私服。

总结镜像、容器、仓库这三部分组成了Docker的整个生命周期,如下图所示,容器是由镜像实例化而来的,这和我们学习的面向对象的概念十分相似,我们可以把镜像想象成类,把容器想象成类经过实例化后的对象,这样就非常好理解镜像和容器的关系。


 

二、深层次理解

    要点:容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的

    要点:容器 = 镜像 + 读写层。并且容器的定义并没有提及是否要运行容器。

1、镜像

    镜像就是一堆只读层(read-only layer)的统一视角,也许这个定义有些难以理解,下面的这张图能够帮助读者理解镜像的定义。

    从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,并且能够在主机(译者注:运行Docker的机器)的文件系统上访问到。统一文件系统(union file system)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

2、容器

容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

需要注意:容器的定义并没有提及容器是否在运行

3、运行态容器

一个运行态容器被定义为一个可读写的统一文件系统加上隔离的进程空间和包含其中的进程。下面这张图片展示了一个运行中的容器。

一个容器中的进程可能会对文件进行修改、删除、创建,这些改变都将作用于可读写层(read-write layer)。下面这张图展示了这个行为。

linux部署Docker、Docker常用命令

本次部署Linux版本:CentOS 7.4 64位。 说明: 因为Docker是基于Linux 64bit的 所以Docker要求64位的系统且内核版本至少为3.10

一、部署Docker

1、添加yum源

# yum install epel-release –y
# yum clean all
# yum list

2、安装并运行Docker

# yum install docker-io –y
# systemctl start docker

3、检查安装结果

# docker info

如果出现下面 就说明Docker安装成功了

不得不说 现在在linux部署个框架真的是越来越方便了。

 

二、Docker常用命令

安装部署好Dokcer后,执行的命令是docker开头

总的来说分为以下几种:

  docker [run|start|stop|restart|kill|rm|pause|unpause]             #容器生命周期管理
  docker [ps|inspect|top|attach|events|logs|wait|export|port]       #容器操作运维
  docker [commit|cp|diff]                                           #容器rootfs命令
  docker [login|pull|push|search]                                   #镜像仓库
  docker [images|rmi|tag|build|history|save|import]                 #本地镜像管理

1、镜像命令

搜索镜像

  docker search 镜像名称

列出当前系统存在的镜像

   docker images

拉取镜像

  docker pull image_name
  docker pull image_name:tag
  #image_name:表示镜像的仓库源名称,TAG:镜像的标签 如果不指定tag 那么默认用最新的

删除镜像

docker rmi 镜像名称/镜像ID
docker rmi -f 镜像名称/镜像ID
#强制删除 如果镜像有容器在运行 那么就需要强制删除 增加 -f 参数

举例

docker search nginx       #搜索所有nginx相关的镜像列表(模糊查询)
docker pull nginx         #拉取nginx镜像
docker pull nginx:stable  #拉取tag为stable的nginx

通过查看镜像 会发现是有两个nginx镜像 ,不过他们版本不一样。

2、容器命令

运行容器

docker run  #首先会从本地找镜像,如果有则直接启动,没有的话,从镜像仓库拉起,再启动)
docker run -d --name "xiaoxiao" -p 5672:5672 -p 15672:15672 rabbitmq:management
    	    #-d 后台运行
			#-p 端口映射 (可以有多个 因为该镜像可能存在多个端口)
			#rabbitmq:management  (格式 REPOSITORY:TAG),如果不指定tag,默认使用最新的
			#--name  给该容器取个名字

运行容器后 我们可以直接访问rabbitmq 这就是Docker带来的方便


列举当前运行的容器

docker ps

检查容器内部信息

docker inspect 容器名称

停止某个容器

docker stop 容器名称

启动某个容器

docker start 容器名称

移除某个容器

docker rm 容器名称 (容器必须是停止状态)
【Docker】(4)搭建私有镜像仓库

说明
1、 这里是通过阿里云,搭建Docker私有镜像仓库。
2、 这里打包的镜像是从官网拉下来的,并不是自己项目创建的新镜像,主要测试功能

一、搭建过程

首先进入阿里云创建镜像仓库: https://dev.aliyun.com/search.html-->点击管理中心(初次使用会提示开通,然后设置密码)
然后创建命名空间和镜像仓库:

有关docker拉取和推送指令,点击上图的中管理,就能看到。

1、登录阿里云

docker login --username=hongxuezhe520@qq.com registry.cn-hangzhou.aliyuncs.com

用于登录的用户名为阿里云账号全名,密码为上面开通开通服务时设置的密码。

2、将镜像推送到Registry

 docker tag [ImageId] registry.cn-hangzhou.aliyuncs.com/binron/xx_repertory:[镜像版本号]
 docker push registry.cn-hangzhou.aliyuncs.com/binron/xx_repertory:[镜像版本号]

请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数,还有推送地址每个地区也不一样,我这里是杭州的。

3、从Registry中拉取镜像

docker pull registry.cn-hangzhou.aliyuncs.com/binron/xx_repertory:[镜像版本号]

就是这么滴简单~~~

 

二、案例演示

1、推送到阿里云镜像仓库

(1) 先登陆阿里云镜像仓库

(2)把本地镜像打包,推送到阿里云镜像仓库

(3)在镜像仓库查看

我们可以看到 镜像仓库已经存在该仓库,说明推送成功。

2、从阿里云镜像仓库拉取

拉取后查看,从阿里云镜像仓库拉取成功

 

【Docker】(5)---springCloud注册中心打包Docker镜像

上一篇文章讲了将镜像推送到远处私有仓库,然后再从私有仓库拉取该镜像的过程。而这里的镜像是直接从Docker拉取的。
所以这篇要讲的就是将本地项目打包成Docker镜像的过程。

先说明: 操作系统:mac,JDK版本:1.8,Maven版本:3.5.4

一、Mac安装Docker

1、下载 docker.dmg文件,然后点击下一步,安装完成。

2、下载好后,点击启动Docker,之后在命令行输入:docker version

说明本地安装Docker已经成功

 

二、创建注册中心服务项目

1、application.yml

server:
  port: 7001
  
eureka:
  instance:
    hostname: localhost
  client:
  #声明自己是个服务端
    registerWithEureka: false    #false表示不向注册中心注册自己
    fetchRegistry: false         #false表示自己就是注册中心,职责是维护实例,不参加检索
    serviceUrl:                  #设置eureka server的交互地址,即对外暴露的地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

2、启动类

@SpringBootApplication
@EnableEurekaServer
@RestController
public class EurekaserverApplication {

	public static void main(String[] args) {
		SpringApplication.run(EurekaserverApplication.class, args);
	}

    //用来测试 是否镜像容器是否成功
	@RequestMapping("/user")
	public Object findUser(){
		Map<String, String > map = new HashMap<>();
		map.put("name", "xuxiaoxiao");
		map.put("age","2");
		return map;
	}
}

有关pom的配置,在之前写springcloud中有展示。

三、配置Docker的maven插件

1、dockerfile-maven-plugin插件

       <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.7</version>
                <configuration>
                    <!--打包镜像名称 docker.image.prefix是在上面properties中设置的-->
                    <!--<docker.image.prefix>xdclass</docker.image.prefix>-->
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
       </plugin>

2、配置Dockerfile

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

3、执行打包命令

执行命令:mvn clean package dockerfile:build

说明:之前这边配置的 <version>1.3.6</version>执行上面命令一直报错,之后在STACK OVERFLOW找到原因,因为插件本身版本问题,后面改成1.4.7版本就不报这个错了。

运行成功如图

查看本地镜像

启动镜像容器:docker run -d --name "start" -p 9999:7001 ffff160672d1
页面访问9999端口,看容器是否启动成功。

成功!

有关dockerfile-maven-plugin插件和Dockerfile文件,在接下来博客中会深入了解。

 

springboot项目打包镜像中的Dockerfile文件

在讲Dockerfile文件之前应该先讲下maven的一个插件叫:dockerfile-maven-plugin。他们是组合一起用的

一、dockerfile-maven-plugin

该maven插件可以实现由java源代码直接到docker镜像,配置了dockerfile-maven-plugin插件的maven工具就像是一个管道,一端输入Java源代码, 另一端直接输出docker镜像。在dockerfile-maven-plugin插件出现之前,还有一个maven插件是docker-maven-plugin,是由同一个作者创造,两个 插件的设计思想是有差别的,前者需要独立编写Dockerfile文件,后者允许没有Dockerfile文件,所有的docker相关配置都写在pom文件的plugin中,这样使maven插件显得很笨重,并且如果脱离了这个maven插件还得重写编写Dockerfile,不够灵活。
因此,推荐使用maven插件:dockerfile-maven-plugin

查看pom中插件

<!--指定一个名字而已~-->
    <properties>
    	<docker.image.prefix>xuxiaoxiao</docker.image.prefix>
	</properties>

	<build>
		<finalName>eureka-server</finalName>
		<plugins>
			<!--Docker打包镜像 插件-->
			<plugin>
				<!--三个坐标定位dockerfile插件-->
				<groupId>com.spotify</groupId>
				<artifactId>dockerfile-maven-plugin</artifactId>
				<version>1.4.7</version>
				<configuration>
					<!--这里指定打包镜像的名称-->
					<repository>${docker.image.prefix}/${project.artifactId}</repository>
					<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
					<buildArgs>
						<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
					</buildArgs>
				</configuration>
			</plugin>

		</plugins>
	</build>

 

二、Dockerfile文件

先贴出,上一篇博客Dockerfile文件完整版,再来一个一个分析。

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

1、FORM,这是引入一个父镜像,在此基础上进行添加只读层。之前我写过,镜像可以理解成由一层层只读层组成,FORM下面的命令,可以理解就是在已有的只读层,添加只读层。FORM可以有多个,但最上面的一定是FROM命令。

2、VOLUME,配置一个具有持久化功能的目录,主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。该步骤是可选的。
通俗解释:默认情况下,容器不使用任何 volume,此时,容器的数据被保存在容器之内,它只在容器的生命周期内存在,会随着容器的被删除而被删除。
因为如果你不想在容器删除后,容器的数据也被删除,那么就可以指定持久化目录。它被设计用来保存数据,而不管容器的生命周期。因此,当你删除一个容器时,Docker 肯定不会自动地删除一个volume。

3、ARG, 设置编译镜像时加入的参数。 这里的JAR_FILE就是maven插件中的<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>

4、COPY,只支持将本地文件复制到容器 ,还有个ADD更强大但复杂点。

5、ENTRYPOINT 容器启动时执行的命令。这里就是java -jar app.jar

当然Dockerfile的命令说明官网有标准文档,以后有需要会再回过来查看官方文档。

[Dockerfile官方文档] (https://docs.docker.com/engine/reference/builder/#usage)

 

posted @ 2022-02-21 19:27  hanease  阅读(93)  评论(0编辑  收藏  举报