<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用Docker Compose、Nginx、SSH和Github Actions實現(xiàn)前端自動化部署測試機

          共 10986字,需瀏覽 22分鐘

           ·

          2021-12-31 01:00

          開篇,我們先來看一下遠古時代的構(gòu)建部署流程。想必大家對這個都不陌生:

          • 開發(fā)將源碼經(jīng)過編譯、壓縮打包生成打包文件
          • 將打包生成的文件上傳服務器

          顯然這個流程不僅繁瑣,而且效率也不高,開發(fā)每次發(fā)布都要耗費很長的時間在部署構(gòu)建上面。

          后面為了解決這個問題,就出現(xiàn)了CI/CD

          接下來我們來聊一下什么是CI/CD?

          CI/CDContinuous Intergration/Continuous Deploy 的簡稱,翻譯過來就是持續(xù)集成/持續(xù)部署CD 也會被解釋為持續(xù)交付(Continuous Delivery

          再具體一點就是:

          • 持續(xù)集成:當代碼倉庫代碼發(fā)生變更,就會自動對代碼進行測試和構(gòu)建,反饋運行結(jié)果。
          • 持續(xù)交付:持續(xù)交付是在持續(xù)集成的基礎(chǔ)上,可以將集成后的代碼依次部署到測試環(huán)境、預發(fā)布環(huán)境、生產(chǎn)環(huán)境中

          聊了這么多,相信很多同學一定會說:

          • 這一般不都是運維搞的嗎?
          • 和業(yè)務也不相關(guān)啊,了解它有什么用?
          • 全是服務器相關(guān)的東西,dockernginx、云服務器啥的,我該怎么學習呢?

          很早之前,我也是這么想的,感覺與自己的業(yè)務也沒啥關(guān)系,沒有太大的必要去了解。

          但是最近我在搞一個全棧項目(做這個項目是為了突破自己的瓶頸)時,就遇到了這些問題,發(fā)現(xiàn)陷入了知識盲區(qū)。

          沒辦法,只能一頓惡補。

          但是當我通過學習這些知識和在項目中實踐這些流程后,我在知識面上得到了很大的擴展。對操作系統(tǒng),對實際的構(gòu)建部署,甚至對工程化擁有了全新的認識。

          這里也放下前面提到的全棧項目的架構(gòu)圖吧:

          這個大的項目以low code為核心,囊括了編輯器前端編輯器后端C端H5組件庫組件平臺后臺管理系統(tǒng)前端后臺管理系統(tǒng)后臺統(tǒng)計服務自研CLI九大系統(tǒng)。

          其中的編輯器前端如何設(shè)計實現(xiàn) H5 營銷頁面搭建系統(tǒng)文章中已經(jīng)有很詳細的說明。

          目前整個項目做了 70%左右,過程中遇到了很多問題,也得到了很大的提升。后續(xù)會有一波文章是關(guān)于項目中的一個個小點展開的,也都是滿滿的干貨。

          回到本篇文章的主題:使用Docker Compose、Nginx、SSH和Github Actions實現(xiàn)前端自動化部署測試機。本文是以后臺管理系統(tǒng)前端為依托詳細說明了如何借助DockernginxGithub CI/CD能力自動化發(fā)布一個純前端項目。選這個項目來講解自動化發(fā)布測試機有兩個出發(fā)點:

          • 后臺管理系統(tǒng)業(yè)務較簡單,可將重心放在自動化部署流程上
          • 純前端項目更適用于大部分前端同學現(xiàn)狀,拿去即用

          整體思路

          前端代碼,打包出來的是靜態(tài)文件,可用nginx做服務。思路:

          • 構(gòu)建一個Docker容器(有nginx
          • dist/目錄拷貝到Docker容器中
          • 啟動nginx服務
          • 宿主機端口,對應到Docker容器端口中,即可訪問

          核心代碼變動:

          • nginx.conf(給Docker容器的nginx使用)
          • Dockerfile
          • docker-compose.yml

          ?? 本文將采用理論知識和實際相結(jié)合的方式,即先講述一下對應知識點,同時會放一下與此知識點相關(guān)的項目代碼或配置文件。

          下面會依次講解Dockerdocker-composesshgithub actions等知識點。

          Docker

          Docker很早之前,在公眾號的一篇文章誰說前端不需要學習 docker?就有過詳細說明。這里簡單再闡述下。

          docker 可以看成是一個高性能的虛擬機,主要用于 linux 環(huán)境的虛擬化。開發(fā)者可以打包他們的應用以及依賴包到一個可移植的容器中,然后發(fā)布到任何流行的 linux 機器上。容器完全使用沙箱機制,相互之間不會有任何接口。

          在容器中你可以做任何服務器可以做的事,例如在有 node 環(huán)境的容器中運行 npm run build 打包項目,在有 nginx 環(huán)境的容器中部署項目等等。

          centos 上安裝 docker

          由于這次的云服務器是centos的,所以這里就提一下如何在 centos 上安裝 docker


          $?sudo?yum?remove?docker?docker-client?docker-client-latest?docker-common?docker-latest?docker-latest-logrotate?docker-logrotate?docker-engine

          $?sudo?yum?install?-y?yum-utils?device-mapper-persistent-data?lvm2

          $?sudo?yum-config-manager?--add-repo?https://download.docker.com/linux/centos/docker-ce.repo

          $?sudo?yum?install?docker-ce?docker-ce-cli?containerd.io

          $?sudo?systemctl?start?docker

          $?sudo?docker?run?hello-world

          dockerfile

          docker 使用 Dockerfile 作為配置文件進行鏡像的構(gòu)建,簡單看一個 node 應用構(gòu)建的 dockerfile

          FROM?node:12.10.0

          WORKDIR?/usr/app

          COPY?package*.json?./

          RUN?npm?ci?-qy

          COPY?.?.

          EXPOSE?3000

          CMD?["npm",?"start"]

          說明一下每個關(guān)鍵字對應的含義。

          FROM

          基于這個 Image 開始

          WORKDIR

          設(shè)置工作目錄

          COPY

          復制文件

          RUN

          新層中執(zhí)行命令

          EXPOSE

          聲明容器監(jiān)聽端口

          CMD

          容器啟動時執(zhí)行指令默認值

          看下項目中的Dockerfile文件:

          #?Dockerfile
          FROM?nginx

          #?將?dist?文件中的內(nèi)容復制到?/usr/share/nginx/html/?這個目錄下面
          #?所以,之前必須執(zhí)行 npm run build 來打包出 dist 目錄,重要!!!
          COPY?dist/?/usr/share/nginx/html/

          #?拷貝?nginx?配置文件
          COPY?nginx.conf?/etc/nginx/nginx.conf

          #?設(shè)置時區(qū)
          RUN?ln?-sf?/usr/share/zoneinfo/Asia/Shanghai?/etc/localtime?&&?echo?'Asia/Shanghai'?>/etc/timezone

          #?創(chuàng)建?/admin-fe-access.log?,對應到?nginx.conf
          CMD?touch?/admin-fe-access.log?&&?nginx?&&?tail?-f?/admin-fe-access.log

          在這個文件里面,我們做了下面幾件事:

          1、我們用了 NginxDocker image 作為 base image

          2、把打包生成的文件夾dist/的全部內(nèi)容放進 Nginx Docker 的默認 HTML 文件夾,也就是/usr/share/nginx/html/里面。

          3、把自定義的 Nginx 配置文件nginx.conf放進 Nginx Docker 的配置文件夾/etc/nginx/nginx.conf中。

          4、設(shè)置時區(qū)。

          5、創(chuàng)建 /admin-fe-access.log,啟動nginx并使用tail -f模擬類似pm2的阻塞式進程。

          這里提到了nginx.conf文件:

          #nginx進程數(shù),通常設(shè)置成和cpu的數(shù)量相等
          worker_processes?auto;

          #全局錯誤日志定義類型
          #error_log??logs/error.log;
          #error_log??logs/error.log??notice;
          #error_log??logs/error.log??info;

          #進程pid文件
          #pid????????logs/nginx.pid;

          #參考事件模型
          events?{
          ????#單個進程最大連接數(shù)(最大連接數(shù)=連接數(shù)+進程數(shù))
          ????worker_connections??1024;
          }

          #設(shè)定http服務器
          http?{
          ????#文件擴展名與文件類型映射表
          ????include???????mime.types;
          ????#默認文件類型
          ????default_type??application/octet-stream;

          ????#日志格式設(shè)定
          ????#$remote_addr與?$http_x_forwarded_for用以記錄客戶端的ip地址;
          ????#$remote_user:用來記錄客戶端用戶名稱;
          ????#$time_local:?用來記錄訪問時間與時區(qū);
          ????#$request:?用來記錄請求的url與http協(xié)議;
          ????#$status:?用來記錄請求狀態(tài);成功是200,
          ????#$body_bytes_sent :記錄發(fā)送給客戶端文件主體內(nèi)容大小;
          ????#$http_referer:用來記錄從那個頁面鏈接訪問過來的;
          ????#$http_user_agent:記錄客戶瀏覽器的相關(guān)信息;
          ????log_format??main??'$remote_addr?-?$remote_user?[$time_local]?"$request"?'
          ?????????????????????'$status?$body_bytes_sent?"$http_referer"?'
          ?????????????????????'"$http_user_agent"?"$http_x_forwarded_for"';

          ????#?access_log??logs/access.log??main;

          ????sendfile????????on;
          ????#tcp_nopush?????on;

          ????#keepalive_timeout??0;
          ????#長連接超時時間,單位是秒
          ????keepalive_timeout??65;

          ????#gzip??on;

          ????#設(shè)定通過nginx上傳文件的大小
          ????client_max_body_size???20m;

          ????#虛擬主機的配置
          ????server?{
          ????????#監(jiān)聽端口
          ????????listen???????80;
          ????????#域名可以有多個,用空格隔開
          ????????server_name??admin-fe;

          ????????#charset?koi8-r;

          ????????#定義本虛擬主機的訪問日志
          ????????access_log??/admin-fe-access.log??main;?#?注意,在?Dockerfile?中創(chuàng)建?/admin-fe-access.log

          ????????#入口文件的設(shè)置
          ????????location?/?{
          ????????????root???/usr/share/nginx/html;???#入口文件的所在目錄
          ????????????index??index.html?index.htm;????#默認入口文件名稱
          ????????????try_files?$uri?$uri/?/index.html;
          ????????}
          ????????#error_page??404??????????????/404.html;

          ????????#?redirect?server?error?pages?to?the?static?page?/50x.html
          ????????error_page???500?502?503?504??/50x.html;
          ????????location?=?/50x.html?{
          ????????????root???html;
          ????????}
          ????}
          }

          核心點就是監(jiān)聽80端口,定義日志文件為admin-fe-access.log,入口文件根目錄為/usr/share/nginx/html,這些都是與Dockerfile中一一對應的。

          說完了Dockerfile及其相關(guān)的配置文件,下面接著來看下docker中幾個核心的概念。

          docker 核心概念

          docker中有三個非常重要的概念:

          • 鏡像(image)
          • 容器(container)
          • 倉庫(repository)

          一張圖來表明其中的關(guān)系:

          如果把容器比作輕量的服務器,那么鏡像就是創(chuàng)建它的模版,一個 docker鏡像可以創(chuàng)建多個容器,它們的關(guān)系好比 JavaScript實例的關(guān)系。

          鏡像(image)常用命令:

          • 下載鏡像:docker pull :
          • 查看所有鏡像:docker images
          • 刪除鏡像:docker rmi
          • 上傳鏡像:docker push /:

          如果docker images出現(xiàn)repository的情況,可以運行docker image prune刪除

          容器(container)常用命令

          • 啟動容器:docker run -p xxx:xxx -v=hostPath:containerPath -d --name
            • -p 端口映射
            • -v 數(shù)據(jù)卷,文件映射
            • -d 后臺運行
            • --name 定義容器名稱
          • 查看所有容器:docker ps(加-a顯示隱藏的容器)
          • 停止容器:docker stop
          • 刪除容器:docker rm (加-f強制刪除)
          • 查看容器信息(如 IP 地址等):docker inspect
          • 查看容器日志:docker logs
          • 進入容器控制臺:docker exec -it /bin/sh

          鏡像構(gòu)建完成后,可以很容易的在當前宿主上運行,但是, 如果需要在其它服務器上使用這個鏡像,我們就需要一個集中的存儲、分發(fā)鏡像的服務,Docker Registry 就是這樣的服務。

          一個 Docker Registry 中可以包含多個倉庫(Repository);每個倉庫可以包含多個標簽(Tag);每個標簽對應一個鏡像。所以說:鏡像倉庫是 Docker 用來集中存放鏡像文件的地方,類似于我們之前常用的代碼倉庫。

          docker-compose

          docker-compose項目是Docker官方的開源項目,負責實現(xiàn)對Docker容器集群的快速編排。允許用戶通過一個單獨的docker-compose.yml模板文件(YAML 格式)來定義一組相關(guān)聯(lián)的應用容器為一個項目(project)。

          使用 compose 的最大優(yōu)點是你只需在一個文件中定義自己的應用程序棧(即應用程序需要用到的所有服務),然后把這個 YAML 文件放在項目的根目錄下,與源碼一起受版本控制。其他人只需 clone 你的項目源碼之后就可以快速啟動服務。

          通常適用于項目所需運行環(huán)境(對應多個docker容器)較多的場景,例如同時依賴于nodejsmysqlmongodbredis等。

          這里放下docker-compose.yml文件:

          version:?'3'
          services:
          ??admin-fe:
          ????build:
          ??????context:?.
          ??????dockerfile:?Dockerfile
          ????image:?admin-fe?#?引用官網(wǎng)?nginx?鏡像
          ????container_name:?admin-fe
          ????ports:
          ??????-?8085:80?#?宿主機可以用?127.0.0.1:8085?即可連接容器中的數(shù)據(jù)庫

          基于上文的Dockerfile創(chuàng)建鏡像,端口映射是8085:80,這里的8085是宿主機端口,80對應的是nginx暴露的 80 端口

          常用命令

          • 構(gòu)建容器:docker-compose build
          • 啟動所有服務器:docker-compose up -d(后臺啟動)
          • 停止所有服務:docker-compose down
          • 查看服務:docker-compose ps

          ssh 及云服務器

          首先說下云服務器,既然要一鍵部署測試機,那么肯定要有臺測試機,也就是云服務器,這里我用的是阿里云CentOS 8.4 64位的操作系統(tǒng)。

          有了服務器,那怎么登陸呢?

          本地登陸云服務器的方式一般有兩種,密碼登陸和 ssh 登陸。但是如果采用密碼登陸的話,每次都要輸入密碼,比較麻煩。這里采用ssh登陸的方式。關(guān)于如何免密登錄遠程服務器,可以參考SSH 免密登陸配置[1]

          此后每次登陸都可以通過ssh @的方式直接免密登陸了。

          云服務器安裝指定包

          接著要給云服務器安裝基礎(chǔ)包,在CentOS安裝指定包一般用的是yum,這個不同于npm

          docker

          #?Step?1:?卸載舊版本
          sudo?yum?remove?docker?docker-client?docker-client-latest?docker-common?docker-latest?docker-latest-logrotate?docker-logrotate?docker-engine
          #?Step?2:?安裝必要的一些系統(tǒng)工具
          sudo?yum?install?-y?yum-utils
          #?Step?3:?添加軟件源信息,使用阿里云鏡像
          sudo?yum-config-manager?--add-repo?http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
          #?Step?4:?安裝?docker-ce
          sudo?yum?install?docker-ce?docker-ce-cli?containerd.io
          #?Step?5:?開啟?docker服務
          sudo?systemctl?start?docker
          #?Step?6:?運行?hello-world?項目
          sudo?docker?run?hello-world

          如果你像我一樣,有Hello from Docker!的話那么Docker就安裝成功了!

          docker-compose

          通過訪問 https://github.com/docker/compose/releases/latest 得到最新的 docker-compose 版本(例如:1.27.4),然后執(zhí)行一下命令安裝 docker-compose

          #?下載最新版本的?docker-compose?到?/usr/bin?目錄下
          curl?-L?https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname?-s`-`uname?-m`?-o?/usr/bin/docker-compose

          #?給?docker-compose?授權(quán)
          chmod?+x?/usr/bin/docker-compose

          安裝完,命令行輸入docker-compose version來驗證是否安裝成功:

          node

          首先確保可以訪問到EPEL庫,通過運行以下命令來安裝:

          sudo?yum?install?epel-release

          現(xiàn)在可以使用yum命令安裝Node.js了:

          sudo?yum?install?nodejs

          驗證一下:

          nginx

          yum 安裝 nginx 非常簡單,輸入一條命令即可:

          $?sudo?yum?-y?install?nginx???#?安裝?nginx

          git

          同樣也是使用yum來安裝:

          yum?install?git

          最后來看一下github actions,也是串聯(lián)起了上面提到的各個點。

          github actions

          大家知道,持續(xù)集成由很多操作組成,比如拉取代碼、執(zhí)行測試用例、登錄遠程服務器,發(fā)布到第三方服務等等。GitHub 把這些操作就稱為 actions

          我們先來了解一下一些術(shù)語

          • workflow(工作流程):持續(xù)集成一次運行的過程,就是一個 workflow。

          • job(任務):一個 workflow 由一個或多個 jobs 構(gòu)成,含義是一次持續(xù)集成的運行,可以完成多個任務。

          • step(步驟):每個 job 由多個 step 構(gòu)成,一步步完成。

          • action(動作):每個 step 可以依次執(zhí)行一個或多個命令(action)。

          workflow 文件

          GitHub Actions 的配置文件叫做 workflow 文件,存放在代碼倉庫的.github/workflows目錄。

          workflow 文件采用 YAML 格式,文件名可以任意取,但是后綴名統(tǒng)一為.yml,比如deploy.yml。一個庫可以有多個 workflow 文件。GitHub 只要發(fā)現(xiàn).github/workflows目錄里面有.yml文件,就會自動運行該文件。

          workflow 文件的配置字段非常多,這里列舉一些基本字段。

          name

          name字段是 workflow 的名稱。

          如果省略該字段,默認為當前 workflow 的文件名。

          name:?deploy?for?feature_dev

          on

          on字段指定觸發(fā) workflow 的條件,通常是pushpull_request

          指定觸發(fā)事件時,可以限定分支或標簽。

          on:
          ??push:
          ????branches:
          ??????-?master

          上面代碼指定,只有master分支發(fā)生push事件時,才會觸發(fā) workflow

          jobs

          jobs字段,表示要執(zhí)行的一項或多項任務。其中的runs-on字段指定運行所需要的虛擬機環(huán)境。

          runs-on:?ubuntu-latest

          steps

          steps字段指定每個 Job 的運行步驟,可以包含一個或多個步驟。每個步驟都可以指定以下三個字段。

          • jobs..steps.name:步驟名稱。
          • jobs..steps.run:該步驟運行的命令或者 action。
          • jobs..steps.env:該步驟所需的環(huán)境變量。

          下面放一下項目中的.github/workflows/deploy-dev.yml文件:

          name:?deploy?for?feature_dev

          on:
          ??push:
          ????branches:
          ??????-?'feature_dev'
          ????paths:
          ??????-?'.github/workflows/*'
          ??????-?'__test__/**'
          ??????-?'src/**'
          ??????-?'config/*'
          ??????-?'Dockerfile'
          ??????-?'docker-compose.yml'
          ??????-?'nginx.conf'

          jobs:
          ??deploy-dev:
          ????runs-on:?ubuntu-latest

          ????steps:
          ??????-?uses:?actions/checkout@v2
          ??????-?name:?Use?Node.js
          ????????uses:?actions/setup-node@v1
          ????????with:
          ??????????node-version:?14
          ??????-?name:?lint?and?test?#?測試
          ?????????run:?|
          ???????????npm?i
          ???????????npm?run?lint
          ???????????npm?run?test:local
          ??????-?name:?set?ssh?key?#?臨時設(shè)置?ssh?key
          ????????run:?|
          ??????????mkdir?-p?~/.ssh/
          ??????????echo?"${{secrets.COSEN_ID_RSA}}"?>?~/.ssh/id_rsa
          ??????????chmod?600?~/.ssh/id_rsa
          ??????????ssh-keyscan?"106.xx.xx.xx"?>>?~/.ssh/known_hosts
          ??????-?name:?deploy
          ????????run:?|
          [email protected]?"
          ????????????cd?/home/work/choba-lego/admin-fe;
          ????????????git?remote?add?origin?https://Cosen95:${{secrets.COSEN_TOKEN}}@github.com/Choba-lego/admin-fe.git;
          ????????????git?checkout?feature_dev;
          ????????????git?config?pull.rebase?false;
          ????????????git?pull?origin?feature_dev;
          ????????????git?remote?remove?origin;

          ????????????#?構(gòu)建?prd-dev
          ????????????#?npm?i;
          ????????????#?npm?run?build-dev;

          ????????????#?啟動?docker
          ????????????docker-compose?build?admin-fe;?#?和?docker-compose.yml?service?名字一致
          ????????????docker-compose?up?-d;
          ??????????"

          ??????-?name:?delete?ssh?key
          ????????run:?rm?-rf?~/.ssh/id_rsa

          這里概述一下:

          1?? 整個流程在代碼pushfeature_dev分支時觸發(fā)。

          2?? 只有一個job,運行在虛擬機環(huán)境ubuntu-latest

          3?? 第一步使用的是最基礎(chǔ)的action,即actions/checkout@v2,它的作用就是讓我們的workflow可以訪問到我們的repo

          4?? 第二步是在執(zhí)行工作流的機器中安裝node,這里使用的actionactions/setup-node@v1

          5?? 第三步是執(zhí)行linttest

          6?? 第四步是臨時設(shè)置 ssh key,這也是為了下一步登錄服務器做準備。

          7?? 第五步是部署,這里面先是ssh登錄服務器,拉取了最新分支代碼,然后安裝依賴、打包,最后啟動docker,生成鏡像。到這里測試機上就有了Docker服務。

          8?? 最后一步是刪除ssh key

          最后來github看一下完整的流程:

          其中deploy階段算是核心了:

          總結(jié)

          洋洋灑灑寫了這么多,也不知道你看明白了不 ??

          如果有任何問題,歡迎評論區(qū)留言,看到后會第一時間解答 ??

          后續(xù)會有很多關(guān)于這個項目的文章,也請大家多多關(guān)注~


          參考資料

          [1]

          SSH 免密登陸配置: https://segmentfault.com/a/1190000021000360


          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一级欧美一级在线播放 | 人操人 | 手机免费看国产黄色电影 | 麻豆久久爱 | 伊人大香蕉在线观看视频 |