部署基于Gitlab+Docker+Rancher+Harbor的前端项目这一篇就够了

momenta 中台开发工程师
6 人赞同了该文章

就目前的形势看,一家公司的运维体系不承载在 Docker+Harbor(或 Pouch 等同类平台)之上都不好意思说自己的互联网公司。当然这些技术也不适用于全部公司,技术在迭代,平台也一样,把我使用的工具和大家分享下,一起成长(文章中扩展可按需Google)。

Docker

docker的架构图如下:

从图中可以看出几个组成部分

  • docker client: 即 docker 命令行工具
  • docker host: 宿主机,docker daemon 的运行环境服务器
  • docker daemondocker 的守护进程,docker client 通过命令行与 docker daemon 交互
  • container: 最小型的一个操作系统环境,可以对各种服务以及应用容器化
  • image: 镜像,可以理解为一个容器的模板配置,通过一个镜像可以启动多个容器
  • registry: 镜像仓库,存储大量镜像,可以从镜像仓库拉取和推送镜像

我在刚接触到Docker的时候,产生了一种错觉--这不就是个性能不错的虚拟机吗?显然他能做的远比虚拟机多得多。具体表现在 Docker 不是在宿主机上虚拟出一套硬件后再虚拟出一个操作系统,而是让 Docker 容器里面的进程直接运行在宿主机上(Docker 会做文件、网络等的隔离),这样一来 Docker 会 “体积更轻、跑的更快、同宿主机下可创建的个数更多”(类似于一个一个的沙箱,互相不暴露接口,互相不影响)。

Docker 中有三个核心概念:Image、Container、Repository。

  • Image: 和 windows 的那种 iso 镜像相比,Docker 中的镜像是分层的,可复用的,而非简单的一堆文件迭在一起(类似于一个压缩包的源码和一个 git 仓库的区别)。
  • Container: 容器的存在离不开镜像的支持,他是镜像运行时的一个载体(类似于实例和类的关系)。依托 Docker 的虚拟化技术,给容器创建了独立的端口、进程、文件等“空间”,Container 就是一个与宿机隔离 “沙箱”。沙箱可在宿主机之间可以进行 port、volumes、network 等的通信。
  • Repository: Docker 的仓库和 git 的仓库比较相似,拥有仓库名、tag。在本地构建完镜像之后,即可通过仓库进行镜像的分发。常用的 Docker hub 有 https://hub.docker.com/ 、 https://cr.console.aliyun.com/ 等。

底层原理

docker 底层使用了一些 linux 内核的特性,大概有 namespacecgroups 和 ufs

namespace

docker 使用 linux namespace 构建隔离的环境,它由以下 namespace 组成

  • pid: 隔离进程
  • net: 隔离网络
  • ipc: 隔离 IPC
  • mnt: 隔离文件系统挂载
  • uts: 隔离hostname
  • user: 隔离uid/gid

control groups

也叫 cgroups,限制资源配额,比如某个容器只能使用 100M 内存

Union file systems

UnionFS 是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加。docker 的镜像与容器就是分层存储,可用的存储引擎有 aufsoverlay 等。

镜像

镜像是一份用来创造容器的配置文件,而容器可以视作最小型的一个操作系统(类似于容器由镜像解压而来)。

docker 的镜像和容器都使用了 unionFS 做分层存储,镜像作为只读层是共享的,而容器在镜像之上附加了一层可写层,最大程度地减少了空间的浪费,详见下图

镜像仓库与拉取

我们可以在官方镜像仓库拉取镜像,也可以自己构造镜像

# 加入拉取一个 node:alpine 的镜像
$ docker pull node:alpine # 查看镜像信息
$ docker inspect node:alpine # 列出所有镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node alpine f20a6d8b6721 13 days ago 105MB
mongo latest 965553e202a4 2 weeks ago 363MB
centos latest 9f38484d220f 8 months ago

镜像的构造与发布

镜像仓库里找不到全部的镜像,这时我们需要为自己的业务去构建镜像了。

-t 指定标签

# -t node-base:10: 镜像以及版本号
# .: 指当前路径
$ docker build -t node-base:10 ./
#使用docker push将镜像推送到镜像仓库
$ docker push node-base:10

Dockerfile

在使用docker部署自己应用时,往往需要自己构建镜像。docker使用Dockerfile作为配置文件构建镜像,简单看一个node应用构建的dockerfile

FROM node:alpine

ADD package.json package-lock.json /code/
WORKDIR /code RUN npm install --production
#.为当前文件目录 /code为镜像内的目录
ADD . /code CMD npm start

FROM

基于一个旧的镜像,格式如下

FROM <image> [AS <name>]
# 在多阶段构建时会用到
FROM <image>[:<tag>] [AS <name>]

ADD

把目录,或者 url 地址文件加入到镜像的文件系统中

ADD [--chown=<user>:<group>] <src>... <dest>

RUN

执行命令,由于 ufs 的文件系统,它会在当前镜像的顶层新增一层

RUN <command>

CMD

指定容器如何启动

一个 Dockerfile 中只允许有一个 CMD

# exec form, this is the preferred form
CMD ["executable","param1","param2"]
# as default parameters to ENTRYPOINT
CMD ["param1","param2"]
# shell form
CMD command param1 param2

容器

镜像与容器的关系,类似于代码与进程的关系。

  • docker run 创建容器
  • docker stop 停止容器
  • docker rm 删除容器

创建容器

基于 nginx 镜像创建一个最简单的容器:启动一个最简单的 http 服务

使用 docker run 来启动容器,docker ps 查看容器启动状态

$ docker run -d --name nginx -p 8888:80 nginx:alpine
$ docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
404e88f0d90c nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:8888->80/tcp nginx
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

其中:

  • -d: 启动一个 daemon 进程
  • --name: 为容器指定名称
  • -p host-port:container-port: 宿主机与容器端口映射,方便容器对外提供服务
  • nginx:alpine: 基于该镜像创建容器

此时在宿主机使用 curl 测试容器提供的服务是否正常

curl localhost:8888
会在下方打印出html代码

使用docker exec -it container-name命令可以进入容器的环境中

容器管理

docker ps 列出所有容器

$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

404e88f0d90c        nginx:alpine         "nginx -g 'daemon of…" 4 minutes ago       Up 4 minutes        0.0.0.0:8888->80/tcp     nginx
498e7d74fb4f nginx:alpine "nginx -g 'daemon of…" 7 minutes ago Up 7 minutes 80/tcp lucid_mirzakhani 2ce
10556dc8f redis:4.0.6-alpine "docker-entrypoint.s…" 2 months ago Up 2 months 0.0.0.0:6379->6379/tcp apolloserverstarter_redis_1

docker port 查看容器端口映射

$ docker port nginx 80/tcp -> 0.0.0.0:8888

docker stats 查看容器资源占用

$ docker stats nginx CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
404e88f0d90c nginx 0.00% 1.395MiB / 1.796GiB 0.08% 632B / 1.27kB 0B / 0B 2

Harbor

它的目标是帮助用户迅速搭建一个企业级的 Docker registry 服务。它以 Docker 公司开源的 registry 为基础,提供了管理UI,基于角色的访问控制(Role Based Access Control),AD/LDAP集成、以及审计日志(Auditlogging) 等企业用户需求的功能,同时还原生支持中文。Harbor 的每个组件都是以 Docker 容器的形式构建的,使用 Docker Compose 来对它进行部署。


Rancher

rancher 容器管理平台 在生产环境中轻松快捷的部署和管理容器 管理K8s 内置CI/CD 快速搭建 导入和纳管 集中式身份。

准确的说,Rancher是一套容器管理打包方案,支持三种编排引擎:Kubernetes,Swarm,还有Rancher自己开发的Cattle(最近好像换成了Mesos)。从功能的完整性和易用性来看,Rancher甚至可以算得上一个商业软件了,部署极其简单,这也是我们选择它作为入门级容器管理平台的原因。以下是Rancher的组件图:

虽然Rancher非常的易用,但是rancher也不都是优点,随着后端机器和项目数量的增加,它的一些问题也更易暴露,UI卡顿,发布速度越来越慢,1.3之后甚至经常出现服务的预期状态(容器数量,版本)无法被保证,卡在发布中或者完成中状态。团队后续可能会考虑使用kubernetes。

基于GitLab的CI/CD

个人理解就是把代码测试、打包、发布等工作交给一些工具来自动完成。这样可以提高效率,减少失误,开发人员只需要关心开发和提交代码到git就可以了。

使用工具如gitlab-CI,这种方式的原理就是为项目在自己的服务器安装上注册gitlab-runner,注册会有一个token,服务器上运行gitlab-runner后,runner会轮询的发送带tokenhttp请求给gitlab,如果gitlab有任务了,(一般是git push),那么会把任务信息返回给runner,然后runner就开始调用注册时选的Executor(我是用的shell)来执行项目根目录下的配置文件.gitlab-ci.yml,执行后把结果反馈给gitlab
详细的工作原理请参考:

当谈到 GitLab CI 的时候,我们该聊些什么(上篇)​www.upyun.com

对GitLab-CI,GitLab-Runner等概念不清楚,参考:

GitLab-CI与GitLab-Runner - CNundefined - 博客园​www.cnblogs.com

开发环境要求

1、gitlab远程仓库

2、本地配置文件gitLab-ci.yml

stages:
- test
- build
- push
- deploy variables:
image:.......
.deploy_test_refs: &deploy_test_refs
- development
- test .deploy_production_refs: &deploy_production_refs
- master # all_deploy_refs = deploy_test_refs + deploy_production_refs, but YAML cannot concat arrays
.all_deploy_refs: &all_deploy_refs
- development
- test
- master

3、服务器上配置nginx、gitlab-runner(注册runner,修改runner的权限)

sudo chown -R gitlab-runner:gitlab-runner /home/gitlab-runner
sudo chmod -R 777 /home/gitlab-runner

开启runner

 gitlab-runner run

4、本地配置好node、git

配置成功展示界面:

参考文章:

前端项目基于GitLab-CI的持续集成/持续部署(CI/CD) - 掘金​juejin.im

使用Docker+Rancher(结合gitlab)+Harbor的具体流程

环境准备

1、macpro+多出来的服务器(没有也可以)

2、docker 版本:18 (最新也成)

3、docker-compose:1.24 (最新也成)

4、Harbor:1.1.2(最新也行)

安装docker

brew cask install docker

打开docker客户端之后再item中输入

docker login 域名

然后就可以在客户端中输入用户名与密码,由于作者使用公司的内网(不涉及业务内容),因此需要事先配置好推到harbor内的权限

处理过权限问题,之后的阶段就可以进入相应的文件夹进行手动的配置,前提是要先写好一个类似于build.sh的文件,内部配置好各种命令,build文件中的内容

function build() {
echo "------------------------------ BUILD ------------------------------" (cd frontend && env COMMIT_ID=${COMMIT_ID} BUILD_TIME=${TIMESTAMP2} $(cat .env.${DEPLOY}) yarn build) rm -rf docker/frontend
cp -r frontend/build docker/frontend # local IMAGES=`docker images -q -f 'dangling=true'`
# [ "$IMAGES" != '' ] && docker rmi -f ${IMAGES}
# local IMAGES=`docker images -q -f "label=app=${APP}"`
# [ "$IMAGES" != '' ] && docker rmi -f ${IMAGES} docker build -t ${TAG} ${DOCKER_DIR}
} function push() {
echo "------------------------------ PUSH ------------------------------" docker push ${TAG}
export SERVICE_NAME NAMESPACE IMAGE_URL
envsubst <deploy/${APP}.tmpl || :
} function all() {
build
push
} function usage() {
echo "Usage: $0 [build|push|all] [production|test]"
} function main() {
case ${CMD} in
b*) build ;;
p*) push ;;
a*) all ;;
*) usage ;;
esac
} init $@
main

配置好后且确保权限无误即可执行:

./build.sh all test

配置执行后会直接push镜像到harbor内(事先配置好)。

查看docker中的各种内容的命令:

docker ps

See 'docker --help'
MacBook-Pro:111$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

查看已经打出的镜像

docker images

MacBook-Pro:111$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.momenta.works/cla/milky-web 191202-test 1532be927f8d 5 hours ago 18.7MB
registry.momenta.works/cla/milky-web 191128-test 1af4615c4cb3 4 days ago 18.7MB
registry.momenta.works/cla/milky-web 191121-test f6cb17d8b0a0 11 days ago 18.7MB
registry.momenta.works/cla/milky-web 191120-production 3e11cd30dd89 11 days ago 18.7MB
registry.momenta.works/cla/milky-web 191120-test ee0909ecd9f7 11 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 13993e12200a 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 8de9f053335a 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 7828f22eb355 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> c23b51230cad 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> f5169dc0f863 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> eb5463875800 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 618d7f09c2f6 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> b682475e4d9b 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 85420f94ff4c 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 972cc2cc9c7c 12 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 08098283428a 12 days ago 18.7MB
registry.momenta.works/cla/milky-web 191119-test bdc5d28d724f 12 days ago 18.7MB
registry.momenta.works/cla/milky-web 191118-test 3aca38625579 13 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> 5b4dcdc14def 13 days ago 18.7MB
registry.momenta.works/cla/milky-web <none> f40db7e196fb 2 weeks ago 18.7MB
registry.momenta.works/cla/milky-web <none> ff2c5da90a90 2 weeks ago 18.7MB
registry.momenta.works/cla/milky-web 191116-test c2e20e00fa04 2 weeks ago 18.7MB
registry.momenta.works/cla/milky-web 191115-test 2d0ebce7a82c 2 weeks ago 18.7MB
nginx 1.15-alpine dd025cdfe837 6 months ago 16.1MB

将打好的镜像上传到相对应的harbor仓库中:

docker push registry.momenta.works/cla/milky-web:-test

在rancher中对相应的服务(微服务)edit相应的镜像地址即可

以上是权限没有配置好情况下的操作

假如说我们的权限配置没有问题了,直接执行build.sh即可(省略中间步骤),最后在rancher中edit相应的镜像即可

未完待续(harbor与rancher的使用及配置会在近期附上)

Happy Hacking

部署基于Gitlab+Docker+Rancher+Harbor的前端项目这一篇就够了的更多相关文章

  1. 关于 Docker 镜像的操作,看完这篇就够啦 !(下)

    紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...

  2. node项目自动化部署--基于Jenkins,Docker,Github(1)安装Jenkins

    前言 每次项目代码更新后都要重新部署,如果只有一台服务器还好. 但是如果是分布式系统,动不动就很多台服务器,所以代码的自动部署就显得十分重要了. 这里用几篇文章来记录一下如何使用Jenkins,Doc ...

  3. 一键部署基于GitLab的自托管Git项目仓库

    https://market.azure.cn/Vhd/Show?vhdId=9851&version=11921 产品详情 产品介绍GitLab https://about.gitlab.c ...

  4. node项目自动化部署--基于Jenkins,Docker,Github(3)自动化部署

    GitHub仓库 由于现在的代码基本上都是多人合作开发,所以肯定会用到像 git 这样的版本控制工具 所以这里使用 GitHub 来做一个演示 首先我们需要在github上新建一个仓库 点击New来新 ...

  5. node项目自动化部署--基于Jenkins,Docker,Github(2)配置节点

    上一篇文章中准备工作已经完成的差不多了 这一篇主要讲解 Jenkins 上面的相关配置 为了让代码部署到所有的子节点上 所以我们首先需要在 Jenkins 中添加我们希望代码部署到的节点 配置节点 首 ...

  6. 使用docker+jenkins构建nodejs前端项目

    前文使用Docker搭建Jenkins+Docker持续集成环境我们已经搭建了基于docker+jenkins的持续集成环境,并构建了基于maven的项目.这一节,我们继续扩展功能,增加对Nodejs ...

  7. Docker+Jenkins持续集成环境(2)使用docker+jenkins构建nodejs前端项目

    前文使用Docker搭建Jenkins+Docker持续集成环境我们已经搭建了基于docker+jenkins的持续集成环境,并构建了基于maven的项目.这一节,我们继续扩展功能,增加对Nodejs ...

  8. 在已部署好的docker环境下配置nginx项目路径

    第一步:申请一个docker连接账号,可以借用putty工具,如果使用sublime,可以下载sftp插件,上传.下载来同步你线上线下的文件: 第二步:修改nginx区域配置文件,在conf文件夹里放 ...

  9. 基于vue cli 3.0创建前端项目并安装cube-ui

    前提条件: 安装node.js. 国内的开发者最好先配置淘宝镜像. 之后用cnpm来代替npm命令. 项目创建过程: 打开cmd,输入命令进入目标工作空间,以本机项目为例: cd /d d: cd D ...

随机推荐

  1. C语言入门:一维数组的概要

    数组的概念: 具有相同数据的有序集合 一维数组的定义格式: int a[5]; 类型说明符  数组名(标识符)[常量表达式(长度)]; 一维数组下标 : 数组的下标 从0开始  最大下标值 为 数组的 ...

  2. ios--->特定构造方法NS_DESIGNATED_INITIALIZER

    特定构造方法 1> 后面带有NS_DESIGNATED_INITIALIZER的方法,就是特定构造方法 2> 子类如果重写了父类的[特定构造方法],那么必须用super调用父类的[特定构造 ...

  3. 通过 SCF Component 轻松构建 REST API,再也不用熬夜加班了

    本教程将分享如何通过 Serverless SCF Component .云函数 SCF 及 API 网关组件,快速构建一个 REST API 并实现 GET/PUT 操作. 当一个应用需要对第三方提 ...

  4. 五、Shell运算

    整数值运算 使用expr命令:只能做整数运算,默认返回计算结果 格式: expr 整数1 运算符 整数2 ... 整数值可以有变量提供,直接给出运算结果 + 加法 expr 43 + 21 .expr ...

  5. Request和Session的生命周期

    request的生命周期是request请求域,一个请求结束,则request结束 session的生命周期是session会话域,打开一个浏览器请求一个网站的页面后,Session开始,当sessi ...

  6. 机器学习(ML)七之模型选择、欠拟合和过拟合

    训练误差和泛化误差 需要区分训练误差(training error)和泛化误差(generalization error).前者指模型在训练数据集上表现出的误差,后者指模型在任意一个测试数据样本上表现 ...

  7. python代码迷之错误(ModuleNotFoundError: No module named 'caffe.proto')

    1.pandas.read_csv book[n]下的print(n) 总图片数是少一张的,print(n)发现也是少了一个序号 仔细查找后发现缺少99号,即最后一张图片没有被读取.print(m)时 ...

  8. 对MYSQL注入相关内容及部分Trick的归类小结

    前言 最近在给学校的社团成员进行web安全方面的培训,由于在mysql注入这一块知识点挺杂的,入门容易,精通较难,网上相对比较全的资料也比较少,大多都是一个比较散的知识点,所以我打算将我在学习过程中遇 ...

  9. Java类的加载过程与ClassLoader的理解及测试

    当程序准备运行某个类,但该类还未被加载到内存中时,会经过以下三个步骤进行类的加载: 类的加载(Load)→类的连接(Link)→类的初始化(Initialize) 加载:类经过javac.exe编译的 ...

  10. XLNet:运行机制及和Bert的异同比较

    这两天,XLNet貌似也引起了NLP圈的极大关注,从实验数据看,在某些场景下,确实XLNet相对Bert有很大幅度的提升.就像我们之前说的,感觉Bert打开两阶段模式的魔法盒开关后,在这条路上,会有越 ...