什么是Docker
Docker作为虚拟化分支的一项重要的革新,有必要将Docker和其他虚拟化技术进行一下比较。下面是介绍虚拟化过程中最常见的一张图,它描述了计算机从软到硬的一个层次关系。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/865e1b76c5becad4744d118527052ff0.png)
这个图看似简单,其实它很清晰的描述了计算机资源的一种层次关系。最底层是基础设施层,基本都是硬件方面的构成,如CPU,内存,磁盘,这些支撑了计算机的基本运行,如果没有这些硬件,计算机也就不存在了。在硬件层上运行了格式的操作系统,他能够根据合理的将硬件资源合理的分配给上面的应用,并保证他们有条不紊的运行。在系统上自带一些系统的lib和可执行命令,这些可执行命令就是我们常用的Linux命令(cd,cat,ls….太多了),Lib则包含了一些基本程序库,供我们自己编写的各种程序调用。最上面就是我们开发的各种Application了。
Docker与虚拟机
说完了基本的分层关系,下面就需要重点介绍两种比较重要的虚拟化技术,虚拟机和Docker,虽然感觉区别被讲烂了不过为了介绍的完整性还是简单提一句,还请大家耐心看完。
Hypervisor与虚拟机
从本质上看,虚拟机和Docker属于在不同层次上的虚拟,虚拟机则是虚拟到操作系统层次的,如下图所示。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/641d4ca6ddd2c405abed946958af7524.png)
在宿主机的操作系统中,抽象出了一个Hypervisor的概念,因为自己并没有涉猎过这个领域,所以扒一些现成的资料给我自己扫扫盲。
首先是Hypervisor的定义,根据wiki上讲,Hypervisor或者Virtual Machine Monitor(VMM)是创造并且运行虚拟机的软件、固件、或者硬件,通俗的讲,hypervisor是一种将操作系统和硬件分离的一种方式,使得宿主机的硬件上能够同时运行多个虚拟机。
Hypervisor具有如下的优点:
提高主机硬件的使用率
虚拟机移动性较强
资源的隔离性,某台虚拟机的宕机不影响其他虚拟机的使用
易保护,易恢复
Hypervisor种类:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/672895d8bc27cf895eeea7ac1422edeb.png)
如上面两张图所示,Hypervisor分为两类,一类是直接部署在硬件层面上(bare-metal hypervisors),另一类则是部署在宿主机的操作系统上,算是一种软件(hosted hypervisors)。两种方式的特点与典型系统如下:
bare-metal hypervisors 特点
需要硬件支持
虚拟机monitor作为主操作系统
运行效率高
典型系统
VMware5.5+
Xen3.0+
KVM
hosted hypervisors 特点
-
虚拟机监视器作为应用程序运行在主操作系统环境内
效率较低
典型系统
Virtual Box
early VMware5.5
early Xen3.0
Docker
与虚拟机不同,Docker是通过软件层的虚拟化实现了更加轻量级的虚拟化,其架构图如下:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/f546a27d161afdc02707a6d5cd0db429.png)
初步看来,Docker所在的层级与虚拟机所在的层次相同,都是在宿主机的操作系统上部署,但是Docker完全是软件,不需要硬件进行支持,它利用的是操作系统自带的资源隔离机制对硬件资源进行隔离,例如Win中的Hyper-v,Linux中的cgroup等,由Docker的后端程序Docker Engine调用这些接口完成资源隔离。Docker在创建容器时并不运行完整的操作系统,使用的资源更少,部署,启动更快。但提供的隔离粒度不足,所以Docker更加适合单个用户使用,而虚拟机则更适合在多个用户混合的多租户类型的场景中执行。
为什么用Docker
Docker简单使用方法
介绍使用方法前,先明确Docker中的几个基本组件以及这些组件的交互关系。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/0643a980804aa19df5560af4c3030922.jpeg)
Docker镜像:Docker镜像是用于创建Docker容器的模板
Docker容器(Container):容器是独立运行的一个或一组应用
Docker客户端(Client):Docker客户端通过命令行或者其他工具使用Docker API与Docker的守护进程通信。
Docker主机(Host):一个物理或者虚拟的机器用于执行Docker守护进程和容器
Docker仓库(Registry):Docker仓库用来保存镜像,可以理解为代码控制中的代码仓库。Docker Hub提供了庞大的镜像集合供使用。
Docker Machine:Docker Machine是一个简化Docker安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装Docker,比如VirtualBox、 Digital Ocean、Microsoft Azure
终于到了实战环节,在这一小节里面,我们通过两个具体案例介绍Docker的简单使用方法,首先是Docker的Hello World,另一个则是按照Docker官方文档部署一个Flask后端服务。
安装Docker
Mac && Windows:直接下载安装文件进行安装
Linux:
yum install -y epel-release ##安装仓库
yum install docker-io ##安装Docker
chkconfig docker on ## 加入开机自动启动
service docker start ## 启动Docker
Docker Hello World
这个案例非常简单,只有一个命令:
docker run hello-world
如果看到下图中的结果则说明成功。
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/0529414e3398e8c870d593714b522ec3.png)
Docker复杂使用
这个应用主要是一个Python的Web服务,该服务用于统计用户访问量,用户访问量存储在Redis中。下面正式开始部署。
首先先写一个Flask的Python程序,主要的统计逻辑和前端展示都由这个文件提供,代码如下:
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)## 连接redis
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter") ##获取计数器当前值并将其+1
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) ##网页渲染
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80) ## 服务的设置为80端口
然后编写Python需要的依赖文件requirements.txt。
Redis
Flask
最后写出Docker的部署文件Dockerfile:
# 将官方 Python 运行时用作父镜像
FROM python:2.7-slim
# 将工作目录设置为 /app
WORKDIR /app
# 将当前目录内容复制到位于 /app 中的容器中
ADD . /app
# 安装 requirements.txt 中指定的任何所需软件包
RUN pip install -r requirements.txt
# 使端口 80 可供此容器外的环境使用
EXPOSE 80
# 定义环境变量
ENV NAME World
# 在容器启动时运行 app.py
CMD ["python", "app.py"]
最后的目录结构如下:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/9c327534914c7f3a0ccea61c5edc57e1.png)
完成之后开始构建,首先build镜像:
docker build -t bryantchangflasktest .
其中 -t 的作用是指定镜像的名字。
完成构建后,结果如下:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/b22be8da23acaba4733ea0e2b6f2063e.png)
使用docker images查看已经构建的镜像:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/e2e0594bd8f0fe53f112457f4fe5c0ed.png)
完成构建后,接下来开始运行:
docker run -p 4001:80 bryantchangflasktest ##将4001端口映射到80端口
运行结果:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/c50fe1d05c7e86eb092a3d7ce48a3d27.png)
可以看到因为没有配置Redis所以这里面的异常是我们预期内的,为了做后面的配置方便,我们将镜像上传到公共镜像,命令如下:
docker build -t bryantchangxy/bryantchangflasktest .
docker push bryantchangxy/bryantchangflasktest:latest
涉及的一些常见命令:
docker build -t friendlyname .# 使用此目录的 Dockerfile 创建镜像
docker run -p 4001:80 friendlyname # 运行端口 4001 到 80 的“友好名称”映射
docker run -d -p 4001:80 friendlyname # 内容相同,但在分离模式下
docker ps # 查看所有正在运行的容器的列表
docker stop <hash> # 平稳地停止指定的容器
docker ps -a # 查看所有容器的列表,甚至包含未运行的容器
docker kill <hash> # 强制关闭指定的容器
docker rm <hash> # 从此机器中删除指定的容器
docker rm $(docker ps -a -q) # 从此机器中删除所有容器
docker images -a # 显示此机器上的所有镜像
docker rmi <imagename> # 从此机器中删除指定的镜像
docker rmi $(docker images -q) # 从此机器中删除所有镜像
docker login # 使用您的 Docker 凭证登录此 CLI 会话
docker tag <image> username/repository:tag # 标记 <image> 以上传到镜像库
docker push username/repository:tag # 将已标记的镜像上传到镜像库
docker run username/repository:tag
docker stack ls # 列出此 Docker 主机上所有正在运行的应用
docker stack deploy -c <composefile> <appname> # 运行指定的 Compose 文件
docker stack services <appname> # 列出与应用关联的服务
docker stack ps <appname> # 列出与应用关联的正在运行的容器
docker stack rm <appname> # 清除应用
注意,下面我不再继续沿用那篇文档里面的内容,我直接将Flask和Redis集成,并使用Docker Compose部署,部署文件为docker-compose.yml,内容如下:
web:
build: .
command: python app.py
ports:
- "4001:80"
volumes:
- .:/app
links:
- redis
redis:
image: microbox/redis
最后部署镜像,命令如下:
docker-compose up -d
完成后,输入localhost:4001,终于看到了最终的结果:
![640?wx_fmt=png](https://i-blog.csdnimg.cn/blog_migrate/6edda066b9fd64054b89669588ec069e.png)
对于Docker Compose的使用,参见博客:https://blog.csdn.net/u011781521/article/details/80464826。
原文链接:https://bryantchang.github.io/2019/02/17/docker-utilization/
![640?wx_fmt=jpeg](https://i-blog.csdnimg.cn/blog_migrate/b25e87cb815a8e4cc648d24d659037b4.jpeg)