第2章 Docker的核心概念和安装
本章首先介绍Docker的三大核心概念:
·镜像(Image)
·容器(Container)
·仓库(Repository)
读者理解了这三个核心概念,就能顺利地理解Docker的整个生命周期。社区讨论很激烈的一个话题,就是Docker和Linux容器技术到底有何区别?相信读者在阅读完本章后,会得到更清晰的答案。
随后,笔者将介绍如何在常见的操作系统上安装Docker,包括Ubuntu、CentOS、Windows和MacOS等。
2.1 核心概念
Docker镜像
Docker镜像(Image)类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统。
例如:一个镜像可以只包含一个完整的Ubuntu操作系统环境,可以把它称为一个Ubuntu镜像。镜像也可以安装了Apache应用程序(或用户需要的其他软件),可以把它称为一个Apache镜像。
镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的应用镜像,并通过简单的命令就可以直接使用。
Docker容器
Docker容器(Container)类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。
容器是从镜像创建的应用运行实例,可以将其启动、开始、停止、删除,而这些容器都是相互隔离、互不可见的。
读者可以把容器看做一个简易版的Linux系统环境(这包括root用户权限、进程空间、用户空间和网络空间等),以及运行在其中的应用程序打包而成的应用盒子。
镜像自身是只读的。容器从镜像启动的时候,Docker会在镜像的最上层创建一个可写层,镜像本身将保持不变。
Docker仓库
Docker仓库(Repository)类似于代码仓库,是Docker集中存放镜像文件的场所。
有时候会看到有资料将Docker仓库和注册服务器(Registry)混为一谈,并不严格区分。实际上,注册服务器是存放仓库的地方,其上往往存放着多个仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。例如存放Ubuntu操作系统镜像的仓库,称为Ubuntu仓库,其中可能包括14.04、12.04等不同版本的镜像。仓库注册服务器的示例如图2-1所示。
根据所存储的镜像公开分享与否,Docker仓库可以分为公开仓库(Public)和私有仓库(Private)两种形式。
目前,最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供稳定的国内访问。
当然,用户如果不希望公开分享自己的镜像文件,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库。
当用户创建了自己的镜像之后就可以使用push命令将它上传到指定的公有或者私有仓库。这样用户下次在另外一台机器上使用该镜像时,只需将其从仓库上pull下来就可以了。
注意 可以看出,Docker利用仓库管理镜像的设计理念与Git非常相似。
2.2 安装Docker
Docker支持在主流的操作系统平台上使用,包括Ubuntu、CentOS、Windows以及MacOS系统等。当然,在Linux系列平台上是原生支持,使用体验也最好。
Ubuntu
1.Ubuntu 14.04及以上版本
Ubuntu 14.04版本官方软件源中已经自带了Docker包,可以直接安装:
$ sudo apt-get update $ sudo apt-get install -y docker.io $ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker $ sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io以上流程使用Ubuntu 14.04系统默认自带docker.io安装包安装Docker,这样安装的Docker版本相对较旧。
读者也可通过下面的方法从Docker官方源安装最新版本。首先需要安装apt-transport-https,并添加Docker官方源:
$ sudo apt-get install apt-transport-https $ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 $ sudo bash -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list" $ sudo apt-get update之后,可以通过下面的命令来安装最新版本的Docker:
$ sudo apt-get install -y lxc-docker
在安装了Docker官方软件源后,若需要更新Docker软件版本,只需要执行以下命令即可升级:
$ sudo apt-get update -y lxc-docker注意 后文中使用$作为终端引导符时,表示非root权限用户;#代表是root用户。
2.ubuntu 14.04以下的版本
如果使用的是较低版本的Ubuntu系统,则需要先进行内核更新并重启系统后再进行安装:
$ sudo apt-get update
$ sudo apt-get install -y linux-image-generic-lts-raring linux-headers-generic-lts-raring
$ sudo reboot
重启后,重复在Ubuntu 14.04系统的安装步骤即可。
CentOS
Docker支持CentOS 6及以后的版本。
对于CentOS 6系统可使用EPEL库安装Docker,命令如下:
$ sudo yum install -y http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm
$ sudo yum install -y docker-io
对于CentOS 7系统,由于CentOS-Extras源中已内置Docker,读者可以直接使用yum命令进行安装:
$ sudo yum install -y docker
目前在Centos系统中更新Docker软件有两种方法,一是自行通过源码编译安装,二是下载二进制文件进行更新。
Windows
目前Docker官方已经宣布Docker通过虚拟机方式支持Windows 7.1和8,前提是主机的CPU支持硬件虚拟化。由于近几年发布的Intel和AMD CPU基本上都已支持了硬件虚拟化特性,因此在
Windows中使用Docker通常不会有硬件支持的问题。
由于Docker引擎使用了Linux内核特性,所以在Windows上运行的话,需要额外使用一个虚拟机来提供Linux支持。这里推荐使用Boot2Docker工具,它会首先安装一个经过加工与配置的VirtualBox
轻量级虚拟机,然后在其中运行Docker。主要步骤如下:
1)从https://docs.docker.com/installation/windows/下载最新官方Docker for Windows Installer。
2)运行Installer。这个过程将安装VirtualBox,MSYS-git,boot2docker Linux ISO镜像,以及Boot2Docker管理工具。如图2-2所示。
3)打开桌面的Boot2Docker Start程序,或者用以下命令:Program Files>Boot2Docker for Windows。此初始化脚本在第一次运行时需要输入一个SSH Key Passphrase(用于SSH密钥生成的口令)。读者可以自行设定,也可以直接按回车键,跳过此设定,如图2-3所示。
此时Boot2Docker Start程序将连接至虚拟机中的Shell会话,Docker已经运行起来了!
Mac OS
目前Docker已经支持Mac OS X 10.6Snow Leopard及以上版本的Mac OS。
在Mac OS上使用Docker,同样需要Boot2Docker工具的支持。主要步骤如下:
1)下载最新官方Docker for OS X Installer。读者可以从https://docs.docker.com/installation/mac/下载。
2)双击运行安装包。这个过程将安装一个VirtualBox虚拟机、Docker本身以及Boot2Docker管理工具,如图2-4所示。
3)安装成功后,找到Boot2Docker(Mac系统的Application或“应用”文件夹中)并运行它。现在进行Boot2Docker的初始化:
$ boot2docker init $ boot2docker start $ $(boot2docker shellinit)
读者将看到虚拟机在命令行窗口中启动运行,并显示Docker的启动信息,则说明Docker安装成功。当虚拟机初始化完毕后,可以使用boot2docker stop和boot2docker start来控制它。
注意:如果在命令行中看到如下提示信息:
To connect the Docker client to the Docker daemon, please set: export DOCKER_HOST=tcp://192.168.59.103:2375
可以执行提示信息中的语句:export DOCKER_HOST=tcp://192.168.59.103:2375。此语句的作用是在系统环境变量中设置Docker的主机地址。
2.3 本书环境介绍
本书的实践环境是一台装有Linux Mint 17的笔记本电脑,并使用虚拟机软件VirturBox虚拟了一套Ubuntu 14.04系统,两套系统上都安装了Docker的1.3版本,虚拟机通过VirturBox网络的NAT方式连接到外部,如图2-5所示。
其中,Ubuntu 14.04虚拟机将是主要的操作环境(自动获取的IP地址为10.0.2.15/24),而笔记本上装的Linux Mint环境(内网地址为10.0.2.2/24,外网地址为192.168.1.0/24段地址)将作为本地私有仓库的服务器,演示跟仓库相关的操作。
读者可根据自己本地环境,选择搭建类似的环境。
2.4 本章小结
本章介绍了Docker的三大核心概念:镜像、容器和仓库。
通过这三大核心概念所构建的高效工作流程,毫无疑问,正是Docker得以从众多容器虚拟化方案中脱颖而出的重要原因。
熟悉Git和GitHub的读者,会理解这一工作流程为文件分发和合作所带来的众多优势。在后续章节,笔者将进一步地介绍围绕这三大核心概念的Docker常见操作命令。
第3章 镜像
镜像是Docker的三大核心概念之一。
Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。
本章将介绍围绕镜像这一核心概念的具体操作,包括如何使用pull命令从Docker Hub仓库中下载镜像到本地;如何查看本地已有的镜像信息;如何在远端仓库使用search命令进行搜索和过滤;如何删除镜像标签和镜像文件;如何创建用户定制的镜像并且保存为外部文件。最后,还将介绍如何向Docker Hub仓库中推送自己的镜像。
3.1 获取镜像
镜像是Docker运行容器的前提。
读者可以使用docker pull命令从网络上下载镜像。该命令的格式为docker pull NAME[:TAG]。对于Docker镜像来说,如果不显式地指定TAG,则默认会选择latest标签,即下载仓库中最新版本的镜像。
下面,笔者将演示如何从Docker Hub的Ubuntu仓库下载一个最新的Ubuntu操作系统的镜像。
$ sudo docker pull ubuntu ubuntu:latest: The image you are pulling has been verified d497ad3926c8: Downloading [======> ] 25.41 MB/201.6 MB 51m14s ccb62158e970: Download complete e791be0477f2: Download complete 3680052c0f5c: Download complete 22093c35d77b: Download complete 5506de2b643b: Download complete 511136ea3c5a: Download complete该命令实际上下载的就是ubuntu:latest镜像,目前最新的14.04版本的镜像。
下载过程中可以看出,镜像文件一般由若干层组成,行首的2185fd50e2ca这样的字串代表了各层的ID。下载过程中会获取并输出镜像的各层信息。层(Layer)其实是AUFS(Advanced Union File
System,一种联合文件系统)中的重要概念,是实现增量保存与更新的基础。
读者还可以通过指定标签来下载特定版本的某一个镜像,例如14.04标签的镜像。
$ sudo docker pull ubuntu: 14.04
上面两条命令实际上都相当于$sudo docker pull registry.hub.docker.com/ubuntu:latest命令,即从默认的注册服务器registry.hub.docker.com中的ubuntu仓库来下载标记为latest的镜像。
用户也可以选择从其他注册服务器的仓库下载。此时,需要在仓库名称前指定完整的仓库注册服务器地址。例如从DockerPool社区的镜像源dl.dockerpool.com下载最新的Ubuntu镜像。
$ sudo docker pull dl.dockerpool.com:5000/ubuntu
下载镜像到本地后,即可随时使用该镜像了,例如利用该镜像创建一个容器,在其中运行bash应用。
$ sudo docker run -t -i ubuntu /bin/bash
root@fe7fc4bd8fc9:/#
3.2 查看镜像信息
使用docker images命令可以列出本地主机上已有的镜像。
例如,下面的命令列出了本地刚从官方下载的ubuntu:14.04镜像,以及从DockerPool镜像源下载的ubuntu:latest镜像。
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 14.04 5506de2b643b 1 weeks ago 197.8 MB
dl.dockerpool.com:5000/ubuntu latest 5506de2b643b 1 weeks ago 197.8 MB
在列出信息中,可以看到几个字段信息:
·来自于哪个仓库,比如ubuntu仓库。
·镜像的标签信息,比如14.04。
·镜像的ID号(唯一)。
·创建时间。
·镜像大小。
其中镜像的ID信息十分重要,它唯一标识了镜像。
TAG信息用于标记来自同一个仓库的不同镜像。例如ubuntu仓库中有多个镜像,通过TAG信息来区分发行版本,包括10.04、12.04、12.10、13.04、14.04等标签。
为了方便在后续工作中使用这个镜像,还可以使用docker tag命令为本地镜像添加新的标签。例如添加一个新的ubuntu:latest镜像标签如下:
$ sudo docker tag dl.dockerpool.com:5000/ubuntu:latest ubuntu:latest
再次使用docker images列出本地主机上镜像信息,可以看到多了一个ubuntu:latest标签的镜像。
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu 14.04 5506de2b643b 1 weeks ago 197.8 MB dl.dockerpool.com:5000/ubuntu latest 5506de2b643b 1 weeks ago 192.8 MB ubuntu latest 5506de2b643b 1 weeks ago 192.8 MB细心的读者可能会注意到,这些不同标签的镜像的ID是完全一致的,说明它们实际上指向了同一个镜像文件,只是别名不同而已。标签在这里起到了引用或快捷方式的作用。
使用docker inspect命令可以获取该镜像的详细信息。
$ sudo docker inspect 5506de2b643b [{ "Architecture": "amd64", "Author": "", "Comment": "", "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "/bin/bash" ], "CpuShares": 0, "Cpuset": "", "Domainname": "", "Entrypoint": null, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "ExposedPorts": null, "Hostname": "065262ce3c91", "Image":"964692831e07f7362f5c3fedf0c4b81a622f2c6e3ec5f19d0eddff21afd64c12", "Memory": 0, "MemorySwap": 0, "NetworkDisabled": false, "OnBuild": [], "OpenStdin": false, "PortSpecs": null, "StdinOnce": false, "Tty": false,"User": "", "Volumes": null, "WorkingDir": "" }, "Container":"f26bc14cc07412402bdab911b8a935fead0322649cf042cee8515c02ebdfa53a", "ContainerConfig": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "/bin/sh", "-c", "#(nop) CMD [/bin/bash]" ], "CpuShares": 0, "Cpuset": "", "Domainname": "", "Entrypoint": null, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "ExposedPorts": null, "Hostname": "065262ce3c91", "Image":"964692831e07f7362f5c3fedf0c4b81a622f2c6e3ec5f19d0eddff21afd64c12", "Memory": 0, "MemorySwap": 0, "NetworkDisabled": false, "OnBuild": [], "OpenStdin": false, "PortSpecs": null, "StdinOnce": false, "Tty": false, "User": "", "Volumes": null, "WorkingDir": "" }, "Created": "2014-09-23T22:37:05.812213629Z", "DockerVersion": "1.2.0", "Id": "53bf7a53e8903fce40d24663901aac6211373a8d8b4effe08bc884e63e181805", "Os": "linux", "Parent":"964692831e07f7362f5c3fedf0c4b81a622f2c6e3ec5f19d0eddff21afd64c12", "Size": 0 }]ocker inspect命令返回的是一个JSON格式的消息,如果我们只要其中一项内容时,可以使用-f参数来指定,例如,获取镜像的Architecture信息:
$ sudo docker inspect -f {{".Architecture"}} 550
amd64
在指定镜像ID的时候,通常使用该ID的前若干个字符组成的可区分字串来替代完整的ID。