docker的整合

Docker的整合

一、为什么需要Docker

一般我们写程序的,能接触到好几个环境

  • 自己写代码的环境叫做开发环境。
  • 给测试去跑的环境叫做测试环境。
  • 测试完可以对外使用的叫做生产环境。

其实我们在学习编程中,很多时间都浪费在“环境”上:

  • 如果我现在重装了系统,我想要跑我的war/jar包,我得去安装一下JDK、Tomcat、MySQL等配置各种的环境变量才能跑起来。
  • 开开心心地跟着博主给出的步骤去写Demo,但总是有Bug。(这里我将版本/依赖也归纳在环境的范畴里边)。
  • 好不容易在测试环境下跑起来了,在生产环境就各种出错!
  • 跟着教学视频做分布式/集群的项目,跑一堆的虚拟机,每个虚拟机都要安装对应的环境。

上面的这些东西你可能不能完全体会,但是相信每个人都体会过安装软件,下载软件的艰辛吧,尤其是使用百度云的时候,尤其是下载大的镜像的时候。找软件的过程应该也是艰辛的。docker就可以解决我们这个痛苦。

所以就有个笑话《千万不要跟程序员说,你的代码有bug》:

  • 他的第一反应是你的环境有问题,第二就是你是傻逼不会用吧。
  • 你要跟他这么说:“这个程序运行的怎么运行的跟预期不一样,是我操作有问题吗?”。
  • 这货就会第一反应“我擦,这是不是出bug了?”

1.2应用之间需要隔离

比如我写了两个应用(网站),这两个应用部署在同一台服务器上,那可能会出现什么问题?

  • 如果一个应用出现了问题,导致CPU占100%。那另一个应用也会受到关联,跟着一起凉凉了。
  • 这两个应用是完全不同技术栈的应用,比如一个PHP,一个.NET。这两个应用各种的依赖软件都安装在同一个服务器上,可能就会造成各种冲突/无法兼容,这可能调试就非常麻烦了。

二、Docker是如何解决上述的问题的

2.1解决环境(切换/配置)

不知道大家有没有装过系统,比如说装Linux虚拟机,重装Windows系统,都是需要镜像的。

有了这个镜像,我们就可以运行这个镜像,来进行安装系统的操作(此处省略N个下一步),于是我们的系统就装好了。一般来说,我们去官方渠道下载的镜像,都是纯净的。比如去官方下载Windows镜像,装完后之后桌面只有一个回收站。

但有过了解装系统的同学可能就会知道,有的镜像装完可能还有360这些软件,但系统的的确确是变了。简单来说,就是这些镜像添加了其他的东西(比如360软件、腾讯、千千静听等等软件)。

Docker也是这种思路,可以将我们的想要的环境构建(打包)成一个镜像,然后我们可以推送(发布)到网上去。想要用这个环
境的时候,在网上拉取一份就好了。

有了Docker,我们在搭环境的时候,跟以前的方式就不一样了。

既然Docker属于一个容器,它就是用来装东西的,东西来自于远程的docker仓库,我们需要什么就从仓库里面拿什么。

  • 之前:在开发环境构建出了一个war包,想跑到Linux下运行。我们得先在Linux下载好Java、Tomcat、MySQL,配置好对应的环境变量,将war包丢到Tomcat的webapps文件夹下,才能跑起来。
  • 现在:在Linux下直接拉取一份镜像(各种环境都配好了),将镜像运行起来,把war包丢进去就好了。

这就是精髓了,我们要拉取的这个镜像帮我们打包了好了所有的运行环境,这不就省的我们自己去下载了嘛,还减掉了下载的版本不同导致出现bug的情况。我们只需要运行把项目放进去,运行docker下载好的镜像就可以了。

将Docker的镜像运行起来就是一两秒的事情而已,十分方便的。

2.2解决应用之间隔离

说到这里,就得提出一个大家可能不认识的概念:LXC(Linux Containers)—>Linux容器。

2.2.1Linux容器

在Linux内核中,提供了cgroups功能,来达成资源的区隔化。它同时也提供了名称空间(namespace)区隔化的功能,使应用程序看到的操作系统环境被区隔成独立区间,包括进程树,网络,用户id,以及挂载的文件系统。

简单来说就是:LXC是一个为Linux内核包含特征的用户接口。通过强大的API和简单的工具,它可以让Linux用户轻松的创建和托管系统或者应用程序容器。

2.2.2回到Docker

我们在翻看Docker的官方文档的时候,也很容易看见cgroup和namespace这两个名词:

来源维基百科:

Early versions of Docker used LXC as the container execution driver, though LXC was made optional in v0.9 and support was dropped in Docker v1.10.

lxc是早期版本docker的一个基础组件,docker 主要用到了它对 Cgroup 和 Namespace 两个内核特性的控制。新的Docker版本已经移除了对LXC的support。

2.2.3Docker在Windows和Mac

上面说了,Docker底层用的Linux的cgroup和namespace这两项技术来实现应用隔离,那Windows和Mac用户能用Docker吗?

上面说了,Docker底层用的Linux的cgroup和namespace这两项技术来实现应用隔离,那Windows和Mac用户能用Docker吗?

  • 之前,Windows和Mac使用Docker实际上就是跑了一层Linux虚拟机。

    • 比如在Windows下安装的是Docker Toolbox,它需要Oracle Virtual Box来跑Docker
  • 现在,Windows和Mac都已经原生支持Docker了。但需要一些安装的条件,详情可以查看官网

    • 比如Windows:Docker for Windows requires 64bit Windows 10 Pro and Microsoft Hyper-V

参考资料:

  • Windows 原生 Docker 正式商用

    • http://blog.daocloud.io/windows-docker/

三、虚拟机和Docker

估计大家都用过虚拟机,虚拟机也能实现对应用的隔离,安装特定的镜像也能跑出我们想要的环境。虚拟机已经发展了很久了,为什么我们还需要Docker呢?

这部分内容在官网也有相关的介绍:

  • http://www.docker-cn.com/what-container#/virtual_machines

一句话总结:Docker容器比虚拟机轻量多了!

我自己对docker和虚拟机的理解,我感觉docker就是一个运行速度快,暂用内存少的虚拟机。一般的电脑启动一个虚拟机风扇就呼呼的转了,别说搭建集群了。而且docker下载镜像可以是打包重新生成的镜像,我不知道虚拟机可不可以下载。

最后

Docker可以干嘛?

  • 将一整套环境打包封装成镜像,无需重复配置环境,解决环境带来的种种问题。
  • Docker容器间是进程隔离的,谁也不会影响谁。

了解了Docker的作用,我们就看看到底是怎么用的。

Docker的入门

一、Docker相关术语

  • 镜像
  • 容器
  • 仓库

我们先从仓库获取镜像,通过一个镜像又可以制作出多个容器。这就和在虚拟机安装镜像一下,每拷贝一个linux系统相当于又用镜像生成了一个容器。

二、安装Docker与HelloWorld

既然我们用的是Docker,肯定第一步是先把他安装到自己的windows中,mac中,还是远程的服务器中,这个就根据你的要求来了。

在安装的时候一定要明确自己的版本,这种无用功做多了挺烦的。

首先需要明确自己所使用的环境,就我而言,我使用的是CentOS 7。据我所知,CentOS 7CentOS 6.8在安装中都是有区别的。

所以,如果你想跟着我一起安装Docker,先明确自己的版本是否是CentOS 7,如果不是只能找其他的教程来进行安装。

cat /etc/redhat-release

// 结果

CentOS Linux release 7.3.1611 (Core)

上面是查看自己的Linux版本的命令。

2.1安装Docker

首先我们需要安装GCC相关的环境:

// 安装GCC相关的环境

yum -y install gcc

yum -y install gcc-c++

如果曾经安装过Docker(旧版本)的话,得先卸载,如果没有安装过,跳过这一步:

// 卸载旧Docker版本

yum -y remove docker docker-common docker-selinux docker-engine

安装Docker需要的依赖软件包:

// 安装Docker需要的依赖软件包:

yum install -y yum-utils device-mapper-persistent-data lvm2

设置stable镜像仓库(注意:我们这里使用国内的镜像地址【因为Docker 官网给出的地址在国外,太慢了!】)

// 设置stable镜像仓库:

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新yum软件包索引:

// 更新yum软件包索引:

yum makecache fast

安装DOCKER CE(注意:Docker分为CE版和EE版,一般我们用CE版就够用了)

// 安装DOCKER CE:

yum -y install docker-ce

启动Docker

// 启动Docker

systemctl start docker

2.2HelloWorld走起

到上面为止,我们已经启动了Docker,下面我们检验一下我们运行的Docker是否正常。

首先,我们可以看看下载回来的Docker版本:

// 查看Docker的版本

docker version

版本都查到了,说明Docker是运行起来的啦。我们来一发HelloWorld:

// docker的HelloWorld

docker run hello-world

当我们运行这个命令的时候,默认会先从远程仓库拉取hello-world的镜像,因为本地我们没有创建,然后通过镜像创建一个容器,然后运行该容器。这个hello-world容器的功能就是一句话:Hello from Docker!。所以我们在屏幕上就可以看到这句话了。

效果:

2.3配置加速器

由于安装的Docker默认是去Docker Hub找我们想要的镜像的,我们知道国外肯定没国内的快,所以我们一般会配置一个加速器

国内的镜像仓库一般我们使用的有:

  • 阿里云
  • 网易云
  • // 等等

首先,我们到下面链接搜索一下镜像,比如Tomcat (这就需要我们注册/登录一个阿里云账号)

  • https://promotion.aliyun.com/ntms/act/kubernetes.html

随后,我们可以在镜像加速器上找到我们的url:

我们依照阿里云给出的教程,就可以配置加速器了。

mkdir -p /etc/docker


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

让配置生效,并重启Docker

systemctl daemon-reload

systemctl restart docker

这里有些同学可能会有疑问了,我按照docker的时候不是设置镜像仓库了嘛,那个镜像是我们下载docker时候使用的国内的镜像仓库下载的docker.而我们这里是通过docker容器下载docker仓库里面的东西。

运行了个Hello-World感觉没什么意思,毕竟去了公司也不让我只运行Hello-World,我要学的干货还没来了。

三、体验Docker

假如说,要在一台全新的系统上将Tomcat跑起来。我们需要做以下的事:

  • 安装Java,配置环境变量
  • 安装Tomcat

如果我们用了Docker,我们是这样做的:直接在仓库里拉一份tomcat的镜像下来,将镜像跑起来就,就完事了!

拉取Tomcat镜像:

docker images查看是否有拉取到的tomcat

docker image ls

拉取到的Tomcat镜像:

运行这个Tomcat镜像,生成容器

docker run -it -p 9999:8080 tomcat

我们可以发现,这个Tomcat运行起来了

(滚犊子,没运行起来,踩坑了!,一直卡在INFO: Deploying web application directory这句话上了。我还一直想,为啥我访问不到呢,才发现没运行起来)

看到这里我突然有了一个怀疑,不是tomcat镜像里面没jdk吧,看了下面的内容,不是这个原因,我的心情还是比较美丽的。

因为要想运行tomcat必须有jdk的环境,每次按照jdk其实也挺烦的。

3.1解决docker运行Tomcat卡住的问题

原因:

docker+tomcat 启动时非常慢,一般正常启动几十秒的,发现docker+tomcat启动竟需要几分钟,不可思议

根本原因是 SecureRandom 这个 jre 的工具类的问题。那为什么 SecureRandom generateSeed 这么慢,甚至挂在 Linux 操作系统呢?

Tomcat 7/8 都使用 org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom 类产生安全随机类 SecureRandom 的实例作为会话 ID。

SecureRandom generateSeed 使用 /dev/random 生成种子。但是 /dev/random 是一个阻塞数字生成器,如果它没有足够的随机数据提供,它就一直等,这迫使 JVM 等待

首先,我们先以后台的方式运行Tomcat镜像:

docker run -tid  tomcat

以bash的方式进入到容器中:

docker exec -it 4a471223bfc4(为你正在运行容器的id) /bin/bash

为容器安装vim

apt-get update


apt-get install vim

修改对应的java.security文件

cd /docker-java-home/jre/lib/security

vim  java.security

找到 securerandom.source=file:/dev/random,修改为securerandom.source=file:/dev/./urandom

在Tomcat镜像下创建一个属于我们自己的Tomcat镜像(这个镜像安装了vim,修改了配置文件)

docker commit -m "change java.security" -a "3y" 4a471223bfc4(为当前容器的id) mytomcat

于是我们就生成了mytomcat镜像,就可以使用mytomcat:

docker run -it -p:9999:8080 mytomcat

效果图:

参考资料:

  • docker 启动tomcat慢的解决方法

    • https://my.oschina.net/lwenhao/blog/1830538
  • JRE /dev/random阻塞

    • https://www.cnblogs.com/lemon-flm/p/7396627.html

除了Tomcat,大家还可以去拉个mysql、redis、centos等等镜像来玩玩~~

如果上面的步骤没有启动成功可以看下这个视频

或者直接看链接

四、命令说明

剩下的命令我们在使用的过程中百度就可以了,毕竟现在就算全学会也会忘记。

最后

留下几个问题:

  • 我们知道Tomcat运行起来需要Java的支持,那么我们在Docker拉取下来的Tomcat镜像是不是也有Java环境呢?

这个肯定是有的,要不然不可能运行成功。

  • 容器退出了(好比Linux进程退出了),容器的数据就没了,我们想要保留容器内的数据,怎么办?
  • 从上面我们可以看出,通过commit可以在原有的容器基础上,创建出属于我们自己的镜像,还有其他方式创建新的镜像吗?

Docker镜像

首先我们至少要明白,其实我们看到的windows系统这个页面底层都是一行行的代码写出来了,所以Docker镜像的底层也是代码写的。存放代码的文件我们叫做DockerFile文件。

Dockerfile是用来构建Docker镜像的文件,是由一系列命令和参数构成的脚本

简单来说:Dockerfile是镜像的源码

上一篇我们pull了一份Tomcat的镜像,我们也可以去看看它的Dockerfile长的什么样:

我们随便点进去一个看一下:

我们在Dockerfile的第一行就可以发现FROM openjdk:8-jre,所以可以确定的是:在DockerHub拉取下来的Tomcat镜像一定有Java环境

在这里我们先不说如何阅读/编写Dockerfile文件,先了解到Dockerfile是镜像的源码即可

简单来说:通过Dockerfile文件可以知道我们拉取下来的镜像究竟是怎么构建的。

二、解除镜像的疑惑

我们知道Docker Hub有很多常用的镜像,比如说Centos。我们去pull一个下来看看Docker中的Centos长啥样:

我们可以发现的是:TomcatSIZE竟然比Centos还要大!但按我们常规的想法,Centos的镜像可能是3或4GB(现在200M),Tomcat的镜像可能就200M(现在400M)。这是为什么呢??

如果我们在pull的时候观察得比较仔细的话,可以发现pull会拉下很多镜像:

完全pull下来的之后,我们如果使用docker images只能查看到最终的镜像:

如果我们使用docker images -a命令的话,可以把中间层镜像都查出来:

  • 理想效果:(在镜像列表里边除了tomcat和centos应该还夹杂着名为``的镜像)
  • 遗憾的是:博主一直没测出效果来,也就是我的镜像列表里没有``的镜像(怀疑是版本的问题,我的版本是Docker版本是18.09.1,Centos的版本是CentOS Linux release 7.3.1611 。如果知道具体原因的不妨在评论区下告诉我)

Emmm,我们可以使用history命令来看看,可以发现Tomcat包含很多个镜像层

还可以发现一点:Dockerfile有多少条命令,那就有多少个镜像层(不信你数数)

说了那么多,就想让大家知道:我们拉取下来的镜像实际上是由很多中间层镜像组成的。

再结合我们上一篇Docker入门为什么可以这么简单?,在解决Tomcat启动时一直卡住问题时,能够发现的是,我们可以使用cd, ls等基础命令,但无法使用vi命令(需要我自己去下载)。

我们可以推断出,pull下来的镜像由很多层镜像组成【这些镜像都是精简过的(甚至连vi命令都不支持)】

  • 因为Tomcat镜像要的基础环境比Centos镜像要多,所以Tomcat镜像的SIZECentos要大

三、Docker镜像的特点

关于Docker镜像,有以下特点:

  • Dockerfile生成
  • 呈现层级结构
  • 每层镜像包含:镜像文件以及镜像json元数据信息

图像来源:http://open.daocloud.io/allen-tan-docker-xi-lie-zhi-shen-ke-li-jie-docker-jing-xiang-da-xiao/

3.1镜像呈现层级结构

联合文件系统(UnionFS)是实现Docker镜像的技术基础。在Docker中一般使用是AUFS(Another Union File System或Advanced Multilayered Unification File System)【具体还是得看宿主机用的什么系统】。

在搜索中文资料的时候,常常会发现有类似的解释:

“AUFS是一种 Union FS, 简单来说就是“支持将不同目录挂载到同一个虚拟文件系统下的文件系统”, AUFS支持为每一个成员目录设定只读(Rreadonly)、读写(Readwrite)和写(Whiteout-able)权限。Union FS 可以将一个Readonly的Branch和一个Writeable的Branch联合在一起挂载在同一个文件系统下”。

看得我一头雾水….后来去官方文档介绍AUFS:

AUFS is a union filesystem, which means that it layers multiple directories on a single Linux host and presents them as a single directory. These directories are called branches in AUFS terminology, and layers in Docker terminology

说白了,还是可以理解成:Docker的镜像的基础是联合文件系统,它支持将文件系统中的修改信息作为一次提交,并层层叠加,外界看到的是最外层的镜像。(比如外界只看到Tomcat镜像,而中间叠加了很多层镜像)

(这里只是拿AUFS说明,Docker实际上支持很多存储驱动,比如还有devicemapper,overlay2(Ubuntu的14.04.4或更高版本,16.04或更高版本), overlay,zfs

  • https://docs.docker-cn.com/engine/userguide/storagedriver/selectadriver/

3.1.1镜像继承(共享)

Docker镜像可以通过分层来进行继承

例如,hello-world的Dockerfile镜像FROM scratch镜像,scratch在Docker中是一个基础镜像

FROM scratch
COPY hello /
CMD ["/hello"]

Centos的Dockerfile镜像也是FROM scratch镜像:

FROM scratch
ADD centos-7-docker.tar.xz /

LABEL org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20181205"

CMD ["/bin/bash"]

那么Centos镜像和hello-world共享同一个基础镜像层scratch,提高了存储效率

再说个例子,比如我们有一个Centos镜像,这个镜像大小是202M。然后,我们基于Centos镜像手动往里边添加一个Tomcat(假设这个Tomcat的大小是300M),生成一个镜像,总大小就是502M了。

如果仅仅是单纯的累加这两个镜像的大小:202M+502M=704M,但是由于镜像复用的存在,实际占用的磁盘空间大小是:202M+300M=502M

AUFS uses the Copy-on-Write (CoW) strategy to maximize storage efficiency and minimize overhead。

如果想要了解COW,不妨阅读我之前写过的文章:

3.2json文件

Docker每一层镜像的json文件,都扮演着一个非常重要的角色,其主要的作用如下:

  • 记录 Docker 镜像中与容器动态信息相关的内容
  • 记录父子 Docker 镜像之间真实的差异关系
  • 弥补 Docker 镜像内容的完整性与动态内容的缺失

Docker镜像的json文件可以认为是镜像的元数据信息

最后

今天简单地聊了一下Docker镜像的一些细节,但没去深入了解,想要继续深入的同学还得通过官方文档等途径去学习哈。

转自:https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484674&idx=1&sn=e3ea5efe00fde6ebd3c73d5bf2155813&chksm=ebd74403dca0cd15bb3f5e288f28ce2058f8031ee18c2912cec05d886552c24e6e8d8e5ff1ce&token=1676899695&lang=zh_CN###rd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值