Docker由dotCloud的内部服务演变而来,13年开源,Docker使用Go语言开发,基于Linux内核的cgroup,namespace,对进程进行封装隔离,由于隔离的进程之间以及宿主之间相互独立,因此也称其为容器。
Docker的优势
由于容器是进程级别的,与传统虚拟化解决方案相比:
- 系统资源利用率更高
- 启动时间更快
- 统一运行环境
- 持续集成和部署
- 维护和扩展更简单
基本概念
镜像(Image)
Docker把应用程序及其依赖,打包在image文件里面。通过这个文件,才能生 Docker容器。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
实际开发中,一个image文件往往通过继承另一个image文件,以定制自己所需的内容,构建新的镜像。
容器(Container)
容器由镜像实例化而来,可以被建、启、停、删、止。容器实质是个进程,但是与宿主独立,有自己的namespace,可以理解成”沙箱”。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样,这种特性使得容器封装的应用比直接在宿主运行更加安全。
Dockfile
Dockerfile 是一个文本文件,其内包含了一条条的指令,用来配置 image。Docker 根据 该文件生成二进制的 image 文件。特别指出,Dockerfile 中每一个指令都会建立一层,每一条指令的内容,就是描述该层应当如何构建,在写Dockfile的时候一定要注意这一点,对于优化镜像大小有重要作用。
几个必要的指令介绍
- FROM
|
|
定义镜像基准,如上镜像继承自node8.9.3版本,镜像首选本地,不存在从公共仓库下载(或者私有仓库)。
- RUN
|
|
执行命令,并commit镜像。
- EXPOSE
告诉容器在运行时要监听的端口,端口为容器内部端口,外部访问不到,需要隐射到外部接口,在docker run的时候,使用-p选项
- COPY
|
|
将构建上下文中source拷贝到container的文件系统对应的路径target下。另外还有个相似的命令ADD,相比COPY,ADD支持远程URL文件和自动解压缩。
- WORKDIR
WORKDIR指令用于设置Dockerfile中的RUN、CMD和ENTRYPOINT指令执行命令的工作目录(默认为/目录),该指令在Dockerfile文件中可以出现多次,如果使用相对路径则为相对于WORKDIR上一次的值。
安装
安装完成之后可以尝试
|
|
显示正常的话,运行一个nginx容器
|
|
首次执行,由于本地没有镜像,会从hub上拉取安装。
|
|
服务运行后,可以访问http://localhost,如果看到了 “Welcome to nginx!”,就说明 Docker for Mac 安装成功了。
停止并删除Nginx服务器
|
|
前端中的Docker
整个前端项目研发生命周期包括需求、设计、开发、测试、上线,Docker配合CI,让工作焕然一新。
开发阶段
目标提供统一的研发环境,node版本,工程化工具等。一个简单的例子:
- 创建Dockerfile文件
|
|
- 构建镜像
|
|
- 项目运行
|
|
具体项目创建的镜像规模大小不同,以上的方案只是使用docker的思路,实际方案还是要根据项目来定,对于中小型项目,环境版本的差异给开发带来的问题基本上可以忽略,工程化相关的依赖也不会很复杂,如果可以,可以定制一套项目通用的工具,通过发布到私服管理,减少项目维护成本。
测试
目标提供测试一个一键运行的前端环境。一个简单的例子:
- 创建Dockerfile文件
|
|
之后发布镜像,之后就可以通过该镜像一键启动前端环境。
部署
一次典型的前端部署过程,先后经过安装依赖npm install,编译打包npm run build,启动静态服务器。
- 创建Dockerfile文件
|
|
通过镜像缓存,npm install过程可以节省一半的时间。
实际开发过程配合CI,各阶段都会有调整,效率也会更高。比如我们内部有自己的一套运维系统,部署阶段Dockerfile就得调整,需要将安装依赖和build分离。
前端容器化升级没有标准的方案,任何一步都需要结合实际定制,但是方向是一致的,充分利用容器的特点,打造简单、高速,统一的前端开发环境。