Docker是基于Go语言实现的开源容器项目,诞生于2013年年初,最初发 起者是dotCloud公司。Docker自开源后受到广泛的关注和讨论,目前已有多个相关项目(包括Docker三剑客、Kubernetes等),逐渐形成了围绕Docker容器的生态体系。现在主流的Linux操作系统都已经支持Docker。例如,红帽公司的RHEL 6.5/CentOS 6.5往上的操作系统、Ubuntu14.04往上的操作系统,都已经在软件 源中默认带有Docker软件包。
Docker的构想是要实现“Build,Ship and Run Any App,Anywhere”, 即通过对应用的封装(Packaging)、分发(Distribution)、部署 (Deployment)、运行(Runtime)生命周期进行管理,达到应用组件“一次封装,到处运行”的目的。这里的应用组件,既可以是一个 Web应用、一个编译环境,也可以是一套数据库平台服务,甚至是一个操作系统或集群。
虚拟化是一种资源管理技术,是将计算机的各种实体资源,如服务 器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的 不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。
虚拟化的核心是对资源的抽象,目标往往是为了在同一个主机上同时运行多个系统或应用,从而提高系统资源的利用率,并且带来降低成本、方便管理和容错容灾等好处。 从大类上分,虚拟化技术可分为基于硬件的虚拟化和基于软件的虚拟化:
真正意义上,基于硬件的虚拟化技术不多见,少数如网卡中的单根多IO虚拟化(Single Root I/O Virtualization and Sharing Specification,SR-IOV)等技术。
基于软件的虚拟化从对象所在的层次,又可以分为应用虚拟化和平台虚拟化(通常说的虚拟机技术即属于这个范畴)。其中,前者一般指的是一些 模拟设备或诸如Wine这样的软件。平台虚拟化又可以细分为如下几个子类:
传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层。
Docker容器是在操作系统(OS)层面上实现虚拟化,直接复用本地主机的操作系统,因此更加轻量级。
1.Docker镜像(Image)
Docker镜像类似于虚拟机镜像,可以将它理解为一个只读的模板。例如,一个镜像可以包含一个基本的操作系统环境,里面仅安装了Apache应用程序(或用户需要的其他软件)。可以把它称为一个Apache镜像。
镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的应用镜像,并直接使用。
2.Docker容器(Container)
Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。容器是从镜像创建的应用运行实例。可以将其启动、开始、停止、删除,而这些容器都是彼此相互隔离的、互不可见的。可以把容器看做是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。
镜像自身是只读的。容器从镜像启动的时候,会在镜像的最上层创建一个可写层。
3.Docker仓库(Repository)
Docker仓库类似于代码仓库,它是Docker集中存放镜像文件的场所。有时候会看到有资料将Docker仓库和仓库注册服务器(Registry)混为 一谈,并不严格区分。实际上,仓库注册服务器是存放仓库的地方,其上往往存放着多个仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。例如存放 Ubuntu操作系统镜像的仓 库称为Ubuntu仓库,其中可能包括14.04、12.04等不同版本的镜像。
根据所存储的镜像公开分享与否,Docker仓库可以分为公开仓库 (Public)和私有仓库(Private)两种形式。目前,最大的公开仓库是官方提供的Docker Hub,其中存放了数量庞大的镜像供用户下载。国内不少云服务提供商(如时速云、阿里云等)也提供了仓库的本地源,可以提供稳定的国内访问。
当然,用户如果不希望公开分享自己的镜像文件,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库。当用户创建了自己的镜像之后就可以使用push命令将它上传到指定的公有或者私有仓库。这样用户下次在另外一台机器上使用该镜像时,只需要将其从仓库上pull下来就可以了。Docker利用仓库管理镜像的设计理念与Git非常相似,实际上 在理念设计上借鉴了Git的很多优秀思想。
MacOS :https://docs.docker.com/docker-for-mac/install/
Windows : https://docs.docker.com/docker-for-windows/
·Docker Platform : 支持在桌面系统或云平台安装Docker;
·Docker Hub : 官方提供的云托管服务,可以提供公有或私有的镜像仓库;
·Docker Cloud : 官方提供的容器云服务,可以完成容器的部署与管理, 可以完整地支持容器化项目,还有CI、CD功能;
·Docker DataCenter : 提供企业级的简单安全弹性的容器集群编排和管理。
Docker目前只能运行在64位平台上且要求内核版本不低于3.10,实际上内核越新越好,过低的内核版本容易造成功能不稳定。Docker目前支持的最低Ubuntu版本为12.04 LTS,但实际上从稳定性上考 虑,推荐至少使用14.04 LTS版本。CentOS系统的要求与Ubuntu情况下类似:64位操作系统,内核版本至少为3.10。Docker目前支持CentOS 6.5及以后的版本,推荐使用CentOS 7系统。
本人电脑安装简略步骤:
http://localhost/ 打开,看到如下页面,表示正确install nginx webserver.
命令行下输入: docker run --help 可查询docker run 命令所有的参数,其他命令也如此。
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Docker运行容器前需要本地存在对应的镜像,如果镜像没保存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。镜像是运行容器的前提,官方的Docker Hub网站已经提供了数十万个镜像供大家开放下载。
docker pull [OPTIONS] NAME[:TAG|@DIGEST] -------> Pull an image or a repository from a registry,如果不显式指定TAG,则默认会选择 latest 标签,就会下载仓库中最新版本的镜像。
一般来说,镜像的latest标签意味着该镜像的内容会跟踪最新的非稳定版本而发布,内容是不稳定的。从稳定性上考虑,不要在生产环境中忽略镜像的标签信息或使用默认的 latest 标记的镜像。如下:
docker pull nodejs:10.11.0 <=====> docker pull registry.hub.docker.com/nodejs:10.11.0
如果从非官方的仓库下载,则需要在仓库名称前指定完整的仓库地址。docker pull hub.c.163.com/public/nodejs:10.11.0
3.1 docker images(获取镜像文件)
·Tag: 比如14.04、latest用来标注不同的版本信息。只是标记,并不能标识镜像内容;
·IMAGE ID(唯一标识镜像): 如果ID一样表示它们目前实际上指向同一个镜像; 它唯一标识了镜像。在使用镜像ID的时 候,一般可以使用该ID的前若干个字符组成的可区分串来替代完整的ID。
·created : 说明镜像最后的更新时间;
·size : 优秀的镜像往往体积都较小。镜像大小信息只是表示该镜像的逻辑体积大小,实际上由于相同的镜像层本地只会存储一份,物理上占用的存储空间会小于各镜像的逻辑体积之和。
3.2 docker tag (取别名)
为了方便在后续工作中使用特定镜像,还可以使用docker tag命令来为本地镜像任意添加新的标签。这些myubuntu:latest镜像的ID跟ubuntu:latest 完全一致。它们实际上指向同一个镜像文件,只是别名不同而已。docker tag 命令添加的标签实际上起到了类似链接的作用。docker tag ubuntu:latest myubuntu:latest
3.3 docker inspect (获取镜像的详细信息)
使用 docker inspect nginx(docker inspect e81eb098537d)命令可以获取该镜像的详细信息,包括制作者、适应架构、各层的数字摘要等。返回的是一个JSON格式的消息,如果我们只要其中一项内容时,可以使用参数 -f 来指定,例如,
获取镜像的Architecture : docker inspect nginx( or e81eb098537d) -f {{".Architecture"}}
3.4 docker history (获取镜像的历史信息)
使用history子命令,该命令将列出各层的创建信息。docker history nginx
3.5 docker rmi (删除镜像)
使用docker rmi命令可以删除镜像,命令格式为docker rmi IMAGE [IMAGE...],其中IMAGE可以为标签或ID。当同一个镜像拥有多个标签的时候,docker rmi命令只是删除该镜像多个标签中的指定标签而已,并不影响镜像文件。删除标签为hello-world:latest的镜像,由于该镜像没有额外的标签指向它,执行docker rmi命令,可以看出它会删除这个镜像文件的所有层.
要想强行删除镜像,可以使用 -f 参数。通常并不推荐使用-f参数来强制删除一个存在容器依赖的镜像。 正确的做法是,先删除依赖该镜像的所有容器,再来删除镜像。
3.6 创建镜像:创建镜像的方法主要有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerfile创建(后续详解)。
3.6.1 基于已有镜像的容器创建
该方法主要是使用docker commit命令。命令格式为docker commit[OPTIONS]CONTAINER[REPOSITORY[:TAG]],主要选项包括:
·-a,--author="":作者信息;
·-c,--change=[]:提交的时候执行 Dockerfile指令,包括CMD| ENTRYPOINT|ENV|EXPOSE|LABEL|ONBUILD|USER|
VOLUME| WORKDIR 等;
·-m,--message="":提交消息;
·-p,--pause=true:提交时暂停容器运行。
Tip : 创建镜像 和 docker tag 打标签的别混淆
3.6.2 基于本地模板导入
docker import命令。命令格式为 docker import [OPTIONS] file|URL|- [ REPOSITORY [:TAG] ]。要直接导入一个镜像,可以使用OpenVZ提供的模板来创建,或者用其他 已导出的镜像模板来创建。例如:
cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04
3.7 存出、载入、上传镜像
如果要导出镜像到本地文件,可以使用docker save命令 docker save -o nginx.tar nginx : latest
可以使用docker load将导出的tar文件再导入到本地镜像库 docker load < nginx.tar <==> docker load --input nginx.tar
可以使用docker push命令上传镜像到仓库,默认上传到Docker Hub官方仓库(需要登录)。命令格式:
docker push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]
容器是镜像的一个运行实例。所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层。如果认为虚拟机是模拟运行的一整套操作系统(包括内核、应用运行 态环境和其他系统环境)和跑在上面的应用,那么Docker容器就是独立运行 的一个(或一组)应用,以及它们必需的运行环境。
4.1.1 可以使用docker create命令新建一个容器
使用docker create命令新建的容器处于停止状态,可以使用docker start命令来启动它。create命令和run命令支持的选项都十分复杂,主要包括如下几大类:与容器运行模式相关、与容器和环境配置相关、与容器资源限制和安全保护相关。
除了创建容器后通过start命令来启动,也可以直接新建并启动容器。新建并启动容器: 所需要的命令主要为docker run,等价于先执行docker create命令,再执行docker start命令。利用docker run来创建并启动容器时,Docker在后台运行的标准操作包括:
docker run -it ubuntu:14.04 /bin/bash
-t : 让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上。 - i : 让容器的标准输入保持打开。
某些时候,执行docker run会出错,因为命令无法正常执行容器会直接退 出,此时可以查看退出的错误代码。 默认情况下,常见错误代码包括:
·125: Docker daemon执行出错,例如指定了不支持的Docker命令参 数;
·126:所指定命令无法执行,例如权限出错;
·127:容器内命令无法找到。 命令执行后出错,会默认返回错误码。
4.1.2 终止容器
更多的时候,需要让Docker容器在后台以守护态(Daemonized)形式运行。此时,可以通过添加 -d 参数来实现。可以用docker ps -qa命令看到所有容器的ID。
可以使用docker stop来终止一个运行中的容器。该命令的格式为docker stop[-t|--time[=10]][CONTAINER...]。首先向容器发送SIGTERM信号,等待一段超时时间(默认为10秒)后, 再发送SIGKILL信号来终止容器。
docker stop containerID
docker kill 命令会直接发送SIGKILL信号来强行终止容器。当Docker容器中指定的应用终结时,容器也会自动终止。例如对 于上一节中只启动了一个终端的容器,用户通过exit命令或Ctrl+d来退出终端时,所创建的容器立刻终止,处于stopped状态。
docker restart 命令会将一个运行态的容器先终止,然后再重新启动。
进入容器进行操作有多种方法,包括使用官方的 attach 或 exec命令,以及第三方的nsenter工具等。
但是使用attach命令有时候并不方便。当多个窗口同时用attach命令连到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
通过指定 -it 参数来保持标准输入打开,并且分配一个伪终端。通过exec 命令对容器执行操作是最为推荐的方式。
默认情况下,docker rm命令只能删除处于终止或退出状态的容器,并不能删除还处于运行状态的容器。如果要直接删除一个运行中的容器,可以添加 -f 参数。Docker会先发送 SIGKILL信号给容器,终止其中的应用then强行删除。docker rm -f containerID
某些时候,需要将容器从一个系统迁移到另外一个系统,此时可以使用 Docker的导入和导出功能。这也是Docker自身提供的一个重要特性。
1.导出容器是指导出一个已经创建的容器到一个文件,不管此时这个容器 是否处于运行状态,可以使用docker export命令,该命令的格式为 docker export [-o|--output[=""]] CONTAINER。其中,可以通过-o选项来指定导出的tar 文件名,也可以直接通过重定向来实现。可将导出的tar文件传输到其他机器上,然后再通过导入命令导入到系统中,从而实现容器的迁移。
$ docker export -o test_for_run.tar ce5
$ ls
test_for_run.tar
$ docker export e81 >test_for_stop.tar
$ ls
test_for_run.tar test_for_stop.tar
2.导出的文件又可以使用docker import命令导入变成镜像,该命令格式为
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
$ docker import test_for_run.tar - test/ubuntu:v1.0
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB
既可以使用docker load命令来导入镜像存储文件到本地镜像库, 也可以使用docker import命令来导入一个容器快照到本地镜像库。 这两者的区别在于:
根据是否为官方提供,可将这些镜像资源分为两类。
一种是类似centos这样的基础镜像,称为基础或根镜像。这些镜像是由Docker公司创建、验证、 支持、提供。这样的镜像往往使用单个单词作为名字。
另一种类型,比如ansible/centos7-ansible镜像,它是由Docker用户ansible创建并维护的,带有用户名称为前缀,表明是某用户下的某仓库。可 以通过用户名称前缀user_name/镜像名来指定使用某个用户提供的镜像。
另外,在查找的时候通过- s N参数可以指定仅显示评价为N星以上的镜像。
1. docker search 命令来查找官方仓库中的镜像
2. docker pull 命令来将它下载到本地
3. docker push 命令来将本地镜像推送到Docker Hub。
自动创建允许用户通过Docker Hub指定跟踪一个目标网站(目前支持 GitHub或BitBucket)上的项目,一旦项目发生新的提交,则自动执行创建。要配置自动创建,包括如下的步骤:
在本地将启动一个私有仓库服务,监听端口为5000。使用registry镜像创建私有仓库 docker run -d -p 5000:5000 registry 。默认情况下,会将仓库创建在容器的/ tmp/registry目录下。可以通过- v参数来将镜像文件存放在本地的指定路径。 例如下面的例子将上传的镜像放到/ opt/data/registry目录:
docker run -d -p 5000:5000 -v /opt/data/registry:/tmp/registry registry
比较新的Docker版本对安全性要求较高,会要求仓库支持SSL/TLS证书。 对于内部使用的私有仓库,可以自行配置证书或关闭对仓库的安全性检查。修改Docker daemon的启动参数,添加如下参数,表示信任这个私 有仓库,不进行安全证书检查:
DOCKER_OPTS="--insecure-registry 10.0.2.2:5000"
如果要使用安全证书,用户也可以从较知名的CA服务商(如verisign) 申请公开的SSL/TLS证书,或者使用openssl等软件来自行生成。
生产环境中使用Docker的过程中,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作。 容器中管理数据主要有两种方式:
在生产环境中,笔者推荐在使用数据卷或数据卷容器之外,定期将主机 的本地数据进行备份,或者使用支持容错的存储系统,包括RAID或分布式文件系统如Ceph、GPFS、HDFS等。数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount操作。
1.在容器内创建一个数据卷
在用docker run命令的时候,使用- v标记可以在容器内创建一个数据卷。 多次重复使用-v标记可以创建多个数据卷。下面使用training/webapp镜像创建一个web容器,并创建一个数据卷挂载 到容器的/webapp目录:
$ docker run -d -P --name web -v /webapp training/webapp python app.py
注意: -P是将容器服务暴露的端口,是自动映射到本地主机的临时端口。
2.挂载一个主机目录作为数据卷
使用-v标记也可以指定挂载一个本地的已有目录到容器中去作为数据卷 (推荐方式)。
$ docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py
上面的命令加载主机的/ src/webapp目录到容器的/ opt/webapp目录。这个功能在进行测试的时候十分方便,比如用户可以将一些程序或数据放到本地目录中,然后在容器内运行和使用。另外,本地目录的路径必须是 绝对路径,如果目录不存在Docker,会自动创建。
Docker挂载数据卷的默认权限是读写(rw),用户也可以通过 ro指定为只读:
$ docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py
加了:ro 之后,容器内对所挂载数据卷内的数据就无法修改了。
3.挂载一个本地主机文件作为数据卷
-v标记也可以从主机挂载单个文件到容器中作为数据卷(不推荐)。
$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash 这样就可以记录在容器输入过的命令历史。
注意如果直接挂载一个文件到容器,使用文件编辑工具,包括vi或者sed--in- place的时候,可能会造成文件inode的改变,从Docker 1.1.0起,这会导致报错 误信息。所以推荐的方式是直接挂载文件所在的目录。
如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,但是它的目的是专门用来提供数据卷供其他容器挂载。
创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到 /dbdata:
$ docker run -it -v /dbdata --name dbdata ubuntu
root@3ed94f279b6f:/# ls
bin boot dbdata dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr
var
在其他容器中使用--volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:
$ docker run -it --volumes-from dbdata --name db1 ubuntu
$ docker run -it --volumes-from dbdata --name db2 ubuntu
容器db1和db2都挂载同一个数据卷到相同的 /dbdata 目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。
可以多次使用--volumes-from参数来从多个容器挂载多个数据卷。还可以从其他已经挂载了容器卷的容器来挂载数据卷。使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态。如果删除了挂载的容器(包括dbdata、db1和db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时 显式使用 docker rm-v 命令来指定同时删除关联的容器。
1.备份
使用下面的命令来备份dbdata数据卷容器内的数据卷:
$ docker run --volumes-from dbdata -v $(pwd):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdata
这个命令稍微有点复杂,具体分析一下。首先利用ubuntu镜像创建了一个容器worker。使用--volumes-from dbdata参数来让worker容器挂载dbdata容器的数据卷(即dbdata数据卷);
使用-v $(pwd):/backup参数 来挂载本地的当前目录到worker容器的/backup目录。
worker容器启动后,使用了tar cvf/backup/backup.tar/dbdata命令来将/ dbdata下内容备份为容器内的/ backup/backup.tar,即宿主主机当前目录下的backup.tar。
2.恢复
如果要将数据恢复到一个容器,可以按照下面的步骤操作。首先创建一个带有数据卷的容器dbdata2:
$ docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
然后创建另一个新的容器,挂载dbdata2的容器,并使用untar解压备份文件到所挂载的容器卷中:
$ docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar
多个容器之间有能够互相访问到对方的服务。除了通过网络访问外,Docker还提供了两个很方便的功能来满足服务访问的基本需求:一个是允许映射容器内应用的服务端口到本地宿主主机; 另 一个是互联机制实现多个容器间通过容器名来快速访问。
1.从外部访问容器应用
在启动容器的时候,如果不指定对应的参数,在容器外部是无法通过网络来访问容器内的网络应用和服务的。 当容器中运行一些网络应用,要让外部访问这些应用时,可以通过 -P 或 -p参数来指定端口映射。当使用-P(大写的)标记时,Docker会随机映射一个 49000~49900的端口到内部容器开放的网络端口:
$ docker run -d -P training/webapp python app.py
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bc533791f3f5 py_dem:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155->5000/tcp py_demo
此时,可以使用docker ps看到,本地主机的49155被映射到了容器的5000端口。访问宿主主机的49155端口即可访问容器内Web应用提供的界面。同样,可以通过docker logs命令来查看应用的信息:
$ docker logs -f nostalgic_morse
* Running on http://0.0.0.0:5000/
10.0.2.2 - - [23/May/2014 20:16:31] "GET / HTTP/1.1" 200 -
10.0.2.2 - - [23/May/2014 20:16:31] "GET /favicon.ico HTTP/1.1" 404 -
-p(小写的)可以指定要映射的端口,并且在一个指定端口上只可以绑定一个容器。支持的格式有
IP:HostPort: ContainerPort | IP : : ContainerPort | HostPort:ContainerPort。
2.映射所有接口地址
使用HostPort:ContainerPort格式将本地的5000端口映射到容器的5000端口,可以执行:
$ docker run -d -p 5000:5000 training/webapp python app.py
此时默认会绑定本地所有接口上的所有地址。多次使用 -p标记可以绑定多个端口。例如:
$ docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
3.映射到指定地址的指定端口
可以使用IP:HostPort:ContainerPort格式指定映射使用一个特定地址,比如localhost地址127.0.0.1:
$ docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
4.映射到指定地址的任意端口
使用IP::ContainerPort绑定localhost的任意端口到容器的5000端口,本地主机会自动分配一个端口:
$ docker run -d -p 127.0.0.1::5000 training/webapp python app.py
还可以使用udp标记来指定udp端口:
$ docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
5.查看映射端口配置
使用docker port命令来查看当前映射的端口配置,也可以查看到绑定的地址:
$ docker port py_demo 5000
127.0.0.1:49155.
注意: 容器有自己的内部网络和IP地址,使用docker inspect+容器ID可以获取容器的具体信息。
容器的互联(linking)是一种让多个容器中应用进行快速交互的方式。 它会在源和接收容器之间创建连接关系,接收容器可以通过容器名快速访问到源容器,而不用指定具体的IP地址。
1.自定义容器命名
连接系统依据容器的名称来执行。因此,首先需要定义一个好记的容器名字。 虽然当创建容器的时候,系统默认会分配一个名字,但自定义容器名字有两个好处:
使用--name标记可以为容器自定义命名:
$ docker run -d -P --name web test/demo python app.py
使用docker ps来验证设定的命名:
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aed84ee21bde test/demo:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154->5000/tcp web
也可以使用docker inspect来查看容器的名字: $ docker inspect -f "{{.Name}}" aed84ee21bde -----> /web
容器的名称是唯一的。如果已经命名了一个叫web的容器,当你要再次使用web这个名称的时候,需要先用docker rm来删除之前创建的同名容器。
在执行docker run的时候如果添加 --rm 标记,则容器在终止后会立刻删除。注意,--rm和 -d 参数不能同时使用。
2.容器互联
使用--link参数可以让容器之间安全地进行交互。 下面先创建一个新的数据库容器:
$ docker run -d --name db training/db2
删除之前创建的web容器: $ docker rm -f web 然后创建一个新的web容器,并将它连接到db容器:
$ docker run -d -P --name web --link db:db training/webapp python app.py
此时,db容器和web容器建立互联关系: --link参数的格式为 --link name:alias,其中name是要连接的容器名称,alias是这个连接的别名。使用docker ps来查看容器的连接,如下所示:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
349169744e49 training/db2:latest su postgres -c '/usr Up About a minute 5432/tcp db, web/db
aed84ee21bde training/webapp:latest python app.py Up 2 minute 0.0.0.0:49154->5000/tcp 16 hours ago web
Docker相当于在两个互联的容器之间创建了一个虚机通道,而且不用映射它们的端口到宿主主机上。在启动db容器的时候并没有使用 -p 和 -P 标记, 从而避免了暴露数据库服务端口到外部网络上。Docker通过两种方式为容器公开连接信息:
Docker容器服务访问的两大基本操作--基础的容器端口映射机制和 容器互联机制。同时,Docker目前可以成熟地支持Linux系统自带的网络服务和功能,这既可以利用现有成熟的技术提供稳定支持,又可以实现快速的高性能转发。
在生产环境中,网络方面的需求更加复杂多变,包括跨主机甚至跨数据中心的通信,这时候往往就需要引入额外的机制,例如SDN(软件定义网络) 或NFV(网络功能虚拟化)的相关技术。
Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。
Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。 一般而言,Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。例如:
# This Dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
# Base image to use, this must be set as the first line
FROM ubuntu
# Maintainer: docker_user (@docker_user)
MAINTAINER docker_user [email protected]
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx
其中,一开始必须指明所基于的镜像名称,接下来一般是说明维护者信 息。后面则是镜像操作指令,例如RUN指令,RUN指令将对镜像执行跟随的命 令。每运行一条RUN指令,镜像就添加新的一层,并提交。最后是CMD指令,用来指定运行容器时的操作命令。下面是Docker Hub上两个热门镜像的Dockerfile的例子,可以帮助读者对 Dockerfile结构有个基本的认识。
第一个例子是在debian:jessie基础镜像基础上安装Nginx环境,从而创建 一个新的nginx镜像:
FROM debian:jessie
MAINTAINER NGINX Docker Maintainers "[email protected]"
ENV NGINX_VERSION 1.10.1-1~jessie
RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC64107
9A6ABABF5BD827BD9BF62 \
&& echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/sources.list \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
ca-certificates \
nginx=${NGINX_VERSION} \
nginx-module-xslt \
nginx-module-geoip \
nginx-module-image-filter \
nginx-module-perl \
nginx-module-njs \
gettext-base \
&& rm -rf /var/lib/apt/lists/*
# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
第二个例子是基于buildpack-deps:jessie-scm基础镜像,安装Golang相关环境,制作一个GO语言的运行环境镜像:
FROM buildpack-deps:jessie-scm
# gcc for cgo
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
gcc \
libc6-dev \
make \
&& rm -rf /var/lib/apt/lists/*
ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd
7561275a87aeb
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
&& echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
&& tar -C /usr/local -xzf golang.tar.gz \
&& rm golang.tar.gz
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH
COPY go-wrapper /usr/local/bin/
1.FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认会去Docker Hub 下载指定镜像。格式为
FROM
,或FROM 。: ,或FROM @ 任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像,可以使用多个FROM指令(每个镜像一次)。
2.MAINTAINER
指定维护者信息,格式为MAINTAINER
。例如: MAINTAINER [email protected]
该信息会写入生成镜像的Author属性域中。
3.RUN
运行指定命令。 格式为RUN
或 RUN["executable","param1","param2"] 。注意,后一个指令会被解析为Json数组,因此必须用双引号。 前者默认将在shell终端中运行命令,即/ bin/sh-c;后者则使用exec执行,不会启动shell环境。 指定使用其他终端类型可以通过第二种方式实现,例如RUN["/bin/bash","-c","echo hello"]。 每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用 \ 来换行。例如:
RUN apt-get update \ && apt-get install -y libsnappy-dev zlib1g-dev libbz2-dev \ && rm -rf /var/cache/apt
4.CMD
CMD指令用来指定启动容器时默认执行的命令。它支持三种格式:
- ·CMD["executable","param1","param2"]使用 exec执行,是推荐使用的方式;
- ·CMD command param1 param2在/bin/sh中执行,提供给需要交互的应用;
- ·CMD["param1","param2"]提供给 ENTRYPOINT的默认参数。
每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一 条会被执行。如果用户启动容器时手动指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。
5.LABEL
LABEL指令用来指定生成镜像的元数据标签信息。 格式为LABEL
= = = ... LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
6.EXPOSE
声明镜像内服务所监听的端口。 格式为EXPOSE
[ ...]。 例如: EXPOSE 22 80 8443 注意,该指令只是起到声明作用,并不会自动完成端口映射。在启动容器时需要使用-P,Docker主机会自动分配一个宿主机的临时端 口转发到指定的端口;使用-p,则可以具体指定哪个宿主机的本地端口会映射过来。
7.ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动 的容器中也会存在。格式为ENV
例如: 或ENV = ... ENV PG_MAJOR 9.3 ENV PG_VERSION 9.3.4 RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/ postgress && ... ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
指令指定的环境变量在运行时可以被覆盖掉,如docker run --env
= built_image。 8.ADD
该命令将复制指定的
路径下的内容到容器中的 路径下。 格式为ADD 其中
可以是Dockerfile所在目录的一个相对路径(文件或目录),也 可以是一个URL,还可以是一个tar文件(如果为tar文件,会自动解压到 路径下)。 可以是镜像内的绝对路径,或者相对于工作目录 (WORKDIR)的相对路径。 路径支持正则格式,例如: ADD *.c /code/
9.COPY
格式为COPY
。 复制本地主机的 (为Dockerfile所在目录的相对路径、文件或目录)下的内容到镜像中的 下。目标路径不存在时,会自动创建。路径同样支持正则格式。当使用本地目录为源目录时,推荐使用COPY。 10.ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执 行,所有传入值作为该命令的参数。 支持两种格式:
- ENTRYPOINT ["executable", "param1", "param2"](exec调用执行);
- ENTRYPOINT command param1 param2(shell中执行)。
此时,CMD指令指定值将作为根命令的参数。 每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个有效。在运行时,可以被-- entrypoint参数覆盖掉,如docker run--entrypoint。
11.VOLUME
创建一个数据卷挂载点。格式为VOLUME ["/data"]。 可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。
12.USER
指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份。格式为USER daemon。 当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户。例如:
RUN groupadd -r postgres && useradd -r -g postgres postgres
要临时获取管理员权限可以使用gosu或sudo。
13.WORKDIR
为后续的RUN、CMD和 指令配置工作目录。
ENTRYPOINT 格式为WORKDIR/path/to/workdir。可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
则最终路径为 /a/b/c。
14.ARG
指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行 docker build命令时才以-- build-arg
= 格式传入。格式为ARG [= 。则可以用docker build--build-arg] = .来指定参数值。 15.ONBUILD
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令。格式为ONBUILD[INSTRUCTION]。 例如,Dockerfile使用如下的内容创建了镜像 image-A:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A 指定基础镜像,会自动执行ONBUILD指令的内容,等价于在后面添加了两条 指令:
FROM image-A #Automatically run the following ADD . /app/src RUN /usr/local/bin/python-build --dir /app/src
使用ONBUILD指令的镜像,推荐在标签中注明,例如ruby:1.9- onbuild。
16.STOPSIGNAL
指定所创建镜像启动的容器接收退出的信号值。例如: STOPSIGNAL signal
17.HEALTHCHECK
配置所启动容器如何进行健康检查(如何判断健康与否),自Docker 1.12开始支持。格式有两种:
- HEALTHCHECK[OPTIONS]CMD command:根据所执行命令返回值是否 为0来判断;
- HEALTHCHECK NONE:禁止基础镜像中的健康检查。
OPTION支持: ·--interval=DURATION(默认为:30s):过多久检查一次; ·--timeout=DURATION(默认为:30s):每次检查等待结果的超时; ·--retries=N(默认为:3):如果失败了,重试几次才最终确定失败。
18.SHELL
指定其他命令使用shell时的默认shell类型。 默认值为["/bin/sh","-c"]。
注意: 对于Windows系统,建议在Dockerfile开头添加#escape=`来指定转义信 息。
编写完成Dockerfile之后,可以通过docker build命令来创建镜像。
基本的格式为docker build[选项]内容路径,该命令将读取指定路径下 (包括子目录)的Dockerfile,并将该路径下的所有内容发送给 Docker服务端,由服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置 Dockerfile的目录为空目录。有两点经验:
- 如果使用非内容路径下的Dockerfile,可以通过 -f 选项来指定其路径。
- 要指定生成镜像的标签信息,可以使用 -t 选项。
例如,指定Dockerfile所在路径为/ tmp/docker_builder/,并且希望生成 镜像标签为build_repo/first_image,可以使用下面的命令:
$ docker build -t build_repo/first_image /tmp/docker_builder/
使用.dockerignore文件 可以通过.dockerignore文件(每一行添加一条匹配模式)来让 Docker忽略匹配模式路径下的目录和文件。例如:
# comment
*/temp*
*/*/temp*
tmp?
~*
建议读者在生成镜像过程 中,尝试从如下角度进行思考,完善所生成的镜像。
- 精简镜像用途: 尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
- 选用合适的基础镜像: 过大的基础镜像会造成生成臃肿的镜像,一般推 荐较为小巧的debian镜像;
- 提供足够清晰的命令注释和维护者信息: Dockerfile也是一种代码,需要 考虑方便后续扩展和他人使用;
- 正确使用版本号: 使用明确的版本号信息,如1.0,2.0,而非latest, 将避免内容不一致可能引发的惨案;
- 减少镜像层数: 如果希望所生成镜像的层数尽量少,则要尽量合并指 令,例如多个RUN指令可以合并为一条;
- 及时删除临时文件和缓存文件: 特别是在执行apt-get指令后,/var/cache/ apt下面会缓存一些安装包;
- 提高生成度: 如合理使用缓存,减少内容目录下的文件,或使 用.dockerignore文件指定等;
- 调整合理的指令顺序: 在开启缓存的情况下,内容不变的指令尽量放在 前面,这样可以尽量复用;
- 减少外部源的干扰: 如果确实要从外部引入数据,需要指定持久的地 址,并带有版本信息,让他人可以重复而不出错。
第九章只是针对这本书中涉及到的做个简单的简介,具体的内容以及想深入了解可以自行学习。
目前常用的Linux发行版主要包括Debian/Ubuntu系列和CentOS/Fedora系列。前者以自带软件包版本较新而出名;后者则宣称运行更稳定一些。选择哪个操作系统取决于读者的具体需求。同时,社区还推出了完全基于Docker 的Linux发行版CoreOS。 使用Docker,只需要一个命令就能快速获取一个Linux发行版镜像,这是以往包括各种虚拟化技术都难以实现的。这些镜像一般都很精简,但是可以支持完整Linux系统的大部分功能。带有OFFICIAL标记说明是官方镜像。
3.2 Ubuntu:是一个以桌面应用为主的GNU/Linux操作系统,与Debian的不同在于它每6个月会发布一个新版本,每2年会推
出一个长期支持(LongTerm Support,LTS)版本,一般支持3年。
BusyBox是一个集成了一百多个最常用Linux命令和工具(如 cat、echo、grep、mount、telnet等)的精简工具箱,它只有几 MB的大小, 很方便进行各种快速验证,被誉为“Linux系统的瑞士军刀”。BusyBox可运 行于多款POSIX环境的操作系统中,如Linux(包括 Android)、Hurd、FreeBSD等。
$ docker pull busybox:latest
$ docker run –it busybox
Alpine操作系统是一个面向安全的轻型Linux发行版。它不同于通常的 Linux发行版,Alpine采用了musl libc和BusyBox以减小系统的体积和运行时资源消耗,但功能上比BusyBox又完善得多,因此得到开源社区越来越多的青 睐。在保持瘦身的同时,Alpine还提供了自己的包管理工具apk,可以通过https://pkgs.alpinelinux.org/packages查询包信息,也可以通过apk命令直接查 询和安装各种软件。Alpine Docker镜像也继承了Alpine Linux发行版的这些优势。相比于其他 Docker镜像,它的容量非常小,仅仅只有5MB左右(Ubuntu系列镜像接近 200MB),且拥有非常友好的包管理机制。官方镜像来自docker-alpine项目。
Debian/Ubuntu:Debian和Ubuntu都是目前较为流行的Debian系的服务器操作系统,十分适合研发场景。Docker Hub上提供了官方镜像,国内各大容器云服务也基本 都提供了相应的支持。
3.1 Debian系统
Debian是由GPL和其他自由软件许可协议授权的自由软件组成的操作系 统,由Debian Project组织维护。Debian计划是一个独立、分散的组织,由 3000个志愿者组成,接受世界多个非盈利组织的资金支持,Software in the Public Interest提供支持并持有商标作为保护机构。Debian以其坚守Unix和自 由软件的精神,以及给予用户的众多选择而闻名。现在Debian包括了超过 25000个软件包并支持12个计算机系统结构。
作为一个大的系统组织框架,Debian下面有多种不同操作系统核心的分 支计划,主要为采用Linux核心的Debian GNU/Linux系统,其他还有采用GNU Hurd核心的Debian GNU/Hurd系统、采用FreeBSD核心的Debian GNU/ kFreeBSD系统,以及采用NetBSD核心的Debian GNU/NetBSD系统,甚至还有 利用Debian的系统架构和工具,采用OpenSolaris核心构建而成的Nexenta OS系 统。在这些Debian系统中,以采用Linux核心的Debian GNU/Linux最为著名。众多的Linux发行版,例如Ubuntu、Knoppix和Linspire及Xandros等,都基 于Debian GNU/Linux。
CentOS:(Community Enterprise Operating System,社区企业操作系统)是基于Red Hat Enterprise Linux源代码编译而成的。由于CentOS与Redhat Linux 源于相同的代码基础,所以很多成本敏感且需要高稳定性的公司就使用 CentOS来替代商业版Red Hat Enterprise Linux。CentOS自身不包含闭源软件。
Fedora :Fedora是由Fedora Project社区开发,红帽公司赞助的Linux发行版。它的目标是创建一套新颖、多功能并且自由和开源的操作系统。对用户而言,Fedora是一套功能完备的、可以更新的免费操作系统,而对赞助商Red Hat而言,它是许多新技术的测试平台,被认为可用的技术最终会加入到Red Hat Enterprise Linux中。
$ docker run -it centos[Fedora] bash
比如attach、exec等进入容器的办法命令, 但这些命令都无法解决远程管理容器的问题。因此,当读者需要远程登录到容器内进行一些操作的时候,就需要SSH的支持了。 详情下载PDF查看第10章的内容:
Apache是一个高稳定性的、商业级别的开源Web服务器。目前Apache已经是世界使用排名第一的Web服务器软件。由于其良好的跨平台和安全性,Apache被广泛应用在多种平台和操作系统上。作为Apache软件基金会支 持的项目,它的开发者社区完善而高效。自1995年发布至今,一直以高标准 进行维护与开发。Apache名称源自美国的西南部一个印第安人部落:阿帕奇 族,它支持类UNIX和Windows系统。
Nginx是一款功能强大的开源反向代理服务器,支持 HTTP、HTTPS、SMTP、POP3、IMAP等协议。它也可以作为负载均衡器、HTTP缓存或Web服务器。Nginx一开始就专注于高并发和高性能的应用场景。它使用类BSD开源协议,支持Linux、BSD、Mac、Solaris、AIX等类Unix系统,同时 也有Windows上的移植版本。
Tomcat是由Apache软件基金会下属的Jakarta项目开发的一个Servlet容 器,按照Sun Microsystems提供的技术规范,实现了对Servlet和Java Server Page(JSP)的支持。同时,它提供了作为Web服务器的一些特有功能,如Tomcat管理和控制平台、安全域管理和Tomcat阀等。由于Tomcat本身也内含 了一个HTTP服务器,也可以当作一个单独的Web服务器来使用。下面介绍如何定制Tomcat镜像。
Jetty是一个优秀的开源Servlet容器,以其高效、小巧、可嵌入式等优点深得人心,它为基于Java的Web内容(如JSP和Servlet)提供运行环境。Jetty 基于Java语言编写,它的API以一组JAR包的形式发布。开发人员可以将Jetty 容器实例化成一个对象,可以迅速为一些独立运行的Java应用提供Web服务。
LAMP(Linux-Apache-MySQL-PHP)是目前流行的Web工具栈,其中包 括:Linux操作系统,Apache网络服务器,MySQL数据库,Perl、PHP或者 Python编程语言。其组成工具均是成熟的开源软件,被大量网站所采用。和 Java/J2EE架构相比,LAMP具有Web资源丰富、轻量、快速开发等特点;和微软的.NET架构相比,LAMP更具有通用、跨平台、高性能、低价格的优势。因 此LAMP无论是在性能、质量还是价格方面都是企业搭建网站的首选平台。
CMS:内容管理系统(Content Management System,CMS)指的是提供内容编辑服务的平台程序。CMS可以让不懂编程的用户方便又轻松地发布、更改和管理 各类数字内容(主要以文本和图像为主)。
Ghost是一个广受欢迎的开源博客平台,使用JavaScript编写,以MIT协议 发布。它的设计非常简约,使用起来体验优异,非常适合做内容发布,故而 受到很多极客或技术工作者的喜爱。
WordPress是风靡全球的开源内容管理系统,是博客、企业官网、产品首 页等内容相关平台的主流实现方案之一。类似项目还有 Drupal、Joomla、Typo3等。WordPress基于PHP和MySQL,架构设计简单明了,支持主题,插件和各种 功能模块。更重要的是,WordPress拥有庞大的社区,在线资源非常丰富,并 且在各大网络空间商和云平台中受到广泛的支持。根据2013年8月的统计数 据,流量排名前一千万的网站中其使用率高达22%。
持续集成(Continuous integration,CI)正是针对这类问题的一种开 发实践,它倡导开发团队定期进行集成验证。集成通过自动化的构建来完 成,包括自动编译、发布和测试,从而尽快地发现错误。CI所描述的软件开发是从原始需求识别到最终产品部署整个过程中,需求以小批量形式在团队的各个角色间顺畅流动,能够以较短地周期完成需求的小粒度频繁交付。整个过程中,需求分析、产品的用户体验和交互设计、开发、测试、运维等角 色需要密切协作。
持续集成特点包括:从检出代码、编译构建、运行测试、结果记录、测试统计等都是自动完成的,减少人工干预。需要有持续集成系统的支持,包 括代码托管机制支持,以及集成服务器等。 持续交付(Continuous delivery,CD)则是经典的敏捷软件开发方法的 自然延伸,它强调产品在修改后到部署上线的流程要敏捷化、自动化。甚至 一些较小的改变也要今早的部署上线,这跟传统软件在较大版本更新后才上线的思想不同。
Gitlab是一款非常强大的开源源码管理系统。它支持基于Git的源码管 理、代码评审、issue跟踪、活动管理、wiki页面,持续集成和测试等功能。 基于Gitlab,用户可以自己搭建一套类似 Github的开发协同平台。
目前,主流数据库包括关系型(SQL)和非关系型(NoSQL)两种。在使用数据库容器时,建议将数据库文件映射到宿主主机,一方面减少容器文件系统带来的性能损耗,另一方面实现数据的持久化。
关系数据库是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据,支持复杂的事物处理和结构化查询。代 表实现有MySQL、Oracle、PostGreSQL、MariaDB、SQLServer等。
非关系数据库是新兴的数据库技术,它放弃了传统关系型数据库的部分强一致性限制,带来性能上的提升,使其更适用于需要大规模并行处理的场景。非关系型数据库是关系型数据库的良好补充,代表产品有 MongoDB、Redis、CouchDB等。
MongoDB是一款可扩展、高性能的开源文档数据库,是当今最流行的 NoSQL数据库软件之一。它采用C++开发,支持复杂的数据类型和强大的查 询语言,提供了关系数据库的绝大部分功能。由于MongoDB高性能、易部 署、易使用等特点,已经在很多领域都得到了广泛的应用。mongodb的默认服务端口:27017
MySQL是全球最流行的开源的开源关系数据库软件之一,因为其高性 能、成熟可靠和适应性而得到广泛应用。MySQL目前在不少大规模网站和应用 中被使用,比如Facebook、Twitter和Yahoo!等。
Redis是一个开源(BSD许可)的基于内存的数据结构存储系统,可以用 作数据库、缓存和消息中间件。
CouchDB是一款面向文档的NoSQL数据库,以JSON格式存储数据。它兼 容ACID,可以用于存储网站的数据与内容,以及提供缓存等。CouchDB里文档 域(Field)都是以键值对的形式存储的,对数据的每次修改都会得到一个新 的文档修订号。CouchDB侧重于AP(可用性和分区容忍度)。相比之下,MongoDB侧重于 CP(一致性和分区容忍度),Neo4j则提供了特有的面向图形的结构。
Cassandra是个开源(Apache License 2.0)的分布式数据库,支持分散的 数据存储,可以实现容错以及无单点故障等。Cassandra在设计上引入了P2P 技术,具备大规模可分区行存储能力,并支持Spark、Storm、Hadoop的集 成。目前Facebook、Twitter、Instagram、eBay、Github、Reddit、Netflix 等多家公司都在使用Cassandra。类似工具还有HBase等。
Memcached是一个高性能、分布式的开源内存对象缓存系统。最初是Danga Interactive为了优化LiveJournal的访问速度而编写的。目前已经非常广 泛的应用于各种Web应用中。以BSD license授权协议发布。Memcached守护进程基于C语言实现,基于libevent的事件处理可以实现 很高的性能。需要注意的是,由于数据仅存在于内存中,因此重启 Memcached或重启操作系统会导致数据全部丢失。
RabbitMQ是一个支持Advanced Message Queuing Protocol(AMQP)的开源消息队列实现,由Erlang编写,因以高性能、高可用以及可伸缩性出名。它支持多种客户端,如:Java、Python、PHP、.NET、Ruby、JavaScript等。它主要用于在分布式系统中存储和转发消息,方便组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP架构中有两个主要组件:Exchange和Queue,两者都在服务端,又称Broker,由RabbitMQ实现的。客户端通常有Producer和Consumer两种类型。在使用RabbitMQ过程中需要注意的是,它将数据存储在Node中,默认情 况为hostname。用户使用rabbitmqctl工具进行远程管理,或跨容器管理的时候,会需要设置持久化的cookie。如果需要了解关于Erlang Cookie的信息,可以参见 RabbitMQ官网的集群指南。
除了通用的消息队列外,任务队列在分布式处理中也十分重要。任务队列的输入是工作的一个单元,称为任务,有多个工作者监听队列来获取任务 并执行。Celery是一个简单、灵活、高可用、高性能的开源(BSD许可)分布式任务处理系统,专注于实时处理的任务队列管理,同时也支持任务调 度。Celery基于Python实现,跟包括Django、Pyramid、Pylons、Flask、Tornado等Web框架都无缝集成,有庞大 的用户与贡献者社区。Celery可以单机运行,也可以在多台机器上运行,甚至可以跨越数据中心运行。
作为当今大数据处理领域的经典分布式平台,Apache Hadoop主要基于 Java语言实现,由三个核心子系统组成:HDFS、YARN、MapReduce,其 中,HDFS是一套分布式文件系统;YARN是资源管理系统,MapReduce是运行 在YARN上的应用,负责分布式处理管理。如果从操作系统的角度看,HDFS 相当于Linux的ext3/ext4文件系统,而Yarn相当于Linux的进程调度和内存分配模块。
Apache Spark是一个围绕速度、易用性和复杂分析构建的大数据处理框 架,基于Scala开发。最初在2009年由加州大学伯克利分校的AMPLab开发,并于2010年成为Apache的开源项目之一。与Hadoop和Storm等其他大数据和MapReduce技术相比,Spark支持更灵 活的函数定义,可以将应用处理速度提升一到两个数量级,并且提供了众多 方便的实用工具,包括SQL查询、流处理、机器学习和图处理等: Spark体系架构包括如下三个主要组件:数据存储、API、管理框架。
Apache Storm是一个实时流计算框架,由Twitter在2014年正式开源,遵循 Eclipse Public License 1.0。Storm基于Clojure等语言实现。Storm集群与Hadoop集群在工作方式上十分相似,唯一区别在于Hadoop 上运行的是MapReduce任务,在Storm上运行的则是topology。MapReduce任务完成处理即会结束,而topology则永远在等待消息并处理(直到被停止)。
Elasticsearch是一个基于Lucene的开源搜索服务器,主要基于Java实现。 它提供了一个分布式的,多租户的全文搜索引擎,内含RESTful web接口。Elasticsearch提供了实时的分布式数据存储和分析查询功能,很容易扩展 到上百台服务器,支持处理PB级结构化或非结构化数据。配合 Logstash、Kibana等组件,可以快速构建一套对日志消息的分析平台。