工程化-前端自动化部署
参考链接:
前言
什么是 CI / CD
CI(Continuous Integration 持续集成):一种通过自动化测试持续验证代码库状态的方法。最好通过与版本控制集成来实现。
CD(Continuous Delivery / Deployment 持续交付/部署):一种成功通过 CI 后定期部署的方法,来确保交付。
为什么需要自动化部署
使发布软件更快更健壮。
主要做的工作流程:
- 自动 lint;
- 自动类型检测;
- 自动单元测试;
- 自动构建到 docker 镜像中;
- 自动部署,发布 docker 镜像;
如果就在本地的话,可以除了最后一步自动部署不做。
解决的问题
打包耗时
特殊环境隔离
打包环境的差异,linux 和 windows 的编码格式不同。
环境的差异,导致编码格式不同,当重新编译时,会重新编译未修改文件,造成打包耗时,上线后需要重新下载新的打包文件(hash值已经改变,会认为是需要下载新的文件不使用缓存,虽然文件内容没有改变)。
自动化流程工具
Jenkins (https://jenkins.io)
Gitlab CI/CD (https://gitlab.com)
Github Actions (https://github.com/features/actions)
Travis CI (https://travis-ci.org)
Drone (https://www.drone.io)
之前公司使用的是 gitea(项目托管) + drone 搭配
简易的 CI 系统
参考链接:http://aosabook.org/en/500L/a-continuous-integration-system.html
自动化部署流程
Docker
文档:https://docs.docker.com/get-started/
参考文章:docker 入门教程 - 阮一峰
Docker 可以灵活的创建/销毁/管理多个“服务器”,这些“服务器”被称为 容器 (container)
Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容器解决方案。
Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
总体来说,Docker 的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
为什么要用 Docker
- 环境统一。利用镜像统一开发环境和生产环境,避免因为环境因素导致的问题。
- 便于回滚。版本控制,如果环境出现了问题,可以回滚到之前版本。
- 环境隔离。
- 高效并节省资源。作用类似服务器 / 虚拟机,可以直接在 Docker 中布置特殊环境且不包含操作系统。
用途
- 提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
- 提供弹性的云服务。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
- 组建微服务架构。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。
- 版本管理。
Docker 安装 & 实践
windows 安装链接:https://docs.docker.com/desktop/windows/install/
操作指南:https://docs.docker.com/get-started/overview/
image 仓库:https://hub.docker.com/
安装好后进行检测是否安装成功:
docker version # 查看版本信息
docker info # 查看docker状态
Docker是服务器-客户端架构。命令运行docker命令时,需要本机有Docker服务。
# service 命令用法
service docker start
# systemctl 命令用法
systemctl start docker
image (镜像) 文件:Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
容器文件:image 生成的容器实例,本身也是一个文件。一旦容器生成,就会同时存在两个文件,image 文件和容器文件。
image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image。
docker image ls # 列出本机的所有 image 文件
docker image rm [imageName] # 删除某个 image 文件
docker container ls # 列出本机正在运行的容器
docker container ls --all # 列出本机所有容器
docker container rm [containerID] # 删除容器文件
运行 image
拉取 image 到本地
docker image pull library/hello-world
# 或 Docker官方的 image 都在library组里,是默认组,可省略
docker image pull hello-world
# 拉取成功后 查看镜像
docker image ls
运行 image 文件,会生成一个正在运行的容器实例。docker container run
命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。每次运行都会新建容器。
docker container run hello-world
# 运行已经运行过的container
docker container start [containerID] # 用来启动已经生成、已经停止运行的容器文件
如果 image 提供的是服务,如 Ubuntu系统 docker container run -it ubuntu bash
,则需要手动终止服务 docker
container kill [containId]
。
制作 docker 容器
Dockerfile 文件: 配置 image 的文件。docker 会更具该文件生成二进制的 image 文件。
项目下新建 .dockerignore
文件,配置不需要打包的文件名。
新建 Dockerfile
文件,内容:
FROM node:8.4:该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node。
COPY . /app:将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录。
WORKDIR /app:指定接下来的工作路径为/app。
RUN npm install:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。
EXPOSE 3000:将容器 3000 端口暴露出来, 允许外部连接这个端口。
在当前目录下,创建 image 文件:
docker image build -t [dockerName] . # 默认标签是 latest
# 或
docker image build -t [dockerName]:[tag] .
运行成功后查看新生成的 image 文件:
docker image ls
生成容器
docker container run -p 8000:3000 -it koa-demo /bin/bash
# 或者
docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
-p
参数:容器的 3000 端口映射到本机的 8000 端口。-it
参数:容器的 Shell 映射到当前的 Shell,然后你在本机窗口输入的命令,就会传入容器。koa-demo:0.0.1
:image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。/bin/bash
:容器启动以后,内部第一个执行的命令。这里是启动 Bash,保证用户可以使用 Shell。
Node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射(map)
可以在 run 后加 –rm 配置,在容器终止运行后自动删除容器文件。
可以在 Dockerfile 文件中设置 CMD 命令,但是就不能使用 /bin/bash 了,会覆盖配置的 CMD 命令。
在容器中运行项目
ctrl + c:停止 Node 进程
ctrl + d / exit:退出容器 或者在另一个终端中使用命令 docker countainer kill [containerID]
进行终止服务。
发布 image
需要在 docker 网站上注册账户
# 登录注册号的账户
docker login
# 为本地的 image 标注用户名和版本(可选)
docker image tag [imageName] [username]/[repository]:[tag]
# 例如:
docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1
# 重新构建一下 image 文件
docker image build -t [username]/[repository]:[tag] .
# 发布 image 文件
docker image push [username]/[repository]:[tag]
Docker 其他命令
# 终止容器运行,相当于向容器里面的主进程发出 SIGTERM 信号,然后过一段时间再发出 SIGKILL 信号
# 和 kill 命令的差别是 可以进行一段收尾操作后再杀死容器,避免操作丢失
docker container stop [containerID]
# 查看 docker 容器的输出 即容器里面 Shell 的标准输出
docker container logs [containerID]
# 进入一个正在运行的 docker 容器 进入容器后可以使用 shell 命令
docker container exec -it [containerID] /bin/bash
# 用于从正在运行的 Docker 容器里面,将文件拷贝到本机
docker container cp [containID]:[/path/to/file] . # 拷贝到当前目录