Docker

文章目录

Docker是什么

简单的理解docker是一个轻量级的虚拟机

虚拟机VSDocker

优点

更小更快

更好的资源利用

很多年前,那时候还没有虚拟化,当我们需要创建一个新服务时,我们必须申请实际的物理机硬件。 这可能要花上数月,依赖于公司的流程。一旦服务器到位,我们创建好服务,很多时候它并没有像我们希望的那样成功,因为服务器的CPU使用率只有5%。 太奢侈了。

接着,虚拟化来了。它可以在几分钟之内把一台机器运转起来,还可以在同一硬件上运行多个虚拟机,资源使用率就不只5%了。但是,我们还需要给每个服务分配一个虚拟机,因此我们还是不能如愿的使用这台机器。

容器化是演化进程的下一步。容器可以在几秒之内创建起来,而且还能以比虚拟机更小的粒度进行部署。

依赖

Docker启动速度真的很酷。 但是,我们为什么不把所有的都服务部署到同一台机器上呢? 原因很简单:依赖的问题。在同一台机器上安装多个独立的服务,不管是真是机器还是虚拟机都是一场灾难。用Docker公司的说法是:地狱一样的矩阵依赖。

而Docker通过在容器中保留依赖关系解决了矩阵依赖的问题。

速度

快当然不错,但是能快100倍就太不可思议了。速度让很多事情成为可能,增加了更多新的可能性。比如,现在可以快速创建新的环境,如果需要从 Clojure开发环境完整的切换到Go语言吗?启动一个容器吧。需要为集成和性能测试提供生产环境DB ?启动一个容器吧! 需要从Apache切换整个生产环境到Nginx?启动容器吧!

Docker是怎么工作的

Docker 概念及相互作用

  • 主机, 运行容器的机器。
  • 镜像,文件的层次结构,以及包含如何运行容器的元数据
  • 容器,一个从镜像中启动,包含正在运行的程序的进程
  • Registry, 镜像仓库
  • 卷,容器外的存储
  • Dockerfile, 用于创建镜像的脚本

我们可以通过Dockerfile来构建镜像, 还可以通过commit一个运行的容器来创建一个镜像,这个镜像可以会被标记,可以推到Registry或者从Registry上拉下来,可以通过创建或者运行镜像的方式来启动容器,可以被stop,也可以通过rm来移除它。

镜像

镜像是一种文件结构,包含如何运行容器的元数据。Dockerfile中的每条命令都会在文件系统中创建一个新的层次结构,文件系统在这些层次上构建起来,镜像就构建于这些联合的文件系统之上。

这是一些经常使用的镜像相关的数据:

  • scratch – 基础镜像, 0个文件,大小为0
  • busybox – 最小Unix系统,2.5MB,10000个文件
  • debian:jessie – Debian最新版, 122MB, 18000 个文件
  • ubuntu:14.04 – 188MB,23000 个文件

命令

  1. Build
    • FROM – 新镜像是基于哪个镜像的
    • MAINTAINER – 镜像维护者的姓名和邮箱地址
    • COPY – 拷贝文件和目录到镜像中
    • ADD – 同COPY一样,但会自动处理URL和解压tarball压缩包
    • RUN – 在容器中运行一个命令, 比如:apt-get install
    • ONBUILD – 当构建一个被继承的Dockerfile时运行命令
    • .dockerignore – 不是一个命令, 但它能控制什么文件被加入到构建的上下文中,构建镜像时应该包含.git以及其它的不需要的文件。
  2. 用于与容器交互的命令
    • docker create # 创建一个容器,但不启动它
    • docker run # 创建并启动一个容器
    • docker stop # 停止容器
    • docker start # 启动容器
    • docker restart # 重启容器
    • docker rm # 删除容器
    • docker kill # 给容器发送kill信号
    • docker attach # 连接到正在运行的容器中
    • docker wait # 阻塞直到容器停止为止
    • docker exec # 在运行的容器中执行一条命令
  3. 检查容器
    • docker ps # 显示运行的容器
    • docker inspect # 显示容器信息(包括ip地址)
    • docker logs # 获取容器中的日志
    • docker events # 获取容器事件
    • docker port # 显示容器的公开端口
    • docker top # 显示容器中运行的进程
    • docker diff # 查看容器文件系统中改变的文件
    • docker stats # 查看各种纬度数据、内存、CPU、文件系统等

Registry

Docker Hub是Docker的官方镜像仓库,支持私有库和共有库

Docker Hub 还支持自动化构建来自Github和Bitbucket的项目,如果启用自动构建功能,那么每次你提交代码到代码库都会自动构建镜像。

即使你不想用自动构建,你还是可以直接 docker push到Docker Hub,Docker pull则会拉取镜像下来。docker run 一个本地不存在的镜像,则会自动开始 docker pull操作。

你也可以在任意地方托管镜像,官方有 Registry的开源项目

此外,国内也有厂商提供私有镜像托管服务。

由于进程在容器中创建的数据不会永久的保存起来,所以当kill掉一个容器后,它的数据将丢失;如果我们想要保存进程产生的数据,比如日志,那么就要用到卷,它把容器内部的目录挂载到主机上。

# 启动新的nginx容器,设置/var/log为卷,并映射到主机的/tmp目录下 
$ docker run -v /tmp:/var/log nginx

环境配置

安装docker

与普通安装linux软件没有区别,具体可以看docker官方文档

内核要求:Linux 3.10

$ uname -r
3.10.0-229.el7.x86_64

由于docker要用到linux的container技术进行用户,网络,文件系统,cpu,内存等资源的隔离,所以对于内核版本有要求,最低3.10;

因此centos要求7.x; ubuntu要求12.04

从源码生成镜像

编写Dockerfile:

FROM sails/protobuf
MAINTAINER sails xu <sailsxu@qq.com>

ENV LC_ALL C.UTF-8

RUN DEBIAN_FRONTEND=noninteractive apt-get install wget
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y ruby
# 安装libiconv
RUN DEBIAN_FRONTEND=noninteractive git clone https://github.com/sails/libiconv.git
RUN DEBIAN_FRONTEND=noninteractive cd libiconv && ./configure && make && make install && rm -rf ../libiconv

通过命令生成镜像:

docker build ./ -t imagename

运行容器

docker run -d -p 40000:40000 -p 40004:40004 -p 40005:40005 -v /root/flygame/v1/log:/flygame/dist/log -w /flygame/dist imageId ./flygame_monitor.rb

集群

kubernetes和swarm

swarm集群是docker1.12内置加入的集群解决方案(2016年7月);kubernetes是google的,它加入了google多年内部集群的相关理念;

swarm集群

优点:简单:由于docker内置,所以不用再单独安装,集群一键搭建;

缺点:功能较弱,由于从7月份才发布第一个版本,所以很多功能都弱于kubernetes;

  • (1)docker swarm:集群管理,子命令有init, join, leave, update
    • (2)docker service:服务创建,子命令有create, inspect, update, remove, tasks
    • (3)docker node:节点管理,子命令有accept, promote, demote, inspect, update, tasks, ls, rm
    • (4)docker stack/deploy:试验特性,用于多应用部署 下面在一个三节点环境中,针对各个命令进行试用,详细展开说明

kubernetes

优点:功能强大,全套的解决方案;不只用于docker,还可以用于Rocket(coreos的容器)

缺点:安装很复杂,并且要理解一些新的概念(pods, Replication Controllers, services);

  1. 安装

    可以查看kubernetes官方教程,基本上有三种安装方式,一是直接安装二进制文件;二是通过脚本安装docker镜像;三是通过kubeadm安装docker镜像;

    前两种都比较复杂,要去配置各种参数,kubeadm是最新的二进制安装工具,这里推荐通过它来安装;不过要注意的是,由于kubernetes在安装过程中需要从google cloud上下载镜像,所以你懂的!

  2. 使用

    有两种使用方式,1:通过命令行的方式,最开始的版本中也只有命令行;2;使用dashboard;

kubernetes介绍

kubernetes是什么

kubernetes是Google开源的容器集群管理系统,其提供应用部署、维护、 扩展机制等功能,利用Kubernetes能方便地管理跨机器运行容器化的应用,其主要功能如下:

  • 1) 使用Docker对应用程序包装(package)、实例化(instantiate)、运行(run)。
  • 2) 以集群的方式运行、管理跨机器的容器。
  • 3) 解决Docker跨机器容器之间的通讯问题。
  • 4) Kubernetes的自我修复机制使得容器集群总是运行在用户期望的状态。

当前Kubernetes支持GCE、vShpere、CoreOS、OpenShift、Azure等平台,除此之外,也可以直接运行在物理机上。

基本概念

Kubernetes把集群分成Master和Slave,Master主要用来接收用户操作命令,然后指导Slave进行pods的管理;用户通过kubernetes REST 接口可以操作的三个对象(pod, service, replication controller)。

  • pod:Kubernetes最基本的部署调度单元,可以包含container,逻辑上表示某种应用的一个实例。比如一个web站点应用由前端、后端及数据库构建而成,这三个组件将运行在各自的容器中,那么可以创建包含三个container的pod。
  • service:是pod的路由代理抽象,用于解决pod之间的服务发现问题。因为pod的运行状态可动态变化(比如切换机器了、缩容过程中被终止了等),所以访问端不能以写死IP的方式去访问该pod提供的服务。service的引入旨在保证pod的动态变化对访问端透明,访问端只需要知道service的地址,由service来提供代理。

  • replicationController:是pod的复制抽象,用于解决pod的扩容缩容问题。通常,分布式应用为了性能或高可用性的考虑,需要复制多份资源,并且根据负载情况动态伸缩。通过replicationController,可以指定一个应用需要几份复制,Kubernetes将为每份复制创建一个pod,并且保证实际运行pod数量总是与该复制数量相等(例如,当前某个pod宕机时,自动创建新的pod来替换)。

  • Deployment:用于部署应用时的一个抽象,它包含了pod和Replica Sets(它是下一代replication controller)。它是1.2版本引入的,方便我们在发布过程中对应用进行修改,更新,回滚等操作;
  • Pet Set: 在kubernetes1.3之前,pod与pod之间是弱关系的,它们通过环境变量或者通过DNS彼此关联;一旦pod重启pod名称,网络与储存(pod一般不挂载存储或者挂载共享存储,保存的是所有Pod共享的状态)都会发生改变。这样对于无状态的服务很适合,但是对于数据库集群这样一个有状态的应用来说,就会带来很多挑战(比如数据怎么挂载,其中一个数据库进程怎么定位)。而1.3开始引入pet set,它可以保障pod是有状态的,(重启之后名称不变,网络不变,存储不变),这样的pod就更新一台真正的虚拟机了;

在集群中部署应用的方式

  1. 首先通过docker创建对应的镜像
  2. 通过Dashboard来部署

日志解决方案

不管用不用docker,在集群中都会涉及到日志的问题,因为机器一多不可能每个机器上去看;只是docker 上更加重要;

Docker由于作为容器不可能去理解应用中的日志规则,所以对于我们应用中的记录在文件中的日志,它没有办法去理解,但是对于标准输出,它确会把它记录下来:日志位于 /var/lib/docker/containers/<container_id>,文件名为<container_id>-json.log,它是一个json格式的文件。

我们可以简单的通过docker logs去查看日志:

但是在一个集群中,我们不可能去查看每个容器的日志,所以需要一个统一的收集器,这里引入一个Fluentd、Elasticsearch、Kibana和Swift方案。

具体可以看这里

DNS

由于在集群中,我们不可能相互之后事先知道服务的地址,所以需要一个办法去得到对方的ip地址;有三种办法,1:程序中通过读取配置文件或者环境变量,2:通过DNS;

kubernetes对这两种都提供了支持,但是环境变量对于服务的先后顺序有要求,并且当services重新创建之后,在集群中ip地址会改变,可能会导致使用方连接不上,所以最好用DNS的方式;

通过dns就解决了环境变量先后的问题,因为dns的方式是把services和ip的映射保存到一个集中的地方,这样,使用的时候再查询(在pod中gethostbyname)。

kubernetes中以通过插件的方式使用skydns作为DNS服务器,并且通过kube2sky来创建和删除记录:

建一个临时性的pod,并且运行它的终端:

通过查看pod中的dns配置,可以发现,kubernetes在启动Pods,是把dns服务器的址写到了resolv.conf配置中:

监控

cAvisor

在kubernetes中提供了cAdvisor来监控资源情况,在新版本中,已经在它集成到了kubelet中了:

它会收集本机以及容器的监控数据(CPU, memory, filesystem, and network usage statistics)。可以通过UI,也可以通过JSON的方式返回。

不过由于cAvisor是把数据保存到内存中,所以不能记录历史数据。

Heapster

它会收集cAvisor中的数据,把它记录到数据库中,然后配合前端进行展示:

原文链接:,转发请注明来源!

发表评论