1.什么是容器

有效的将单个操作系统的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使用需求。

1.1.容器化与虚拟化

一、容器   

容器是一个不依赖于操作系统,运行应用程序的环境。它通过Linux的Namespaces和Cgroups技术对应用程序进程进行隔离和限制的,Namespace的作用是隔离,它让应用进程只能看到Namespace内的世界;而Cgroups 的作用是限制分配给进程的宿主机资源。但对于宿主机来说,这些被“隔离”了的进程跟其他进程并没有太大区别。容器只是运行在宿主机上的一种特殊的进程,多个容器之间使用的还是同一个宿主机的操作系统内核。    

二、虚拟机   

虚拟机(VM)是计算机系统的仿真。简而言之,它可以在实际上是一台计算机的硬件上运行看起来很多单独的计算机。   

操作系统(OS)及其应用程序从单个主机服务器或主机服务器池共享硬件资源。每个虚拟机都需要自己的底层操作系统,并且硬件是虚拟化的。管理程序或虚拟机监视器是创建和运行虚拟机的软件,固件或硬件。它位于硬件和虚拟机之间,是虚拟化服务器所必需的。

1.2.底层区别

2.docker

Docker用Go编程语言编写,并利用Linux内核的多种功能来交付其功能。 Docker使用一种称为名称 空间的技术来提供容器的隔离工作区。 运行容器时,Docker会为该容器创建一组名称空间。 这些 名称空间提供了一层隔离。 容器的每个方面都在单独的名称空间中运行,并且对其的访问仅限于

该名称空间。

  • Client: 客户端;操作docker服务器的客户端(命令行或者界面)
  • Docker_Host:Docker主机;安装Docker服务的主机
  • Docker_Daemon:后台进程;运行在Docker服务器的后台进程
  • Containers:容器;在Docker服务器中的容器(一个容器一般是一个应用实例,容器间互相隔离)
  • Images:镜像、映像、程序包;Image是只读模板,其中包含创建Docker容器的说明。容器是由

Image运 行而来,Image固定不变。

  • Registries:仓库;存储Docker Image的地方。

3.docker隔离原理

3.1.namespace隔离

namespace

系统调用参数

隔离内容

UTS

CLONE_NEWUTS

主机和域名

IPC

CLONE_NEWIPC

信号量、消息队列和共享内存

PID

CLONE_NEWPID

进程编号

Network

CLONE_NEWNET

网络设备、网络栈、端口等

Mount

CLONE_NEWNS

挂载点(文件系统)

User

CLONE_NEWUSER

用户和用户组

3.2.cgroups资源限制

cgroup提供的主要功能如下:

资源限制:限制任务使用的资源总额,并在超过这个 配额 时发出提示

优先级分配:分配CPU时间片数量及磁盘IO带宽大小、控制任务运行的优先级

资源统计:统计系统资源使用量,如CPU使用时长、内存用量等

任务控制:对任务执行挂起、恢复等操作

子系统

功能

 cpu

使用调度程序控制任务对CPU的使用。

cpuacct(CPU Accounting)

自动生成cgroup中任务对CPU资源使用情况的报告。

cpuset

为cgroup中的任务分配独立的CPU(多处理器系统时)和内存。

devices

开启或关闭cgroup中任务对设备的访问

freezer

挂起或恢复cgroup中的任务

memory

设定cgroup中任务对内存使用量的限定,并生成这些任务对内存资源使用 情况的报告

perf_event(Linux CPU性能探测器)

使cgroup中的任务可以进行统一的性能测试

net_cls(Docker未使 用)

通过等级识别符标记网络数据包,从而允许Linux流量监控程序(Tra Controller)识别从具体cgroup中生成的数据包

4.docker常用命令

可以参考如下:

https://docs.docker.com/engine/reference/commandline/docker/

4.1.绑定与挂载

-v 宿主机绝对路径:Docker容器内部绝对路径:叫挂载;可能有空挂载问题

-v 不以/开头的路径:Docker容器内部绝对路径:叫绑定(docker会自动管理,docker不会把它当前目录,而把它当前卷)

5.Dockerfile组成

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。 基础的小linux系统。jdk

5.1.Dockerfile可以分为四部分

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 启动时执行指令

常用指令

FROM:指定基础镜像文件

MAINTAINER:维护者的信息
RUN:执行命令
EXPOSE:对外暴露的端口
ADD:复制文件到容器中,若是压缩文件会自动解压
COPY:复制文件到容器中,若是压缩文件不会自动解压
WORKDIR:改变工作目录
ENTRYPOINT:运行容器时执行的命令(default 自启动)

5.2.多阶段构建

使用多阶段构建,可以在一个 Dockerfile 中使用多个 FROM 语句。

每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像中保留下你需要的内容即可。

Go
FROM golang AS `build-env`
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server
FROM alpine
COPY `--from=build-env` /go/src/app/app-server /usr/local/bin/app-server

6.镜像压缩

  • 使用Alpine Linux
  • 只安装最少的依赖
  • 清理apt-get安装包   rm -rf /var/lib/apt/lists/*
  • 尽量将中间依赖的安装与卸载操作放在一个步骤中
  • 多阶段构建
  • 使用slim版本的镜像
  • 使用distroless镜像

7.补充点(前台进程)

        docker容器必须要有一个前台进程一直运行,因为docker容器并不是虚拟机,是利用linux的cgroupnamespace隔离的,在宿主机上本质是个隔离的进程。

例如一个容器的主进程是启动nginx,使用命令systemctl start nginx启动nginx,shell充当了主进程,fork了一个子进程启动了nginx后这个shell就退出了,nginx是shell的子进程,主进程消亡子进程也就停止了,容器也就会一运行就exited了。执行完成systemctl start nginx这个命令也就几秒钟,容器就退出了。

因此,在自定义镜像的时候,不要用后台方式启动,例如:

 nohup java -jar xxx.jar &

使用前台方式启动:

 java -jar xxx.jar

8.文件系统

Docker 使用存储驱动程序来存储镜像层,并将数据存储在容器的可写层中。容器的可写层在容器被删除后不会持久化,但适合存储运行时产生的临时数据。存储驱动程序针对空间效率进行了优化,但(取决于存储驱动程序)写入速度低于本机文件系统性能,尤其是对于使用写时复制文件系统的存储驱动程序。写入密集型应用程序(例如数据库存储)会受到性能开销的影响,特别是如果预先存在的数据存在于只读层中。

docker默认的overlay,不是AUFS


容器化会有3%左右的性能损耗

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐