第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 安装DockerDocker支持在主流的操作系统平台上使用包括Ubuntu、CentOS、Windows以及MacOS系统等。当然在Linux系列平台上是原生支持使用体验也最好。Ubuntu1.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系统的安装步骤即可。CentOSDocker支持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。这个过程将安装VirtualBoxMSYS-gitboot2docker Linux ISO镜像以及Boot2Docker管理工具。如图2-2所示。3打开桌面的Boot2Docker Start程序或者用以下命令Program FilesBoot2Docker 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安装成功后找到Boot2DockerMac系统的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_HOSTtcp://192.168.59.103:2375可以执行提示信息中的语句export DOCKER_HOSTtcp://192.168.59.1032375。此语句的作用是在系统环境变量中设置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该命令实际上下载的就是ubuntulatest镜像目前最新的14.04版本的镜像。下载过程中可以看出镜像文件一般由若干层组成行首的2185fd50e2ca这样的字串代表了各层的ID。下载过程中会获取并输出镜像的各层信息。层Layer其实是AUFSAdvanced Union FileSystem一种联合文件系统中的重要概念是实现增量保存与更新的基础。读者还可以通过指定标签来下载特定版本的某一个镜像例如14.04标签的镜像。$ sudo docker pull ubuntu 14.04上面两条命令实际上都相当于$sudo docker pull registry.hub.docker.com/ubuntulatest命令即从默认的注册服务器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/bashrootfe7fc4bd8fc9:/#3.2 查看镜像信息使用docker images命令可以列出本地主机上已有的镜像。例如下面的命令列出了本地刚从官方下载的ubuntu14.04镜像以及从DockerPool镜像源下载的ubuntulatest镜像。$ sudo docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEubuntu 14.04 5506de2b643b 1 weeks ago 197.8 MBdl.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命令为本地镜像添加新的标签。例如添加一个新的ubuntulatest镜像标签如下$ sudo docker tag dl.dockerpool.com:5000/ubuntu:latest ubuntu:latest再次使用docker images列出本地主机上镜像信息可以看到多了一个ubuntulatest标签的镜像。$ 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}} 550amd64在指定镜像ID的时候通常使用该ID的前若干个字符组成的可区分字串来替代完整的ID。