docker 五分钟入门

docker 作为 golang 社区的杀手级应用,已经拥有越来越多的关注,其在 GitHub 上已经拥有 4万多个 star。尤其在当前各种大规模分布式服务器的环境下,传统的环境部署方式和各种库依赖,已经和当下快速开发快速上线产生了很大的矛盾。所以不管是开发、运维和测试人员,都应该尝试去使用 docker 来维护 pre、online 和 test 环境。

原理

Java 总是宣称 "Write once,run anywhere"。简单地说,docker 允许你安装、部署你的应用程序,而不用担心底层的依赖环境。docker 屏蔽了不同操作系统的差异,而对上层提供统一的访问接口。比如你可以在 CentOS 上编译好程序,而在 Ubuntu 系统上运行,实现了 "Build once,run anywhere"。

这其中的原理就是 docker 提供了『层』的概念:从 Linux kernel,到 OS,再到依赖的库和应用程序,每一层都是独立的。不同的上层可以共享相同的底层,比如 CentOS 镜像和 Ubuntu 镜像共享相同的 kernel 层,Nginx 和 Apache 共享相同的 OS 层。这样也使得镜像的体积大大减少。

既然上层共享下层,那么问题来了:如果有两个上层 A 和 B,都需要下层中 S 的某个文件 f,且 A 和 B 需要的文件内容是不同的。这时候不论将 f 的内容设置为 A 所需要的或是 B 所需要的,都不能满足另一方的需求。docker 的解决办法是在 A 和 B 的上层再增加一个空白层,将该层所需要的特定文件拷贝到该层并修改,且 S 层中的这个文件在运行时会被覆盖。这样,从 A 或 B 的角度看,文件被修改了,而从 S 的角度看,还是原来的初始文件,这就在满足上层需要的同时保证了下层的原始性。

具体到操作方面,docker 主要有镜像、容器和仓库三部分,分别写一下。

镜像

简单地说,镜像就是一个应用程序完整的运行环境,它包含了该程序需要的所有依赖,如库文件、配置文件、运行环境等,只要有 docker,该镜像就能运行起来,具有很好的跨平台性。 你可以通过以下命令列出当前主机上所有的镜像:

$ docker images

可以看到,输出共有五列,分别为 repository,tag,image ID,create 和 size。

创建一个镜像

和 Makefile 一样,docker 也有自己的构建文件,称为 Dockerfile。通过编写该文件,可以使用docker build .一键生成我们所需要的镜像。以下是一个示例:

FROM CentOS
MAINTAINER smart

RUN yum update
RUN yum -y install git nodejs
RUN npm install -g hexo-cl

其中,FROM 指定一个基础镜像。docker 中每个镜像都必须指定一个基础镜像,然后在其上进行操作。本例中是 CentOS。MAINTAINER 指定这个镜像的维护者,RUN 指定在构建镜像时所进行的操作。每 RUN 一次,docker 都会提交为一个新的镜像,并删除当前镜像。

镜像相关操作

容器

镜像和容器的概念很容易被混淆。它们之间的关系就和程序和进程的关系一样。镜像只是一个实体,运行起来的镜像称之为容器。可以看出,同一个镜像按照不同的参数运行,就形成了多个不同的容器。docker run $name 可以生成一个容器并运行,其中 $name 是镜像名。一般来说,在运行容器的时候我们需要给定不同的参数,如 -i 表示保留容器的输入输出,通常和 -t 参数同时指定,表示保留容器输入输出的同时新打开一个命令行终端;--name $name 为容器指定一个名字,$name 是我们新指定的容器名;-p 8080:80 表示将本机上的 8080 端口和容器中的 80 端口绑定,这样就可以通过访问主机的 8080 端口来访问到容器的 80 端口了;-d 表示将容器在后台运行;-v $lpwd:$rpwd:[rw|ro] 表示将本机的 $lpwd 路径指定的文件或目录映射到容器中 $rpwd 指定的文件或目录,以实现数据的交换,其中 $lpwd$rpwd 都是绝对路径。rwro 是可选的,表示容器中该路径是可读写的或只读的,默认为 rw

容器相关操作

类似于 Linux 对进程的操作一样,docker 使用 ps 命令来列出所有当前正在运行的容器;

仓库

类似于 GitHub,docker 也有自己的官方仓库。其中存储了许多基础镜像和应用镜像,如 CentOS,Ubuntu,Nginx,WordPress 等,也有民间人士自己制作的镜像。

每个免费账户可以创建一个 private 仓库和多个 public 仓库。可以利用 docker push $iname 将自己本地的镜像推送到远程仓库,也可以 docker pull $iname 去远端仓库拉取一个镜像。push 的前提是需要先通过 docker login 登录,pull 不用。

docker search $key 可以搜索远端仓库,$key 是关键字,包含该关键字的镜像都会被搜索出来,结果包含每个镜像的 index,name,description,starts,official,automated,分别表示该镜像的索引,名称,描述,点赞数,是否为官方的,是否自动化构建的。