docker-1

来源:互联网 发布:js面向对象教程 编辑:程序博客网 时间:2024/06/06 01:45

Docker是什么?

​ Docker是一个轻量级的(Go语言)开源的应用容器引擎技术(非常方便的发布应用到容器中),容器类似于虚拟机技术(xen、kvm、vmware、virtual)。Docker是直接运行在当前操作系统(Linux)之上,而不是运行在虚拟机中(容器使用宿主操作系统的内核,而虚拟机使用独立的内核,但是它只能用在 64 位的操作系统上),但是也实现了虚拟机技术的资源隔离,性能远远高于虚拟机技术。Docker支持将软件编译成一个镜像(image),在这个镜像里做好对软件的各种配置,然后发布这个镜像,使用者可以运行这个镜像,运行中的镜像称之为容器(container),容器的启动是非常快的,一般都是以秒为单位。这个有点像我们平时安装ghost操作系统,系统安装好后软件都有了,虽然完全不是一种东西,但是思路是类似的。Docker 帮助系统管理员和程序员在容器中开发应用程序,并且可以扩展到成千上万的节点。

​ 目前各大主流云计算平台都支持Docker容器技术,包括阿里云、百度云平台(资源隔离通过Dockert实现)、Cloud Foundry(和Spring一家公司的,目前最成熟也最稳定)、HeroKu、DigitalOcean、OpenShift(JBoss的)、Apache Stratos、Apache MesOS(批处理平台,支持搭建基于Docker的云平台)、Deis(开源PaaS平台);连微软也在Windows Server及其云平台Azure上支持Docker,这样看来Docker大有统一云计算的趋势。
​ 这里的云计算平台一般指的是PaaS(平台即服务),它是一个这样的云计算平台:提供了存储、数据库、网络、负载均衡、自动拓展等功能,你只需将你的程序交给云计算平台就可以了。你的程序可以是用不同的编程语言开发的,而使用的Docker的云计算平台就是用Docker来实现以上功能及不同程序之间的隔离的。
目前主流的软件以及非主流的软件大部分都有人将其封装成Docker镜像,我们只需下载Docker镜像,然后运行镜像就可以快速获得已经做好配置可运行的软件。使用Docker后我们将不用手动下载、安装和配置这些软件(Oracle XE,Redis,MongoDB,ActiveMQ,RabbitMQ)。

特征

​ 面向产品、面向开发、面向测试、面向运维、面向自动化、面向微服务、面向大规模的分布式架构

局限性

​ 基于Linux64位的,不能再32bit环境下运行

​ GuestOS只能是Linux Base

​ 隔离性相对于KVM等虚拟化技术有所欠缺

​ 采用cgroup的resource control对于cpu的度量很难(内存、硬盘)

​ container随着用户进程的停止而销毁

dokcer和LXC(ubuntu)的区别

​ docker更专注部署,而LXC专注于进程的隔离

​ docker有更好的api方便对于docker容器的管理

​ dockerfile让image的创建变得容易

​ 通过docker hub 方便image的分享

未来(focus)

​ 网络(容器间通信)

​ 安全性

​ 容器引擎(libcontainer)

Linux FS

​ 第一层:boot file system(bootfs),包含bootloader和kernal,在启动完成后,kernel在内存中,bootfs解除挂载

​ 第二层:root file system(rootfs),包括/bin等目录,这些是和kernel无关,和不同的Linux分发版本有关

Linux FS in Docker

​ Kernel->BusyBox/Debian->rootfs

FS in Docker

​ 传统Linux启动时,将rootfs设置为readonly并检查完整性,然后设置成read-write

​ Docker在启动container的时候,也是把rootfs设置为readonly,然后通过aufs把一个readwirte的文件系统挂载到rootfs之上,并且把下层文件系统设置成readonly,这样构成一个完整的操作系统

Layer FS

​ 对于每一层readonly的FS,在docker中称为image

​ 对于顶上read-write的FS,称为container

​ 对于readonly中内容的修改,采用的是COW的技术,把文件复制到read-write层并改写,实际用户看到的是当前container层中的文件,image中的文件不会被影响,通过覆盖文件达到实际效果

Image

​ 除了base image之外,每一层Image 都有一个parent image(单链表)

​ 没有parent iamge的镜像叫做base image(操作系统)

​ 基于COW的技术,image部分是不会被修改的,因此container可以共享image层的FS,提高了存储的效率

​ lxc,aufs/btrfs:Kernel:bootfs->Debian:Base Image->add emacs:Image(refereces parent)->add Apache:Image->Writeable:Container

Storage driver

​ 除了默认的aufs之外,docker通过对于storage的抽象,可以支持一些其他的storage driver,通过vfs,devicemapper,btrfs

​ 修改docker启动时候的参数设置,增加-storage-driver={storage plugin}在配置文件中

镜像命名和版本管理

​ base image是docker官方提供的基础镜像

​ 普通镜像的命名规范{namespace}/{repository name}:{tag}

​ namespace是docker hub的用户名,实际是起到了namespace的作用

​ repsitoty ,类似与github的项目,例如ubuntu,mysql等

​ tag,表示版本信息,例如cesc/mysql:5.5,tag是可选的,默认值的latest

Image

​ 对于不存在的Image,Docker会自动去Registry里面下载对应的Image,然后再运行Container

COMMAND

​ Command标志的是在container中实际运行的首进程

​ 如果Image里面包含了CMD的指令,那么在启动container的时候,不需要指定Command,否则会使用指定的Command来覆盖Image中的CMD

前台运行VS后台运行

​ 默认的Container是在前台运行的,会绑定Command进程的STDIN,STDOUT,STDERR到console上

​ 可以通过-d选项让Container运行在后台

​ 如果是在前台运行,也可以通过指定-a {STDOUT,STDIN,STDERR}选择需要绑定的IO

​ 通过attach命令可以重新attch一个后台运行的container

Container Identification

​ 在后台运行的情况下,RUN命令会返回一个UUID,唯一标示Container

​ 可以通过docker ps来查看container的UUID和运行信息

​ 可以通过指定–name的方式来指定container的名字,name必须唯一

inspect

​ 通过docker inspect{Container ID}来获取container的更多的信息,包括网络,Volume,实际在Host上的进程等信息

Log

​ 通过Logs命令可以看到Container中Command所指向进程的STDOUT,STDERR数据

环境变量

​ 通过-e参数,可以在运行container的时候添加系统环境变量

网路设置

​ docker使用bridge的方式来实现Container之间以及外部的通信

​ Network架构:描述:Host:{Bridge docker0{{Container ‘app’,{Tomcat (port 8080)}},{Container ‘app’,{Tomcat (port 8080)}})}

​ 在Host主机上的一个veth{id}的虚拟网卡和一个container里面的eth0网卡一一映射

​ Host上的bridge负责把数据流在不用的veth间转发,实现网络的IO

​ bridge(docker0)使用RFC1918私有网络,给每一个container分配IP

​ 通过–net参数来修改container的网络设置,默认是bridge的方式

​ none 表示关闭container的网络连接

​ host表示主机的网络栈,这个时候host主机不会创建veth虚拟网卡映射

​ container:{name|id},使用另外一个container的网络栈

DNS

​ 默认使用Host的DNS配置

​ 可以通过–dns的参数来指定container自己的dns配置

端口映射

​ Docker通过采用端口映射的方式,允许把内部Container的服务端口暴露到外部

​ 使用-p参数可以指定需要暴露的container的内部端口,在不指定特定的Host的对应端口的情况下,docker会自动分配(49000-49900)在一个Host上的端口与其映射

​ 使用-P参数,表示暴露所有在Image中通过EXPOSE指定的端口,或者随机端口

Volume绑定

​ 通过-v参数,可以把Host上的一个目录绑定到container中,允许container对其进行读写

容器间通信

​ 通过Link参数,把container的端口信息暴露到另一个container中,实现container之间的通信

Dockerfile

​ Docker通过对于在Dockerfile中的一系列指令的顺序解析实现自动的Image的构建

build命令

​ 通过使用build命令,根据Dockerfile的描述来构建镜像

build的两种方法

​ 通过源代码路径的方式

​ 通过标准输入流的方式

通过源代码路径

​ Dockerfile需要放置在项目的根目录位置

​ 在构建的时候,Docker Client会把整个Context打包发送到Docker Server端,然后由Server端负责build镜像,在构建成功后,会删除Context目录

​ docker build -t {镜像名字} {项目的路径,可以是相对路径}

通过标准输入流

​ 通过标准输入流的方式获取Dockerfile的内容

​ client不会打包上传Context目录,因此对于一些ADD,COPY等涉及Host本地文件复制的操作不够支持

​ docker build -t {镜像名字}-< Dockerfile路径

build cache

​ Dockerfile 中的每一个指令执行完毕后,都会提交为一个Image,这样保证了指令之前不会有影响

​ Docker会尽可能尝试重用之前已经构建的镜像

​ 可以通过在build命令中增加–no-cache的方式来禁用cache

dockerignore

​ 当选择源代码路径的方式构建image的时候,通过在根目录下放置dockerignore文件,来过滤不需要发送到server端的文件

​ 类似于.gitignore的概念

Dockerfile指令

​ 只支持Docker自己定义的一套指令,不支持自定义

​ 大小写不敏感,但是建议全部大写

​ 根据Dockerfile的内容顺序执行

FROM

​ FROM {base镜像}

​ 必须放在Dockerfile的第一行,表示从哪个BaseImage开始构建

MAINTAINER

​ 可选的,用来标示Image作者

RUN

​ 每一个RUN指令都会是在一个新的Container里面运行,并提交为一个Image作为下一个RUN的Base

​ 一个Dockerfile中可以包含多个RUN,按定义顺序执行

​ RUN支持两种运行方式

​ RUN< cmd > 这个会当做/bin/sh -c “cmd”运行

​ RUN[“executable”,”arg1”,….],Docker把它当做JSON的序列来解析,因此必须用双引号,而且executable需要是完整路径

CMD

​ CMD的作用是作为执行Container时候的默认行为

​ 当运行Container的时候声明了Command,则不再使用Image中的CMD所定义的命令

​ 一个Dockerfile中只能有一个有效的CMD,当定义多个CMD的时候,只有最后一个才会起作用

CMD定义三种方式

​ CMD < cmd >这个会当做/bin/sh -c “cmd”来执行

​ CMD [“executable”,”arg1”,”arg2”]

​ CMD[“arg1”,”arg2”],这个时候CMD作为ENTRYPOINT的参数

ENTRYPOINT

​ ENTRYPOINT的作用是,把整个Container变成了一个可执行的文件,这样不能够通过替换CMD的方法来改变创建Container的方式.但是可以通过参数传递的方式影响到Container内部

​ 每个Dockerfile只能够包含一个ENTRYPOINT,多个ENTRYPOINT只有最后一个能有效

​ 当定义了ENTRYPOINT以后,CMD只能够作为参数进行传递

ENTRYPOINT定义方式

​ ENTRYPOINT[“executable”,”arg1”,”arg2”],这种定义方式下,CMD可以通过JSON序列的方式来定义ENTRYPOINT的参数,可以通过在运行Container的时候通过指定Command的方式传递参数

​ ENTRYPOINT < cmd >,当做/bin/sh -c “cmd”运行

ADD&COPY

​ 当在源代码构建的方式下,可以通过ADD和COPY的方式,把Host上的文件或者目录复制到Image

​ ADD&COPY的源必须在context路径下

​ 当src为网络URL的情况下,ADD指令可以把它下载到Dest的指定位置,这个在任何build的方式下都可以work

ENV

​ ENV key value

​ 用来设置环境变量,后续的RUN可以使用它所创建的环境变量

​ 当创建基于该镜像的Container的时候,会自动拥有设置的环境变量

WORKDIR

​ 用来指定当前工作目录

​ 当使用相对目录的情况下,采用上一个WORKDIR指定的目录作为基准

USER

​ 指定UID或者username,来决定运行RUN指令的用户

ONBUILD

​ ONBUILD作为一个trigger的标记,可以用来trigger任何Dockerifle中的指令

​ 可以定义多个ONBUILD指令

​ 当下一个镜像B使用镜像A作为Base的时候,在FROM A指令前,会先按照顺序执行在构建A时候定义的ONBUILD指令

​ ONBUILD < DOCKERFILE指令>< Context>

VOLUME

​ 用来创建一个在image之外的mount point,用来在多个Container之间实现数据共享

​ 运行使用Json array的方式定义多个Volume

​ VOLUME[“/var/data1”,”/var/data2”]

​ 或者plain text的情况下定义多个VOLUME指定

进入一个容器

​ sshd

​ nsenter

​ exec

sshd

​ 在容器中开启一个SSHD的服务,通过SSH的协议登录到容器中,把容器看成一个VM

​ 安全性不高,需要开启SSHD的服务端口

nsenter

​ nsenter包含在util-linux包中,用来进入一个进程的Namespace (yum install util-linux)

​ 获取一个容器的进程ID,docker inspect –format “{{.State.Pid}}” < container-id>

​ nsenter –target $PID –mount –uts –ipc –net –pid

exec

​ docker 1.3版本引入的一个新的指令,用来进入一个容器中运行指令

Orchestration as a Service

​ Orchestrate as a Service的目标是协调在不同Host上的Container,把他们有机的组织在一起成为一个统一的系统

OaaS

​ 解决Container的协调管理

​ 单个数据中心单节点/多个节点跨数据中心

​ Container之间的网络通信

OaaS方案

​ Fig,非常简单,但是问题是不支持跨主机的Orchestrate

​ Kubernetes,Google推出的跨云的orchestration as a service的解决方案

Fig

​ Fig通过对于Docker的封装,从而方便我们构建应用的运行环境

​ 应用运行的所有组件全部运行在Container中,通过服务发现的方式连接在一起

服务发现

​ Fig使用Docker自带的Link方式来实现服务发现,Fig会负责管理Link的相关信息

fig.yml

​ fig通过读取当前目录下的fig.yml文件来创建应用的运行环境

​ fig.yml中需要定义不同的service

Service

​ Service标示的是一个独立的组件,例如Web应用,MySQL,Redis等都可以定义为一个独立的Service,Service是可以横向拓展的

​ 可以在Service中直接定义Image,也可以通过定义build配置项来运行时创建Image

​ 所有的Service都会被运行为一个或者多个Docker的Container

fig.yum例子

​ build(.)说明从当前目录来构建Image,需要当前目录有Dockerfile,镜像名称默认是{当前目录名字_ServiceName}

​ command表示启动Container的CMD

​ links中的值是service name,这样可以在scale out中把多个container连接到自己

创建环境

​ fig up 命令会根据当前的fig.yml来启动container,并且根据配置信息把对应的container连接在一起

​ 可以通过fig up{service}的方式,只启动某个Service定义的Container

​ 如果在当前目录下反复运行fig up,会每次都重新创建新的Container,可以通过加参数–no-recreate来防止这个问题产生

检查当前环境

​ fig ps,类似于docker ps ,用来检查当前fig.yml所定义的service对应的Container的运行情况

水平拓展

​ fig scale service=Num的方式可以水平拓展service对应的Container的个数

​ 新添加的container如果是link的源头之一,是不会被自动添加到Link的目标Container中的,这个可以通过重新创建目标Container的方式来解决

清除环境

​ fig stop可以用来停止Container

​ fig rm可以用来删除Container

调试

​ 可以通过使用fig run{service}CMD的方式来对环境进行调试,比如需要看到实际通过Link注入到某一个Service的环境变量,可以通过fig run web export的方式

​ fig run也是运行一个Container,如果该Service依赖于其他的Service,并且其他的Service没有被创建,那么也会先创建其他Service的Container,可以通过设定–no-deps来禁止

我为什么要使用Docker?

​ 作为新手,在一台linux机器上安装一些服务可能是麻烦的,而通过Docker已有镜像安装这些是极其方便而高效的,Docker可以减少运维成本而提高资源利用率,在结合已有的开发框架后,项目开发更加迅捷,比如说SpringBoot创建了微服务工程后,直接扔到Docker中运行,或许中间会通过一个持续代码交付平台,。。。。。。。

如何使用Docker?

安装

​ Centos系统中:(Docker 软件包已经包括在默认的 CentOS-Extras 软件源里;为了方便之后的使用,以管理员权限安装)

sudo yum install docker

卸载

`需要先知道已经安装了哪些docker的功能,然后依次删除掉yum list installed|grep docker复制每一行前面的名称后yum -y remove *删除旧的文件夹rm -rf /var/lib/docker  `

配置加速

echo "DOCKER_OPTS=\"\$DOCKER_OPTS --registry-mirror=http://f2d6cb40.m.daocloud.io\"" | sudo tee -a /etc/default/dockerDOCKER_OPTS="$DOCKER_OPTS --registry-mirror=http://f2d6cb40.m.daocloud.io"

通过查看版本号检测是否安装成功

docker -v

启动

systemctl start docker.service(CentOS 7之前)旧式指令为: service docker start

设置为开机启动

systemctl enable docker.service(CentOS 7之前)旧式指令为: chkconfig docker on

*通过查看进程检测是否启动成功*

ps aux|grep docker   通过管道转换进程流输出显示

关闭

systemctl stop docker.service

搜索镜像

​ 在Docker中各种应用或者服务都是一个镜像,如键值对缓存技术Redis,反向代理服务器Nginx,JMS型的消息队列ActiveMQ,AMQP型的消息队列RabbitMQ……….这些都可以通过直接安装而获得服务,可以简化配置,默认仓库是docker hub,按照start量排名

docker search 镜像名

​ 在搜索结果中,列名中OFFICIAL一栏中值为OK的即为官方版

安装镜像

docker pull 镜像名

​ 默认是latest的TAG

通过查看已经安装的全部镜像检测是否安装成功

docker images

​ 其中REPOSITORY一列中表示的是该镜像所在的仓库的名称(默认来自DockerHub),TAG(标签),IMAGE ID(镜像ID):每一个镜像都有一个唯一的镜像ID,CREATED:上次修改的时间,SIZE(大小)

​ 这里的IMAGE ID其实是截断的id,查看完整的id: –no-trunc

删除镜像

docker rmi 镜像名/镜像ID(IMAGE ID)

上传镜像

​ docker login,登录到docker hub上

​ 把container通过docker commit 容器id 的命令转换成一个image

​ 通过dokcer tag 镜像id 来命名新生成的image

​ docker push 用名O命名/镜像名称[:tag] 到docker hub中

启动容器

​ 运行一个container的本身就是开启一个具有独立namespace的进程(host中一个普通进程)

​ 运行一个container必须要指定一个image作为初始化的文件系统

​ sudo docker run [OPTIONS] IMAGE[:TAG]_[COMMAND]-[ARG…]

docker  run 镜像名 echo 'hello dokcer'   运行后会立即退出docker run --name custom_name  -it 镜像名 bash 启动后进入docker容器中,相当于进入了一台新的机器,进入之后可以通过ls -al 查看所处目录中的文件(linux中包括文件夹),ps aux 查看进程 docker每次只能启动一个进程docker run -d --name custom_name 镜像名 后台模式启动一个镜像,其实也可以不需要先安装就可以启动一个镜像,因为docker会事先pull下来docker start 镜像ID   通过这种方式启动容器可以简便参数的输入镜像名称:标志  默认是启动lasted标志的版本的镜像 

查看容器

docker ps -a  所有docker ps -l  当前运行中的容器

停止容器

docker stop [CONTAINTER ID]

​ 但是这样只能停掉一个container,如果想要停掉所有的container:dokcer ps -a -q|xargs docker stop

进入容器

docker exec或者docker attachnsenter --target 容器PID --mount --uts --ipc --net --pid 容器PID如何获取?docker inspect -f {{.State.Pid}} 容器id(部分标示即可不需全部)推荐使用: docker exec -it 容器id /bin/bash

删除容器

docker rm 删除运行中的容器 docker rm -f

​ 但是这样只能删除一个container,如果想要删除所有的container:dokcer ps -a -q|xargs docker rm

查看帮助

docker --help

进入一个已经运行的容器中

dokcer attach 容器id   这样有时候是进不去的而且之后只能ctrl+c退出然后再次查看运行中的容器时会发现该容器已经退出了nsenter 进入容器中(命名空间),如果没有需要安装 :yum install -y util-linuxnseneter --target 进程ID  --mount --uts --ipc --net --pid

查看容器的信息

docker inspect --format "{{.State.Pid}}" 容器ID/其中时指定的名称

访问端口映射

随机映射:docker run -P指定映射:-p hostPort:ContainerPort-p ip:hostPort:containerPort-p ip::containerPort-p hostPort:containerPort -p hostPort:containerPort

指定数据卷

docker run -it -v /data redis查看数据卷所在位置:docker inspect -f {{.Volumes}} 容器名指定数据卷在宿主机器中的位置 dokcer run -it -v /dockerData:/dockerData redis只读:docker run -it -v /dockerData:/dockerData:ro redis

数据卷容器

​ 专门的docker容器作为一个数据卷,作为中间人

--volumes-from 其他容器名

构建Docker镜像

FROM:基础镜像MAINTAINER:维护者信息RUN:把命令前面加上RUNADD:COPY文件(同一级),会自动解压WORKDIR:当前工作目录VOLUME:目录挂载EXPOSE:端口RUN:进程要一直运行下去docker make -t 镜像名 

Docker核心原理-资源隔离和限制

​ LXC Kernel