容器和虚拟化
虚拟机
虚拟化技术(硬件虚拟化)
虚拟化是指通过软件的技术将一台物理主机虚拟化为多台逻辑计算机,每台逻辑计算机可独立的运行不同的操作系统和各种应用程序。
通过虚拟化技术,使得每一台虚拟机都拥有自己的虚拟硬件(虚拟cpu、网卡、内存等),并让运行在虚拟机上的操作系统认为自己独占一台物理主机;
虚拟机上的软件运行在一个虚拟的平台上,而非真实的硬件平台;
虚拟机的基础架构
Hypervisor,虚拟机监控程序,是一种可以直接运行在裸机上的程序,功能是创建一个底层硬件平台的抽象,一个或多个虚拟机共享这个底层抽象平台,同时负责各个虚拟机的操作系统之间硬件资源的协调;而VM(虚拟机)作为操作系统及其应用程序的容器,起到了隔离各个操作系统的作用。
运行的应用程序所需要的一切都包含在虚拟机里,虚拟化硬件、操作系统以及任何所需要的二进制文件和库,因此,虚拟机有自己独立的架构;
深层理解虚拟机(如何运行多个隔离应用)
从下到上理解:
- 基础资源。可以是个人电脑,数据服务器,或是云主机;可以是本身包含操作系统,或是可以运行程序的裸机;
- 虚拟机管理程序(Hypervisor),。利用Hypervisor,主操作系统上可以运行多个不同的从虚拟操作系统。type1的Hypervisor有支持macOS的HyperKit、支持windows的Hyper-V、Xen和KVM;type2的Hypervisor有VirtualBox和VMWare wrokstation。
- 客户机操作系统(Guest Operating System)。假如你需要运行三个相互隔离的应用程序,就需要Hypervisor启动三个客户机操作系统,即虚拟机(众所周知,虚拟机一般非常大,意味着消耗更多的磁盘空间),更糟糕的是,它们还会消耗更多的CPU和内存。
- 环境依赖。每一个客户机操作系统都需要安装许多依赖,如果你的应用需要连接PostgreSQL的话,则需要安装libpq-dev;如果你使用Ruby的话,应该需要安装gems;如果使用其他编程语言,比如Python或者Node.js,都会需要安装对应的依赖库。
- 应用。安装完依赖后,各个应用就可以相互隔离的在各个客户机操作系统上运行了。
容器
容器技术
容器是一个不依赖操作系统的运行应用程序的环境。它通过linux的Namespaces(linux命名空间,可以隔离进程的id、主机名、用户id、网络访问和进程通信等相关资源)和Cgroups(控制组是一项内核功能,能够控制和限制一个进程或多组进程的资源使用)技术对应用程序进程进行隔离和限制;Namespace的作用是隔离,它让应用进程只能看到该Namespace内的世界;而Cgroups 的作用是限制分配给进程的宿主机资源。但对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有太大区别。
容器只是运行在宿主机上的一种特殊进程,多容器之间使用的还是同一个宿主机的操作系统内核(该特点导致隔离性比虚拟机差)。
chroot:可以将任意目录改为当前进程 的根目录,使得该进程不能访问当前进程根目录之外的其他目录
容器的作用
(1)使用容器镜像的方式统一管理应用的开发、部署和运行。
(2)实现不同应用间隔离。
(3)跨平台支持。
容器运行多个相互隔离的应用(docker为例)
相比于虚拟机,容器更加简洁,不需要运行一个臃肿的客户机操作系统了;
从下到上理解:
- 基础资源。
- 主操作系统(Host Operating System)。所有主流的linux发行版都可以运行Docker,windows和mac也可以通过一些方法来运行Docker。
- Docker守护进程(Docker Daemon)。Docker守护进程类似于虚拟机管理进程,它是运行在操作系统之上的后台进程,负责管理docker容器。它通过与主操作系统通信,为各个容器分配资源。
- 环境依赖。对docker来说,应用的所有依赖都打包到docker镜像中,docker容器是基于docker镜像创建的。
- 应用。应用的源代码和依赖都打包到docker的镜像中,不同的应用需要不同的docker镜像,不同的应用运行在不同的docker容器中,它们相互隔离。
虚拟机和容器的区别
- 容器直接在宿主主机的操作系统上调用硬件资源,而非虚拟化硬件资源(当宿主主机是虚拟机时不在此列),容器并非虚拟机,容器是一个系统进程;虚拟机是在操作系统中的操作系统。
- 虚拟机使用的虚拟资源,存在两种情况,其一是虚拟机管理程序运行在宿主操作系统上,其二是虚拟机管理程序运行在裸机上(这种情况下,虚拟操作系统通过虚拟机管理程序来获取硬件资源)。
- 虚拟机和容器对资源的隔离层次不同。虚拟机是从系统层面出发,通过虚拟化硬件资源来达到隔离不同的操作系统,从而隔离不同的应用;容器是从进程层面出发,运行在操作系统之上的进程,通过分隔进程资源达到隔离不同的应用。[ * ]
- 应用场景不同,虚拟机擅长隔离整个运行环境,例如云服务器通常采用虚拟机技术隔离不同用户;docker擅长隔离不同的应用,例如前端、后台、数据库。
- 优势不同,容器的优势在于性能和效率;虚拟机的优势在于稳定和安全。
- 类比:
底层硬件环境–地基;别墅–带操作系统pc机;高楼–不同操作系统虚拟机;别墅房分割成多个不同空间–容器 - 总的来说:容器和虚拟机不是同一类东西,不能直接对比,但是它们之间从宏观的角度来说,有一些相似点。
Docker
注:部分文章取自华为开发者联盟论坛,每天不断提升自我
什么是docker
一个比较通俗的例子
在一个大型项目部署时,使用到的项目组件较多,运行环境也较为复杂,部署时会碰到一些问题,例如,服务会依赖于各种各样的应用,Node.js、Redis、RabbitMQ、MySQL等等,每一个应用需要的依赖和函数库又有差异,也有可能版本不同,所以依赖关系复杂,容易出现兼容性问题,总的来说,如下两点:
- 依赖关系复杂,容易出现兼容性问题
- 开发、测试、生产环境有差异
docker如何解决依赖的兼容问题(即环境问题)?
- 将应用的Libs(函数库)、Deps(依赖)、配置与应用一起打包
- 将每个应用放到一个隔离容器去运行,避免互相干扰
例举下面4种不同的场景
不同环境的操作系统不同,Docker如何解决?
注:了解操作系统结构,比如Ubuntu系统上的MySQL应用放到CentOS系统上尝试运行,当MySQL去调用函数库时,代码是写死的,这个函数库在CentOS系统上根本不存在,肯定就程序报错,这就是应用不能跨系统运行的原因。
Docker如何解决不同系统环境的问题?
- Docker将用户程序与所需要调用的系统(比如Ubuntu)函数库一起打包;
- Docker运行到不同操作系统时,直接基于打包的库函数,借助于操作系统的Linux内核来运行。
Docker如何解决大型项目依赖关系复杂,不同组件依赖的兼容性问题?
- Docker允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像
- Docker应用运行在容器中,使用沙箱机制,相互隔离
Docker如何解决开发、测试、生产环境有差异的问题?
- Docker镜像中包含完整运行环境,包括系统函数库,仅依赖系统的Linux内核,因此可以在任意Linux操作系统上运行
总结
Docker是一个快速交付应用、运行应用的技术:
1.可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统;
2.运行时利用沙箱机制形成隔离容器,各个应用互不干扰;
3.启动、移除都可以通过一行命令完成,方便快捷。
docker架构
-
docker镜像(Image)
Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,称为镜像。 -
docker容器 (container)
镜像中的应用程序运行后形成的进程就是容器(即运行中的镜像),只是Docker会给容器做隔离,对外不可见。例如,容器想往MySQL存数据,只能先复制一份数据到自己的容器中,在自己的容器中操作,这样就污染不了这个镜像,起到隔离的作用。将来基于镜像再创建一个容器,也是全新的里面都是空的。
注:镜像是只读的,所以跨域交给别人放心大胆的使用,也不会被感染。 -
docker仓库(DockerHub)
DockerHub是一个Docker镜像的托管平台。这样的平台称为Docker Registry。国内也有类似于DockerHub 的公开服务,比如网易云镜像服务、阿里云镜像库等。
docker是一种C/S架构的程序,由两部分组成
1.docker客户端,通过命令或RestAPI向Docker服务端发送指令。可以在本地或远程向服务端发送指令。
2.docker服务端,Docker守护进程,负责处理Docker指令,管理镜像、容器等
小结
将应用程序及其依赖、环境、配置打包在一起即为镜像。
运行中的镜像即为容器,镜像可以由远程仓库pull。容器可以看做镜像的实例(面向对象思想),即容器由镜像生成。
Docker基本操作
镜像名分为两部分,[repository] : [tag] ,tag是版本,没有指定版本是,默认是latest(最新版本)。
基本指令
# ----- 镜像命令 -----
#查看帮助文档/查看某个命令的帮助文档
docker --help / docker common --help
#从dockerhub中拉去镜像到本地(需要配置镜像官方网站)
docker pull iamge:tag
#可以看当前有多少镜像
docker image
#移除某个镜像
docker rmi
#保存一个或多个镜像到tar文件中 / 加载镜像从tar包
docker save -o filename image:tag / docker load -i filename
#登录远程仓库
docker login domian
# ----- 容器命令 -----
#运行某个镜像
docker run --name containerName -p port:port -v volume:/path1/path2 imageName
#查看当前运行中的容器
docker ps
#查看容器运行日志
docker log containerName
#进入正在运行镜像的容器
docker exex -it [id/containerName] /bin/bash
#停止运行中的容器/开始停止的容器
docker stop containerName / docker start containerName
#删除容器(先停止再删除)
docker rm containerName
#容器间如果想通过容器名进行网络连接,需要使用 docker run --link 来链接两个容器。docker run --link 将一个容器映射到当前运行的容器中
#(好像已经废除了,其原理是通过修改环境变量和配置文件实现的)。
docker run --link
docker数据卷(volume)命令
容器与数据耦合存在如下几个问题:
1.不便于修改,修改容器内的数据需要进入到容器内部。
2.数据不可复用,对容器内的修改在容器外是不可见的,不能被其他容器复用。
3.升级维护困难,升级容器需要删除旧容器,而数据又在容器内。
数据卷(volume) 是一个虚拟目录,指向宿主机文件系统中的某个目录(可以看作是一种映射)。将来容器删了,只要数据卷还在,对于新版本来讲,只要挂载在数据卷上就行了(重新映射到宿主机文件系统),可以共享以前旧的数据。
# ----- docker 数据卷命令 ----
#数据卷命令
docker volume [COMMONS]
docker volume create #(创建数据卷)
docker volume ls #(查看数据卷)
docker volume inspect #(查看数据卷存储位置)
docker volume rm #(删除指定数据卷)
docker volume prune #(删除未使用的数据卷)
docker run -v volume:/path1/path2 # 将容器内/path1/path2挂在到volume上
docker run -v /path1/path2:/path11/paht22 #基于目录直接挂载
Dockerfile自定义镜像
镜像结构
镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。它是一种分层结构,每一层都称为Layer。
简单的说就是:底层函数库–>环境配置–>依赖安装–>应用安装–>应用配置。
自定义镜像-Dockerfile
什么是Dockerfile?
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
常见指令
更新详细语法说明,请参考官网文档: https://docs.docker.com/engine/reference/builder
案例 - 基于Ubuntu镜像构建一个新镜像,运行一个java项目
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
步骤1:新建一个空文件夹demo
步骤2:将docker-demo.jar文件、jdk8.tar.gz拷贝到目录demo中,并新建一个文件dockerfile
步骤3:在demo目录中运行命令docker build -t xxx
关于dockerfile和docker-compose的区别(个人认为讲的很透彻了)
https://blog.csdn.net/weixin_41282397/article/details/82879246
docker-compose基础
https://www.cnblogs.com/minseo/p/11548177.html
docker相关的基础命令
https://www.jianshu.com/p/ca1623ac7723