Docker是一个开源的应用容器引擎,开发人员可以非常容易地打包已经开发好的应用,同时将应用相关的依赖包也打包到这样一个可移植的容器中,然后发布到任意的Linux主机系统上。Docker是基于Linux Container(LXC)技术实现的一个轻量级虚拟化解决方案,用户可以直接使用容器(Container),来构建自己的应用程序,应用开发人员无需将注意力集中在容器的管理上。Docker的目标是“Build, Ship and Run Any App, Anywhere”,这说明了使用Docker能够实现应用运行的可移植性、便捷性,对开发人员非常友好,只要你的应用是基于Docker进行构建和部署的,在任何时候任何支持Docker的Linux发行版操作系统上都可以运行你的应用程序。
Docker是基于Go语言开发的, 代码开源,可以在Github上查看对应的源码:https://github.com/docker/docker.git。
基本构架
Docker基于Client-Server架构,Docker daemon是服务端,Docker client是客户端。Docker的基本架构,如下图所示:

上图中,除了展现了Docker的Client、Server、Containers、Images、Registry之间的关系,我们主要说明Docker daemon和Docker client,关于其他组件我们后面详述:
Docker daemon运行在宿主机上,它是一个long-running进程,用户通过Docker client与Docker daemon进行交互。
Docker client为用户提供了与Docker daemon交互的接口,在安装Docker的时候就已经安装,可以通过docker命令来操作。一个Docker client可以与同一个宿主机上的Docker daemon交互,也可以与远程的Docker daemon进行交互。
基本概念
Registry
Registry是一个服务,它负责管理一个或多个Repository(仓库),而Repository还包含公共仓库(Public Repository)和私有仓库(Private Repository)。默认的Registry是Docker Hub,它管理了按照不同用途分类的很多公共仓库,任何人都可以到Docker Hub上查找自己需要的Image,或者可以使用docker search命令来搜索对应Image,例如我们查询关键词hadoop,示例命令如下所示:
查询结果如下所示:
01 | NAME DESCRIPTION STARS OFFICIAL AUTOMATED |
02 | sequenceiq/hadoop-docker An easy way to try Hadoop 428 [OK] |
03 | sequenceiq/hadoop-ubuntu An easy way to try Hadoop on Ubuntu 40 [OK] |
04 | uhopper/hadoop Base Hadoop image with dynamic configurati... 16 [OK] |
05 | ruo91/hadoop Apache hadoop 2.x - Pseudo-Distributed Mode 12 [OK] |
06 | harisekhon/hadoop Apache Hadoop (HDFS + Yarn, tags 2.5 - 2.7) 8 [OK] |
07 | gelog/hadoop Use at your own risk. 5 [OK] |
08 | athlinks/hadoop Distributed Highly Available Hadoop Cluste... 3 [OK] |
09 | dockmob/hadoop Docker images for Apache Hadoop (YARN, HDF... 3 [OK] |
10 | uhopper/hadoop-resourcemanager Hadoop resourcemanager 3 [OK] |
11 | harisekhon/hadoop-dev Apache Hadoop (HDFS + Yarn) + Dev Tools + ... 3 [OK] |
12 | izone/hadoop Hadoop 2.7.3 Ecosystem fully distributed, ... 3 [OK] |
13 | uhopper/hadoop-namenode Hadoop namenode 2 [OK] |
14 | singularities/hadoop Apache Hadoop 2 [OK] |
15 | uhopper/hadoop-datanode Hadoop datanode 2 [OK] |
16 | uhopper/hadoop-nodemanager Hadoop nodemanager 2 [OK] |
17 | lewuathe/hadoop-master Multiple node hadoop cluster on Docker. 2 [OK] |
18 | robingu/hadoop hadoop 2.7 1 [OK] |
19 | mcapitanio/hadoop Docker image running Hadoop in psedo-distr... 1 [OK] |
20 | takaomag/hadoop docker image of archlinux (hadoop) 1 [OK] |
21 | ymian/hadoop hadoop 0 [OK] |
22 | 2breakfast/hadoop hadoop in docker 0 [OK] |
23 | ading1977/hadoop Docker image for multi-node hadoop cluster. 0 [OK] |
24 | meteogroup/hadoop Apache™ Hadoop® in a docker image. 0 [OK] |
25 | hegand/hadoop-base Hadoop base docker image 0 [OK] |
26 | elek/hadoop Base image for hadoop components (yarn/hdfs) 0 [OK] |
上面可以看到,与hadoop相关的Image都被列出来了,可以根据自己的需要选择对应的Image下载并构建应用。
Image
Docker Image是Docker Container的基础,一个Image是对一个Root文件系统的执行变更操作的有序集合,也包括在运行时一个Container内部需要执行的参数的变化。
一个Image是静态的、无状态的,它具有不变性。如果想要修改一个Image,实际是重新创建了新的Image,在原来Image基础上修改后的一个副本。所以,往往我们制作一个Image的时候,可以基于已经存在的Image来构建新的的Image,然后Push到Repository中。
Repository
一个Repository是Docker Image的集合,它可以被Push到Registry而被共享,在Docker Hub就可以看到很多组织或个人贡献的Image,供大家共享。当然,你也可以将自己构建的Image Push到私有的Repository中。在Repository中不同的Image是通过tag来识别的,例如latest 、5.5.0等等。
Container
Container是一个Docker Image的运行时实例,从一个Image可以创建多个包含该应用的Container。一个Container包含如下几个部分:
- 一个Docker Image
- 执行环境
- 一个标准指令的集合
安装启动Docker
我使用了CentOS 7操作系统,可以非常容易地安装Docker环境。假设,下面我们都是用root用户进行操作,执行如下命令进行准备工作:
1 | yum install -y yum-utils |
上面首先安装了yum-utils,它提供了yum-config-manager管理工具,然后安装了最新稳定版本的Repository文件,最后更新yum的package索引。
安装最新版本的Docker,当前是1.13.1,执行如下命令:
1 | sudo yum -y install docker-engine |
首次安装docker-engine,输出类似如下日志信息:
01 | Loaded plugins: fastestmirror, langpacks |
02 | Loading mirror speeds from cached hostfile |
03 | * base: mirrors.btte.net |
04 | * extras: mirrors.btte.net |
05 | * updates: mirrors.btte.net |
06 | Resolving Dependencies |
07 | --> Running transaction check |
08 | ---> Package docker-engine.x86_64 0:1.13.1-1.el7.centos will be installed |
09 | --> Processing Dependency: docker-engine-selinux >= 1.13.1-1.el7.centos for package: docker-engine-1.13.1-1.el7.centos.x86_64 |
10 | --> Running transaction check |
11 | ---> Package docker-engine-selinux.noarch 0:1.13.1-1.el7.centos will be installed |
12 | --> Finished Dependency Resolution |
16 | ================================================================================================================================================================================================================= |
17 | Package Arch Version Repository Size |
18 | ================================================================================================================================================================================================================= |
20 | docker-engine x86_64 1.13.1-1.el7.centos docker-main 19 M |
21 | Installing for dependencies: |
22 | docker-engine-selinux noarch 1.13.1-1.el7.centos docker-main 28 k |
25 | ================================================================================================================================================================================================================= |
26 | Install 1 Package (+1 Dependent package) |
28 | Total download size: 19 M |
31 | warning: /var/cache/yum/x86_64/7/docker-main/packages/docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 2c52609d: NOKEY ] 1.2 MB/s | 944 kB 00:00:14 ETA |
32 | Public key for docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm is not installed |
33 | (1/2): docker-engine-selinux-1.13.1-1.el7.centos.noarch.rpm | 28 kB 00:00:01 |
34 | (2/2): docker-engine-1.13.1-1.el7.centos.x86_64.rpm | 19 MB 00:00:04 |
35 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36 | Total 4.5 MB/s | 19 MB 00:00:04 |
38 | Importing GPG key 0x2C52609D: |
39 | Userid : "Docker Release Tool (releasedocker) <docker@docker.com>" |
40 | Fingerprint: 5811 8e89 f3a9 1289 7c07 0adb f762 2157 2c52 609d |
42 | Running transaction check |
43 | Running transaction test |
44 | Transaction test succeeded |
46 | Installing : docker-engine-selinux-1.13.1-1.el7.centos.noarch 1/2 |
47 | libsemanage.semanage_direct_install_info: Overriding docker module at lower priority 100 with module at priority 400. |
48 | restorecon: lstat(/var/lib/docker) failed: No such file or directory |
49 | warning: %post(docker-engine-selinux-1.13.1-1.el7.centos.noarch) scriptlet failed, exit status 255 |
50 | Non-fatal POSTIN scriptlet failure in rpm package docker-engine-selinux-1.13.1-1.el7.centos.noarch |
51 | Installing : docker-engine-1.13.1-1.el7.centos.x86_64 2/2 |
52 | Verifying : docker-engine-selinux-1.13.1-1.el7.centos.noarch 1/2 |
53 | Verifying : docker-engine-1.13.1-1.el7.centos.x86_64 2/2 |
56 | docker-engine.x86_64 0:1.13.1-1.el7.centos |
59 | docker-engine-selinux.noarch 0:1.13.1-1.el7.centos |
可见,Docker已经成功安装。下面,我们就可以启动Docker了,执行如下命令,启动Docker(Docker Engine):
可以查看一下当前系统上的进程,执行ps -ef | grep docker确认Docker已经启动:
1 | root 2717 1 8 21:52 ? 00:00:00 /usr/bin/dockerd |
3 | root 2920 2645 0 21:52 pts/0 00:00:00 grep --color=auto docker |
下面,我们验证一下,Docker启动了,应该就可以在一个Container中运行一个准备好的应用,执行如下命令:
基于一个名称为hello-world的Image,启动Container并运行它,启动过程如下所示:
01 | Unable to find image 'hello-world:latest' locally |
02 | latest: Pulling from library/hello-world |
03 | 78445dd45222: Pull complete |
04 | Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7 |
05 | Status: Downloaded newer image for hello-world:latest |
08 | This message shows that your installation appears to be working correctly. |
10 | To generate this message, Docker took the following steps: |
11 | 1. The Docker client contacted the Docker daemon. |
12 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. |
13 | 3. The Docker daemon created a new container from that image which runs the |
14 | executable that produces the output you are currently reading. |
15 | 4. The Docker daemon streamed that output to the Docker client, which sent it |
18 | To try something more ambitious, you can run an Ubuntu container with: |
19 | $ docker run -it ubuntu bash |
21 | Share images, automate workflows, and more with a free Docker ID: |
25 | For more examples and ideas, visit: |
首先可以看到,因为本地没有下载过该Image,所以会先从Docker Hub上下载,对应的tag是latest。另外,也可以看到提示信息“Hello from Docker! ”,表示我们的环境配置没问题,可以启动Container运行应用程序。这里,还给出了运行我们这个名称为hello-world的示例Image在Container中运行过程中,Docker的基本运行机制如下所示:
- Docker Client连接到Docker daemon
- Docker daemon从Docker Hub上下载名称为hello-world的Image
- Docker daemon基于这个Image创建了一个新的Container,并运行应用程序,输出“Hello from Docker!”
- Docker daemon将结果输出到Docker Client,也就是我们的终端上
现在,我们可能想知道hello-world这个Image是如何构建,才能够最终在我们的Docker Container中运行,请看下文。
转载至:http://shiyanjun.cn/archives/1608.html