Docker 概述
Docker 是什么
- Docker 是开源应用容器引擎,轻量级容器技术。
- 基于 Go 语言,并遵循 Apache2.0 协议开源。
- Docker 可以让开发者打包他们的应用、依赖包及配置文件打包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 系统上,也可以实现虚拟化。
- 容器完全使用沙箱技术,相互之间不会有任何接口。
- 类似于虚拟机技术(vmware、vitural),但 docker 直接运行在操作系统(Linux)上,而不是运行在虚拟机中,速度快,性能开销极低。
Docker 支持将软件编译成一个镜像,然后在镜像中对各种软件做好配置,将镜像发布出去(Docker Hub),其他使用者可以直接使用这个镜像。 运行中的这个镜像称为容器,容器启动是非常快速的。类似 windows 里面的 ghost 操 作系统,安装好后什么都有了。
docker容器可以理解为在沙盒中运行的进程。这个沙盒包含了该进程运行所必须的资源,包括文件系统、系统类库、shell 环境等等。但这个沙盒默认是不会运行任何程序的。你需要在沙盒中运行一个进程来启动某一个容器。这个进程是该容器的唯一进程,所以当该进程结束的时候,容器也会完全的停止。
常见应用场景
- Web 应用的自动化打包和发布。
- 自动化测试和持续集成、发布。
- 在服务型环境中部署和调整数据库或其他的后台应用。
- 从头编译或者扩展现有的 OpenShift 或 Cloud Foundry 平台来搭建自己的 PaaS 环境。
Docker 特点
Docker 是一个基于容器的应用开发、部署和运行平台,它为开发者和系统管理员们提供了一种新式的应用部署方式,具有灵活(最复杂的应用都能容器化)、轻量(容器共享一个服务器内核)、可替换的(可以在容器运行过程中更新服务器)、可移植的(本地、云上皆可)、可伸缩的(可以轻松地进行复制)、可栈化(指的是可以将多个服务部署在一起,比如用 docker-compose)的特性。
Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. The use of Linux containers to deploy applications is called containerization. Containers are not new, but their use for easily deploying applications is.
Containerization is increasingly popular because containers are:
- Flexible: Even the most complex applications can be containerized.
- Lightweight: Containers leverage and share the host kernel.
- Interchangeable: You can deploy updates and upgrades on-the-fly.
- Portable: You can build locally, deploy to the cloud, and run anywhere.
- Scalable: You can increase and automatically distribute container replicas.
- Stackable: You can stack services vertically and on-the-fly.
Docker 优势
容器技术相比虚拟机,主要优势在于性能上,其性能优势可以说达到了一个量级的差距。根据 Boden Russell 在 OpenStack 上做的一次基准测试报告,一个 KVM 实例的平均内存消耗有 292MB,而一个 docker 实例的平均内存消耗在 49MB 左右。在 CPU overhead 和启动时间方面,docker 基本都比 KVM 有一个量级的优势。
目前,一个 AWS 上的 micro 实例,每小时的按需使用成本大约在一美分多一些。如果用 docker 来提供实例,那么每小时的按需使用成本很可能会做到 0.1 美分。这一点对于云经济至关重要。正如经济学家 William Stanley Jevons 的理论所呈现的,随着商品的价格越便宜,人们使用它们的场景和频率会越来越多。
- container 是一种部署单元,用户可以自由决定部署的范围(dev、test、production),即组织容器的方式,换句话说,容器可以简化工作流和软件的开发、部署生命周期;
- 可以从传统的虚拟机环境平滑过渡到裸机生产环境内;
保证了线上线下环境的一致性。我们在线下的开发环境使用 Docker 构建好 weaapp 的镜像后,可以直接在线上使用一个镜像,保证了线上线下环境的一致性,再也不会有在线下开发环境中运行正常,而部署到线上各种错误了。 - 实现了模块化,提高了复用性。
我们可以将数据库和 Tomcat 运行在不同的容器中,从某种角度来说,这也降低了模块之间的耦合性,便于拓展。比如我们要把 MySQL 替换为 oracle,只需要再构建一个 oracle 镜像并启动与 Tomcat 连接即可,非常方便。对于我们构建的镜像,在其他 app 中直接拿来用就可以了,不必重复劳动。 - 提高整体效率;
极大的简化了 webapp 的部署流程。在不使用 Docker 时,我们部署 app 时,要先搭建好 app 运行所需环境,这个过程做过的人都知道多么枯燥繁琐,一不小心还出错。而有了 Docker,我们只需要直接构建一个我们 webapp 的镜像然后将其运行即可,无论在多少台服务器中部署,都是如此。再比如,使用 Docker 之前要搭建一个 WordPress 对于新手来说是有些困难的,而有了 Docker,只需要从 DockerHub 上 pull 一个 WordPress 镜像并启动就可以了,非常非常方便。 - 实现了虚拟化,提高硬件利用率,有了 Docker,我们可以在一台服务器上运行很多 webapp,充分利用闲置资源。
这时候,服务器的操作系统就类似于货轮,而一个个 Docker 容器就相当于货轮上的一个个集装箱。现在大热的云服务市场,不少就用了 Docker。举个例子来说,现在我们有一台操作系统为 Ubuntu14.04 的服务器,我们构建不同版本的 ubuntu 镜像并启动,并且为不同的用户分配不同的容器。这样,用一台服务器可以虚拟出 n 个运行着不同操作系统的虚拟服务器,而对于用户来说,这些是透明的––用户则认为自己拥有一台完整的服务器。据我推测,阿里云的服务器就是这么干的。这充分利用了闲置的硬件资源。 - Fast
- 传统方式慢,传统情况下,应用服务器扩容缩容步骤繁多流程冗长,从服务器申请、初始化、应用部署、测试、加入退出集群、服务器下线。比如,业务遇到突发的流量高峰时,无法进行快速的扩容,当准备好的时候可能流量高峰已经过去了。
- 传统不稳定,代码上线发布历经多个环境,在某个环境中测试时修复了 bug,代码等无法及时同步各环境中,提升了服务上线的风险。
- Runtime performance at near bare metal speeds (typically 97+ percent or bare metal – a few ticks shaven off for bean counters).
- Management operations (boot, stop, start, reboot, etc.) in seconds or milliseconds.
- Agile
- VM-like agility – it’s still “virtualization”.
- Seamlessly move between virtual and bare metal environments permitting new development workflows which reduce costs (e.g. develop on VMs and move to bare metal in the “click of a button” for production).
- Flexible
- Containerize a “system” (OS less the kernel).
- Containerize “application(s)”.
- Lightweight
- Just enough Operating System (JeOS); include only what you need reducing image and container bloat.
- Minimal per container penalty which equates to greater density and hence greater returns on existing assets – imagine packing 100s or 1000s of containers on a single host node.
- Inexpensive
- Open source – free – lower TCO.
- Supported with out-of-the-box modern Linux kernels.
- Ecosystem
- Growing in popularity – just checkout the google trends for docker or LXC.
- Vibrant community and numerous 3rd party applications (1000s of prebuilt images on docker index and 100s of open source apps on github or other public sources).
- Cloudy
- Various Cloud management frameworks provide support for creating and managing Linux Containers – including OpenStack my personal favorite.
Docker 劣势
既然容器技术有如此大的优势,为什么基于容器的云现在还没有成为主流?我认为主要还是安全性的问题。虚拟机可以利用来自硬件的信任机制来提升安全性,这些机制在 Intel Virtualization Technology Evolution 的演示中有详细的介绍。即使如此,虚拟机仍然被视为相对不安全,比如前一段时间 Xen(半虚拟化,在硬件层和 OS 层之间的虚拟层)爆出一个漏洞,导致 AWS 不得不大量升级自己的主机。
- Docker Hub(镜像管理中心)不稳定
第一个就是很重要的 Docker Hub 的访问问题。我们知道国内访问一些海外的网站有时候会有稳定性的问题。Docker Hub 在我们的实践中就经常出现访问不了的问题。但这种访问的问题并不是持续的,而是时有时无。由于大量的成熟 Docker 映像(image)都需要从 Docker Hub 下载,很多脚本在执行到这一步时,结果很难预料。一种方案是修改缺省的 Docker Hub 地址,改为采用国内的一些镜像(mirror)。但是在没有官方认证的成熟稳定的镜像网站时,Docker 映像的更新不容易得到保证;另一种方案是自行搭建自己的 Docker Hub。但是一来这样就失去了强大的社区贡献的映像资源,二来要花费很多精力来保持更新和同步。容器技术带来的简单化,又因为映像管理而复杂化,得不偿失。 - 运维难度大
第二个就是容器技术的资源管理和运维。因为容器技术本身更适于解决大规模应用场景,所以通常都是集群基础上的部署、运维,但是目前对这一系列任务的自动化处理尚无统一的或者标准的框架。如果要让 Docker 真正在实际环境中发挥最大的效能并且易于维护,就需要有很成熟稳定的资源编排(orchestration)、资源调度(scheduling)和部署(deployment)的支持,但是这方面暂时还没有很明显的最佳解决方案,所以大多数人都在摸索和搭建自己的解决方案。我们在微软开放技术内部也是在一些开源技术的基础之上,自行开发了容器在微软公有云 Azure 上的资源管理调度和部署运维的系统,传统上的开发运维和持续集成,持续部署的技术,比如 Chef,Puppet,Jenkins 等,都可以很容易的与容器技术一起工作。
镜像和容器(Images and containers)
A container is launched by running an image. An image is an executable package that includes everything needed to run an application–the code, a runtime, libraries, environment variables, and configuration files.
A container is a runtime instance of an image–what the image becomes in memory when executed (that is, an image with state, or a user process). You can see a list of your running containers with the command, docker ps, just as you would in Linux.
一个镜像是:
- 一个只读模板,可以用来创建容器,一个镜像可以创建多个容器
- Docker 提供了一个很简单的机制来创建和更新现有的镜像,甚至可以直接从其他人那里获取做好的镜像直接使用
可以理解为 Java 中的类
一个容器是: - 容器是从镜像创建的运行实例,也就是镜像启动后的一个实例称为容器,是独立运行的一个或一组应用。
- docker 利用容器来运行应用,他可以被启动、开始、停止、删除,每个容器都是相互隔离的、保证安全的平台。
- 可以把容器看做是一个简易版的 Linux(包括 root 用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
- 可以理解为 Java 中通过类创建的实例。
服务端和客户端
Docker系统有两个程序:docker服务端和docker客户端。其中docker服务端是一个服务进程,管理着所有的容器。docker客户端则扮演着docker服务端的远程控制器,可以用来控制docker的服务端进程。大部分情况下,docker服务端和客户端运行在一台机器上。
Docker开放的API与Docker的守护进程进行通信。
docker 仓库(Resoisitory)
- 仓库是集中存放镜像文件的场所,类似 git 代码仓库等。
- 仓库(Respository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器一般存放多个仓库,每个仓库又有多个镜像,每个镜像又有不同的标签(tag)。
- 仓库分为公开仓库(public)和私有仓库(private)两种形式。
- 最大的公开仓库是 Docker Hub,国内的公开仓库有阿里云等。
- 可以在本地网络创建一个私有仓库。
- 当创建好自己的镜像后,可以通过 push 命令把它上传到公开或私有仓库。
- 仓库的概念类似 Git,仓库注册服务器可以理解为 GitHub 这种托管服务。
Containers & virtual machines
传统的部署云服务的方式是通过虚拟机完成的,虚拟机会在宿主机上运行一个完整的操作系统、通过hypervisor来间接使用宿主机的硬件资源,实际上这远远超出了应用运行所必须的资源。而容器正相反,它在操作系统中作为进程运行,与所有其他容器共享同一内核、占用相同容量的内存空间,相对来说,会更加轻量。
A container runs natively on Linux and shares the kernel of the host machine with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight.
By contrast, a virtual machine (VM) runs a full-blown “guest” operating system with virtualaccess to host resources through a hypervisor. In general, VMs provide an environment with more resources than most applications need.
下图是Docker(容器)和传统虚拟机之间运行架构的示意图。
Container stack example Virtual machine stack example
In reality virtualization and Docker can and are used together in modern dev-ops. Most VPS providers are running bare-metal full virtualization technologies like Xen and Docker usually runs on top of a virtualized Ubuntu instance.
Docker 与 LXC(Linux Container)
LXC利用Linux上相关技术实现容器,Docker则在如下的几个方面进行了改进:
移植性:通过抽象容器配置,容器可以实现一个平台移植到另一个平台;
镜像系统:基于AUFS的镜像系统为容器的分发带来了很多的便利,同时共同的镜像层只需要存储一份,实现高效率的存储;
版本管理:类似于GIT的版本管理理念,用户可以更方面的创建、管理镜像文件;
仓库系统:仓库系统大大降低了镜像的分发和管理的成本;
周边工具:各种现有的工具(配置管理、云平台)对Docker的支持,以及基于Docker的Pass、CI等系统,让Docker的应用更加方便和多样化。
Docker与Vagrant
两者的定位完全不同
Vagrant类似于Boot2Docker(一款运行Docker的最小内核),是一套虚拟机的管理环境,Vagrant可以在多种系统上和虚拟机软件中运行,可以在Windows。Mac等非Linux平台上为Docker支持,自身具有较好的包装性和移植性。
原生Docker自身只能运行在Linux平台上,但启动和运行的性能都比虚拟机要快,往往更适合快速开发和部署应用的场景。
Docker不是虚拟机,而是进程隔离,对于资源的消耗很少,单一开发环境下Vagrant是虚拟机上的封装,虚拟机本身会消耗资源。因此对于开发环境来讲,使用Docker是更好的选择。
开始使用Docker
查看操作系统版本
Docker是基于LXC(Linux Container)的,因此最好在Linux环境下使用。
Docker要求内核版本高于3.10(如果是Ubuntu则需要高于12.04的发行版)可以使用下面命令查看操作系统版本:
1 | uname -r |
安装(Ubuntu)
最好上官网下载安装最新版docker-ce,命令行下的太旧了:
1 | sudo apt-get install docker.io |
或者按照官网上的步骤:
1 | # 安装插件,可以使用HTTPS来下载仓库软件 |
安装(CentOS)
1 | yum update |
安装(Mac)
1 |
下载镜像
1 | # 搜索可用的镜像,或者上http://index.docker.io/查找 |
运行容器
1 | # docker run命令有两个参数,一个是镜像名,一个是要在镜像中运行的命令。 |
保存对容器的修改
当你对某一个容器做了修改之后(通过在容器中运行某一个命令),可以把对容器的修改保存下来,这样下次可以从保存后的最新状态运行该容器。docker中保存状态的过程称之为committing,它保存的新旧状态之间的区别,从而产生一个新的版本。
1 | # 获得查看正在运行中的、安装完ping命令之后容器的id |
发布镜像
1 | # 列出本地的所有镜像 |
设置用户
- 使用root用户运行
通常我们使用Docker的时候都是使用root用户身份运行的,官方说法如下:1
2The docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can access it with sudo. For this reason, docker daemon always runs as the root user.
To avoid having to use sudo when you use the docker command, create a Unix group called docker and add users to it. When the docker daemon starts, it makes the ownership of the Unix socket read/writable by the docker group. - 使用普通用户运行然后当前用户注销再重新登录就可以正常使用docker命令了:
1
2
3sudo groupadd docker # docker组可能已经存在了
sudo gpasswd -a ${USER} docker # 将当前用户加入docker组
sudo systemctl restart docker # 重新启动docker服务(下面是CentOS7的命令)1
docker ps
登录
要登录容器进行操作,一种办法是在运行容器的时候开放22端口到外部,然后使用ssh来连接:
1 | docker create -it --name=容器别名 -p 20022:22 ics-image |
另一种办法是在运行中的容器内执行/bin/bash:
1 | docker exec -it 容器名 /bin/bash |
Docker Daemon
Docker迁移
将一台宿主机上的Docker环境迁移到另一台宿主机上是比较方便的,只需停止Docker服务,将整个docker存储文件复制到另外一台宿主机上,然后调整另外一台宿主机的配置即可。
Docker Hub
仓库(Repository)、注册服务器(Registry)、注册索引(Index)
仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像;
注册服务器是存放实际的镜像的地方;
注册索引则负责维护用户的账号,权限,搜索,标签等管理。注册服务器利用注册索引来实现认证等管理。
QA
Docker Hub
- docker pull老超时
试试国内的加速:https://www.daocloud.io/mirror#accelerator-doc
或连接VPN后试试 - pull或push时出现一直Waiting的情况
网上没有找到答案,开了VPN也没啥用,最后把环境变量改回来(eval $(docker-machine env -u))就好了。 - 从非官方仓库(如:dl.dockerpool.com)下载镜像的时候,有时候会提示“Error:Invaild registry endpoint https://dl.docker.com:5000/v1/…”?
Docker 自1.3.0版本往后以来,加强了对镜像安全性的验证,需要手动添加对非官方仓库的信任。
DOCKER_OPTS=”–insecure-registry dl.dockerpool.com:5000”
重启docker服务
参考
- docker-library / official-images
- Best practices for writing Dockerfiles
- 十分钟带你理解 Kubernetes 核心概念
- Install Docker https://docs.docker.com/install/
- Get Docker CE for Ubuntu
- Get Started
- 入门教程 中文
- Docker Hub
- Docker Cloud
- 命令行参考文档
- 安装后配置
- daemon配置