前端自動(dòng)化集成部署交付實(shí)踐

后端 | 前端自動(dòng)化集成部署交付實(shí)踐.png

前言

隨著前后端分離應(yīng)用模式的推廣奏属,前端項(xiàng)目可獨(dú)立部署維護(hù)上線藻肄,不再僅僅將前端開發(fā)后打包的文件直接丟到一個(gè)文件目錄下就完事大吉了,現(xiàn)在對(duì)前端來說也需要了解運(yùn)維的相關(guān)知識(shí)皆串,本文旨在介紹一些相關(guān)的運(yùn)維概念以及一些前端運(yùn)維的實(shí)踐。

CI/CD

cicd

持續(xù)集成

continuous integration 持續(xù)集成是一種軟件實(shí)踐眉枕,流程為:開發(fā) => 打包 => 集成 => 測(cè)試

持續(xù)交付

continuous delivery 持續(xù)交付是一種軟件工程手法恶复,流程為:測(cè)試 => 發(fā)布

持續(xù)部署

continous deployment 持續(xù)部署是在持續(xù)交付的管道中發(fā)布版本給最終用戶的一種軟件工程流程,流程為:發(fā)布 => 部署上線

持續(xù)集成速挑、持續(xù)交付谤牡、持續(xù)部署是發(fā)布流程的不同階段

Docker

docker

容器 + 鏡像

docker 是一個(gè)開源的應(yīng)用容器引擎。開發(fā)者可以打包自己的應(yīng)用到容器里面姥宝,然后遷移到其他機(jī)器的 docker 應(yīng)用中翅萤;開發(fā)者可以快速制作一個(gè)自己自定義的鏡像,快速分享腊满,也可以上傳到鏡像庫(kù)進(jìn)行存取和管理套么;容器之間相互隔離不沖突,硬件資源共享碳蛋。

Docker in Docker

容器內(nèi)僅部署 docker 命令行工具(作為客戶端)胚泌,實(shí)際執(zhí)行交由宿主機(jī)內(nèi)的 docker-engine(服務(wù)器)

Jenkins

jenkins

概念

Jenkins 是一個(gè)基于Java語言開發(fā)的CI持續(xù)構(gòu)建工具,主要用于持續(xù)疮蹦、自動(dòng)的構(gòu)建/測(cè)試軟件項(xiàng)目。它可以執(zhí)行你預(yù)先設(shè)定好的設(shè)置和腳本茸炒,也可以和 Git工具做集成愕乎,實(shí)現(xiàn)自動(dòng)觸發(fā)和定時(shí)觸發(fā)器構(gòu)建阵苇。

Gitlab

gitlab

概念

gitlab既是一種服務(wù),也是一種軟件感论。既可以在gitlab.com上去租用服務(wù)绅项,也可以下載gitlab阮籍你自己搭建服務(wù)

Nginx

nginx

概念

Nginx采用C進(jìn)行編寫,處理靜態(tài)文件比肄,索引文件以及自動(dòng)索引;打開文件描述符緩沖快耿。無緩存的反向代理加速,簡(jiǎn)單的負(fù)載均衡和容錯(cuò)芳绩。FastCGI掀亥,簡(jiǎn)單的負(fù)載均衡和容錯(cuò)。模塊化的結(jié)構(gòu)妥色。

Nginx是一個(gè)高性能的HTTP和反向代理web服務(wù)器搪花,同時(shí)也提供了IMAP/POP3/SMTP服務(wù)

Nexus

nexus

概念

制品倉(cāng)庫(kù): 構(gòu)建過程的輸出物,包括軟件包嘹害,測(cè)試報(bào)告撮竿,應(yīng)用配置文件等可在服務(wù)器上直接 運(yùn)行或可查看二進(jìn)制形式的文件,通常稱之為二進(jìn)制軟件制品笔呀。具有版本管理幢踏,歷史管理,權(quán)限校驗(yàn)等功能许师。

Nexus可在自己的局域網(wǎng)內(nèi)搭建自己的遠(yuǎn)程倉(cāng)庫(kù)服務(wù)器房蝉,稱為私服,私服服務(wù)器即是公司內(nèi)部的maven遠(yuǎn)程倉(cāng)庫(kù)枯跑,私服還充當(dāng)一個(gè)代理服務(wù)器惨驶,可從互聯(lián)網(wǎng)中央倉(cāng)庫(kù)自動(dòng)下載

  • proxy 本地倉(cāng)庫(kù),通常我們會(huì)部署自己的構(gòu)件到這一類型的倉(cāng)庫(kù)敛助。比如公司的第二方庫(kù)

  • hosted 代理倉(cāng)庫(kù)粗卜,它們被用來代理遠(yuǎn)程的公共倉(cāng)庫(kù)令野,如maven中央倉(cāng)庫(kù)

  • group 倉(cāng)庫(kù)組踱启,用來合并多個(gè)hosted/proxy倉(cāng)庫(kù),當(dāng)你的項(xiàng)目希望在多個(gè)repository使用資源時(shí)就不需要多次引用了钠四,只需要引用一個(gè)group即可

Ansible

ansible

概念

ansible是基于Python開發(fā)的自動(dòng)化運(yùn)維工具焕数。其優(yōu)勢(shì)在于可以批量操作纱昧,基本原理是通過ansible的核心進(jìn)行通過ssh傳輸?shù)耐ㄐ胚M(jìn)行相關(guān)的分發(fā)處理,進(jìn)行user與host的通信

Modules

執(zhí)行命令的功能模塊堡赔,Ansible2.3版本為止识脆,共有1039個(gè)模塊。還可以自定義模塊

Inventory

管理主機(jī)的清單,默認(rèn)是/etc/ansible/hosts文件

Playbook

任務(wù)劇本(又稱任務(wù)集)灼捂,編排定義Ansible任務(wù)集的配置文件离例,由Ansible順序依次執(zhí)行,yaml格式

Plugins

插件悉稠,模塊功能的補(bǔ)充宫蛆,常有連接類型插件,循環(huán)插件的猛,變量插件耀盗,過濾插件,插件功能用的較少

API

提供給第三方程序調(diào)用的應(yīng)用程序編程接口

實(shí)踐

操作環(huán)境: linux/centos7

操作內(nèi)容: 一臺(tái) gitlab + jenkins + ansible 服務(wù)器推送多臺(tái) nginx 服務(wù)器

docker

  1. 安裝依賴
yum install -y yum-utils device-mapper-persistent-data lvm2
  1. 使用阿里云源安裝
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum install docker-ce
  1. 啟動(dòng)docker
systemctl start docker

systemctl enable docker
  1. 可配置阿里云容器鏡像加速器

阿里云容器鏡像服務(wù)

gitlab + jenkins + ansible

安裝jenkins

  1. 安裝防火墻
yum install firewalld systemd -y
service firewalld start
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="xxx.xx.x.x/16" accept"
systemctl reload firewalld
  1. 編寫Dockerfile
FROM jenkins/jenkins
USER root
# 清除了基礎(chǔ)鏡像設(shè)置的源卦尊,切換成阿里云源
RUN echo '' > /etc/apt/sources.list.d/jessie-backports.list \
  && echo "deb http://mirrors.aliyun.com/debian jessie main contrib non-free" > /etc/apt/sources.list \
  && echo "deb http://mirrors.aliyun.com/debian jessie-updates main contrib non-free" >> /etc/apt/sources.list \
  && echo "deb http://mirrors.aliyun.com/debian-security jessie/updates main contrib non-free" >> /etc/apt/sources.list
# 更新源并安裝缺少的包
RUN apt-get update && apt-get install -y libltdl7
ARG dockerGid=999

RUN echo "docker:x:${dockerGid}:jenkins" >> /etc/group
  1. 構(gòu)建jenkins鏡像
docker build -t local/jenkins .
  1. 啟動(dòng)鏡像

新建/home/jenkins/目錄叛拷,將jenkins目錄外掛到宿主機(jī)內(nèi)

mkdir /home/jenkins

chown -R 1000 /home/jenkins/

鏡像創(chuàng)建容器并啟動(dòng)

docker run -itd --name jenkins -p 8080:8080 -p 50000:50000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
-v /home/jenkins:/var/jenkins_home \
--restart always \
--user root local/jenkins
  1. 啟動(dòng)jenkins

釋放8080和50000端口

firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --add-port=50000/tcp --permanent

systemctl reload firewalld
  1. 初始化jenkins配置

修改密碼 => 下載插件 => 重啟容器

初始化jenkins后會(huì)有一個(gè)初始密碼,可通過docker exec -it jenkins /bin/bash進(jìn)入容器后查看cat /var/jenkins_home/secrets/initialAdminPassword

  1. 配置公鑰私鑰

進(jìn)入jenkins容器猫牡,通過ssh-keygen生成公鑰私鑰

docker exec -it jenkins /bin/bash
ssh-keygen -t rsa

進(jìn)入~/.ssh查看id_rsa和id_rsa.pub胡诗,為jenkins配置

系統(tǒng)管理 => 安全 => Manage Credentials => 全局 => 添加憑據(jù) => 選擇SSH Username with private key

cicd01
cicd02

[圖片上傳失敗...(image-c893ad-1596729955518)]

  1. 配置node環(huán)境

系統(tǒng)管理 => 全局工具配置 => NodeJS

[圖片上傳失敗...(image-d4bc70-1596729955518)]

  1. 新建任務(wù)

首頁(yè) => 左側(cè)導(dǎo)航 => 新建任務(wù) => 源碼管理 + 構(gòu)建環(huán)境 + 構(gòu)建

[圖片上傳失敗...(image-b43989-1596729955518)]

cicd06

構(gòu)建這里選擇執(zhí)行shell,可將命令寫入其中淌友,這里鏡像名稱通常為jenkins服務(wù)器地址煌恢,后邊加時(shí)間戳可以避免重名

set -e
timestamp=`date '+%Y%m%d%H%M%S'`

node -v
npm -v

rm -rf node_modules package-lock.json

npm install

npm run build

(docker ps | grep ansible) && (docker rm -f ansible)

# 編譯docker鏡像
docker build -t xxx.xx.xx.xxx:8082/fe/nginx-fe-$timestamp .

# 推送docker鏡像到制品庫(kù)
docker push xxx.xx.xx.xxx:8082/fe/nginx-fe-$timestamp

docker run -id --name ansible ansible:t1

docker exec -i ansible ansible-playbook --syntax-check /root/playbook.yml

docker exec -i ansible ansible-playbook -e "timestamp=$timestamp" /root/playbook.yml

docker rm -f ansible
  1. 登錄制品庫(kù)

修改daemon.json

vi /etc/docker/daemon.json

{
    "insecure-registries": [
        "xxx.xx.xx.xxx:8082",
        "xxx.xx.xx.xxx:8081"
    ]
}

重啟docker

systemctl daemon-reload
systemctl restart docker

docker login登錄

docker exec -it jenkins /bin/bash

docker login 服務(wù)器ip:端口
exit

安裝gitlab

  1. 拉取gitlab鏡像
docker pull gitlab/gitlab-ce
  1. 創(chuàng)建gitlab容器

創(chuàng)建gitlab工作目錄

mkdir /home/gitlab

啟動(dòng)gitlab容器

docker run -itd -p 443:443 \
-p 8899:8899 \
-p 333:333 \
--name gitlab \
--restart always \
-v /home/gitlab/config:/etc/gitlab \
-v /home/gitlab/logs:/var/log/gitlab \
-v /home/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce
  1. 修改防火墻
firewall-cmd --zone=public --add-port=333/tcp --permanent
firewall-cmd --zone=public --add-port=8899/tcp --permanent

systemctl reload firewalld
  1. 修改gitlab配置文件

修改配置文件

vi /home/gitlab/config/gitlab.rb

exteranl_url 'http://外部訪問域名/地址:端口'
gitlab_rails['gitlab_ssh_host'] = 'SSH外部訪問域名/地址'
gitlab_rails['gitlab_shell_ssh_port'] = SSH端口

修改ssh端口

docker exec -it gitlab /bin/bash

vi /assets/sshd_config
vi /etc/ssh/sshd_config

重啟gitlab

docker restart gitlab
  1. 啟動(dòng)gitlab

宿主機(jī):端口 => 修改密碼

修改gitlab密碼

docker exec -it gitlab /bin/bash

gitlab-rails console production

user = Uer.where(id:1).first
user.password = "xxxxx"
user.password_confirmation = "xxxxx"

user.save!

quit
  1. 配置jenkins的公鑰

登錄gitlab => 點(diǎn)擊頭像 => 設(shè)置 => SSH密鑰

將jenkins中查到的~/.ssh/id_rsa.pub添加到gitlab的ssh密鑰中

cicd07
  1. 在前端項(xiàng)目根目錄下添加Dockerfile
FROM nginx:1.15-alpine
COPY dist /usr/share/nginx/html
WORKDIR /usr/share/nginx/html
  1. 新建倉(cāng)庫(kù) + 配置webhook

新建倉(cāng)庫(kù)后,配置webhook震庭,可通過git相關(guān)命令進(jìn)行自動(dòng)化部署瑰抵,可參考這篇文章[后端]gitlab之webhook自動(dòng)部署,github的webhook配置可參考這篇Jenkins與Github集成 webhook配置

安裝nexus

  1. 拉取nexus鏡像
docker pull sonatype/nexus3
  1. 創(chuàng)建nexus容器

創(chuàng)建nexus工作目錄

mkdir /home/nexus && chown -R 200 /home/nexus

啟動(dòng)容器

docker run -d -p 8081:8081 -P 8082:8082 \
--name nexus \
-v /home/nexus:/nexus-data \
--restart always \
sonatype/nexus3
  1. 修改防火墻
firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --zone=public --add-port=8082/tcp --permanent
  1. 啟動(dòng)nexus

查看日志

docker logs -f nexus
  1. 修改配置

進(jìn)入nexus => 修改密碼

cicd08

[圖片上傳失敗...(image-6ce872-1596729955518)]

  1. 創(chuàng)建私服

齒輪圖標(biāo) => Repositories => Create repository => 填寫表單

cicd10
cicd11

安裝ansible

  1. 創(chuàng)建ansible工作目錄
mkdir /home/ansible-file && cd /home/ansible-file

mkdir ssh
touch Dockerfile
touch hosts
touch playbook.yml
  1. 將配置的公鑰私鑰放入ssh文件夾下
cp -r ~/.ssh/* /home/ansible-file/ssh/
  1. 編輯Dockerfile
FROM centos:7
RUN yum -y install wget curl vim openssh-clients
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum clean all
RUN yum makecache

COPY ssh /root/.ssh/

RUN chmod 755 ~/.ssh/
RUN chmod 600 ~/.ssh/id_rsa ~/.ssh/id_rsa.pub
RUN yum -y install ansible

COPY hosts /etc/ansible/

RUN sed -i 's/^#host_key_checking = False/host_key_checking = False/' /etc/ansible/ansible.cfg
RUN ansible --version

COPY playbook.yml /root/
  1. 編輯hosts 多臺(tái)服務(wù)器ip
[fe-servers]
xxx.xx.xx.xxx
xxx.xx.xx.xxx
xxx.xx.xx.xxx
  1. 編輯playbook
---
- hosts: all
  remote_user: root
  vars: 
    timestamp: 20200806165833
  tasks:
    - name: docker pull new images
      shell: 'chdir=~ docker pull xxx.xx.xx.xxx:8082/fe/nginx-fe-{{timestamp}}
    - name: docker rmf
      shell: 'chdir=~ docker ps | grep xxx && docker rm -f xxx'
      ignore_errors: true
    - name: docker run
      shell: 'chdir=~ docker run -p 80:80 -itd --name xxx xxx.xx.xx.xxx:8082/fe/nginx-fe-{{timestamp}}'

nginx

  1. 拉取nginx鏡像
docker pull nginx
  1. 創(chuàng)建nginx容器

創(chuàng)建nginx工作目錄

mkdir /home/nginx

啟動(dòng)容器

docker run -itd -p 80:80 --name xxx \
-v /home/nginx/html:/usr/share/nginx/html \
-v /home/nginx/logs:/var/log/nginx \
--restart always \
nginx
  1. 公鑰私鑰

使用ssh-keygen創(chuàng)建公鑰私鑰

ssh-keygen -t rsa

在.ssh文件夾下創(chuàng)建authorized_keys器联,將jenkins的公鑰放入其中

cd .ssh/
touch authorized_keys

vi authorized_keys
  1. 登錄制品庫(kù)

修改daemon.json

vi /etc/docker/daemon.json

{
    "insecure-registries": [
        "xxx.xx.xx.xxx:8082",
        "xxx.xx.xx.xxx:8081"
    ]
}

重啟docker

systemctl daemon-reload
systemctl restart docker

docker login登錄

docker exec -it nginx /bin/bash

docker login 服務(wù)器ip:端口
exit

結(jié)果

example

總結(jié)

前端自動(dòng)化部署可在內(nèi)部開發(fā)及后續(xù)上線工程中進(jìn)行運(yùn)維控制二汛,對(duì)前端來說也是越來越重要的能力,整體流程:

前端git提交 => gitlab/github更新 => 觸發(fā)webhook命令 => jenkins構(gòu)建 => nexus制品庫(kù)生成 => ansible分發(fā) => 多臺(tái)nginx交付

對(duì)于gitlab來說還有不同stage進(jìn)行的不同階段的cicd全流程服務(wù)拨拓,具體可根據(jù)團(tuán)隊(duì)的需求進(jìn)行個(gè)性化的定制肴颊,如果后期項(xiàng)目龐大,比如采用了微前端架構(gòu)對(duì)不同框架如angular渣磷、react婿着、vue進(jìn)行不同層次部署交付,可配合k8s(ps: 感興趣的同學(xué)醋界,可參看這篇文章)等進(jìn)行更為嚴(yán)格的開發(fā)上線流程控制竟宋。

總之,在大前端的趨勢(shì)下形纺,前端延伸的方向也更為多樣丘侠,對(duì)于我們的要求也會(huì)越來越多,工程化逐样、智能化蜗字、可視化等等打肝,要在某一領(lǐng)域有所建樹,我們都還要不斷努力才行挪捕,加油闯睹!與君共勉!

參考

感謝

在此担神,特別感謝碼云前端王圣松大佬的分享,此為其個(gè)人歷程分享一位00后前端2年經(jīng)驗(yàn)的成長(zhǎng)歷程始花,感興趣的同學(xué)可以關(guān)注一波

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妄讯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酷宵,更是在濱河造成了極大的恐慌亥贸,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇垦,死亡現(xiàn)場(chǎng)離奇詭異炕置,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)男韧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門朴摊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人此虑,你說我怎么就攤上這事甚纲。” “怎么了朦前?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵介杆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我韭寸,道長(zhǎng)春哨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任恩伺,我火速辦了婚禮赴背,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘莫其。我一直安慰自己癞尚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布乱陡。 她就那樣靜靜地躺著浇揩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪憨颠。 梳的紋絲不亂的頭發(fā)上胳徽,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天积锅,我揣著相機(jī)與錄音,去河邊找鬼养盗。 笑死缚陷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的往核。 我是一名探鬼主播箫爷,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼聂儒!你這毒婦竟也來了虎锚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤衩婚,失蹤者是張志新(化名)和其女友劉穎窜护,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體非春,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柱徙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奇昙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片护侮。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖储耐,靈堂內(nèi)的尸體忽然破棺而出概行,到底是詐尸還是另有隱情,我是刑警寧澤弧岳,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布凳忙,位于F島的核電站,受9級(jí)特大地震影響禽炬,放射性物質(zhì)發(fā)生泄漏涧卵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一腹尖、第九天 我趴在偏房一處隱蔽的房頂上張望柳恐。 院中可真熱鬧,春花似錦热幔、人聲如沸乐设。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)近尚。三九已至,卻和暖如春场勤,著一層夾襖步出監(jiān)牢的瞬間戈锻,已是汗流浹背歼跟。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留格遭,地道東北人哈街。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像拒迅,于是被迫代替她去往敵國(guó)和親骚秦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359