將你的前端應用打包成docker鏡像并部署到服務器?僅需一個腳本搞定

將你的前端應用打包成docker鏡像并部署到服務器?僅需一個腳本搞定
1.前言
前段時間,自己搞了個阿里云的服務器。想自己在上面折騰,但是不想因為自己瞎折騰而污染了現有的環境。畢竟,現在的阿里云已經沒有免費的快照服務了。要想還原的話,最簡單的辦法就是重新裝系統。而一旦重裝,之前的搭建的所有環境就都白搭了。

再加上之前本身就想引入docker,所以就打算利用docker容器來部署這次的前端應用。

2.構建前端應用
在打包之前,首先需要一個可正常運行的前端應用。這個可以使用umi或者create-react-app來構建。

3.nginx的默認配置文件
然后需要在項目中加上默認nginx配置文件。

server {

listen 80;
server_name localhost;location / {root   /usr/share/nginx/html;index  index.html index.htm;try_files $uri $uri/ /index.html;
}

}
4.編寫本地構建腳本
4.1. 移除上次的目錄和Dockerfile

!/bin/bash

if [ -d "./dist" ]; then

rm -rf ./dist

fi

if [ -f "./Dockerfile" ]; then

rm -f ./Dockerfile

fi
因為每次更改后dist中的內容肯定與之前不同,其實這一步顯得不是那么必要。運行npm的打包命令也會自動清楚該目錄。

而清除Dockerfile則是為了防止更新了Dockerfile,而這次卻不能得到最新的配置。

4.2. 打包前端應用
執行前端的打包命令,生成靜態文件目錄。

yarn build
4.3. 生成Dockerfile
echo "FROM nginx:latest" >> ./Dockerfile
echo "COPY ./dist /usr/share/nginx/html/" >> ./Dockerfile
echo "COPY ./default.conf /etc/nginx/conf.d/" >> ./Dockerfile
echo "EXPOSE 80" >> ./Dockerfile
FROM制定了該定制容器的基礎鏡像為nginx:latest;COPY命里將打包好的靜態文件目錄復制到容器內的/usr/share/nginx/html/目錄下,然后將nginx的配置寫入容器中對應的位置; EXPOSE則是設置對外暴露容器的80端口。

4.4. 生成并推送定制image
docker build -t detectivehlh/mine .
docker login -u detectivehlh -p
docker push detectivehlh/mine
這里是在開發本地,使用docker命令來打包,所以該腳本對docker有強依賴。build命令表示打包docker應用的,-t選項則制定了docker鏡像的名字和tag,tag會默認為latest。

然后登錄dockerHub,將定制好的鏡像推送到dockerHub中。detectivehlh就是dockerHub的用戶名,mine是image的名字。

4.5. 刪除tag為none的無用image
第一次構建不會生成tag為none的image,但是后面每次再次執行該命令就會出現這樣的情況。所以每次構建了一個新的image后,需要清除調不需要的image。

docker images | grep none | awk '{print $3}' | xargs docker rmi
使用grep命令匹配到tag為none的image,awk是一個強大的文本分析工具,{print $3}表示打印出匹配到的每一行的第三個字段,也就是docker的image id。如果是$0的話表示當前整行的數據。

xargs是一個給其他命令(也就是后面的docker rmi)傳遞參數的一個過濾器,將標準輸入轉換成命令行參數。

總結來說,上述命令就是找到tag為none的image的ID,然后使用docker rmi命令移除該image。

4.6. 執行部署
cmd="cd ~ && sh deploy.sh mine"
ssh -t USER_NAME@IP_ADDRESS "bash -c "${cmd}""
通過ssh命令,登錄遠程服務器,并且執行參數中的腳本。

deploy.sh是放在服務端的構建腳本。放在默認的登錄用戶下。我們發現,后面還跟了個mine,這是在服務器上運行的docker鏡像的名字。這里暫時沒有對container的名字加上hash,因為自己的小項目,暫時沒有必要。

在項目中的完整構建腳本如下。

!/bin/bash

if [ -d "./dist" ]; then

rm -rf ./dist

fi
if [ -f "./Dockerfile" ]; then

rm -f ./Dockerfile

fi

yarn build

echo "FROM nginx:latest" >> ./Dockerfile
echo "COPY ./dist /usr/share/nginx/html/" >> ./Dockerfile
echo "COPY ./default.conf /etc/nginx/conf.d/" >> ./Dockerfile
echo "EXPOSE 80" >> ./Dockerfile

docker build -t detectivehlh/mine .
docker login -u detectivehlh -p
docker push detectivehlh/mine

docker images | grep none | awk '{print $3}' | xargs docker rmi

cmd="cd ~ && sh deploy.sh mine"
ssh -t USER_NAME@IP_ADDRESS "bash -c "${cmd}""

  1. 編寫服務器部署腳本
    從上面步驟來看,我們還需要一個服務器端的部署腳本。大家可能會說,標題不是說一個腳本搞定嗎?em。。。服務器一個,本地一個...簡稱只需一個腳本。

5.1 接收參數
在本地的構建腳本中,我們傳入了docker運行的container的名字。在服務器構建腳本中需要來接收它。然后更新剛剛推送的docker image。

!/bin/bash

name=$1
docker pull detectivehlh/$name
5.2. 啟動container
在啟動container時我們會面對兩種情況,名字為傳入參數的container已經在運行了。而在此時如果再次運行docker run命令就會報錯而導致我們無法使用最新的container,也無法達到更新應用的目的。

if docker ps | grep $name | awk {'print $(NF)'} | grep -Fx $name; then

echo "Container mine is already start"
docker stop $name
docker rm $name
docker run -d --name $name -p 3000:80 detectivehlh/$name

else

echo "Container mine is not start!, starting"
docker run -d --name $name -p 3000:80 detectivehlh/$name
echo "Finish starting"

fi
docker images | grep none | awk '{print $3}' | xargs docker rmi
所以在這里做一個判斷,第一個if判斷如果存在名字為傳入參數的container正在運行,就停止當前容器再重新啟動。如果不存在則直接啟動容器。

run命令就不過多解釋了。-d表示后臺運行容器并返回容器ID,--name表示設置容器的名字,-p表示設置端口,將阿里云服務器的3000端口映射到容器的80端口,最后一句表示要啟動哪個image(好像還是解釋了一遍)。

最后一句就是移除多次更新后出現的tag為none的無用鏡像。完整的腳本如下。

!/bin/bash

name=$1
docker pull detectivehlh/$name
if docker ps | grep $name | awk {'print $(NF)'} | grep -Fx $name; then

echo "Container mine is already start"
docker stop $name
docker rm $name
docker run -d --name $name -p 3000:80 detectivehlh/$name

else

echo "Container mine is not start!, starting"
docker run -d --name $name -p 3000:80 detectivehlh/$name
echo "Finish starting"

fi
docker images | grep none | awk '{print $3}' | xargs docker rmi

  1. 如果你只是想打個包
    看到標題進來的兄dei,如果只是想打包一個docker鏡像,那么你只需要Dockerfile文件和docker build命令就OK了。
  2. 總結
    最初寫這個腳本,主要目的是為了方便。所以腳本中為了達到這個目的做了一些調整。最終我達成了滿足我需求的一個方便的部署腳本。

它的方便體現在,當我完成了項目代碼的更新,只需要跑一下這個腳本,然后等待一會兒,項目就會自動打包成docker image,并且自動的在我的服務器上運行該container。

但是這種方式會給實際的生產環境帶來一些不可控的問題。比如,腳本必須不能上傳,因為涉及一些服務器的敏感信息。但是如果你不小心上傳了,那你的服務器就相當于裸奔了;再比如,你對你的代碼必須要十分自信,沒有經過測試的代碼就直接部署,會帶來一些風險。

如果是自己用的,那完全不用擔心,想怎么搞怎么搞。但是如果是開放給所有人用的并且有一定的訪問量,比如博客,那么對于其他用戶來說,這種方式就不怎么友好。

所以我的觀點是,分情況來。目前來說我的項目只有少數幾個人在用,也還在處于迭代階段。并且代碼倉庫是私有的,所以我完全不用擔心隱私的問題。服務未經測試就直接上線對于我來說,其實問題也不大。首先我會在本地測試,確認無誤后才會執行部署操作。所以在不同的階段,找到最適合自己的方案就OK。
原文地址https://www.cnblogs.com/detectiveHLH/p/10756702.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448929.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448929.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448929.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CVPR2014: DeepID解讀

上周五就要發的,拖........拖.......拖到現在,文中有不準確的地方,歡迎批評指正。DeepID是一種特征提取的算法,由港中文湯曉鷗團隊于2014年提出,發表于CVPR2014。其應用領域是人臉識別的子領域——人臉驗證&#xff0c…

成大事必備9種能力 9種手段 9種心態(圖)

成大事必備9種能力 1、擺正心態,敢于面對現實 對于那些不停地抱怨現實惡劣的人來說,不能稱心如意的現實,就如同生活的牢籠,既束縛手腳,又束縛身心,因此常屈從于現實的壓力,成為懦弱者;而那些…

解決:A component required a bean of type ‘javax.jms.Queue‘ that could not be found.

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 1. 情景描述:只是想簡單寫個 ActiveMQ 的小樣,啟動服務卻報錯: Error starting ApplicationContext…

【計算機視覺】OpenCV篇(3) - 圖像幾何變換(仿射變換/透視變換)

圖像的幾何變換從原理上看主要包括兩種:基于23矩陣的仿射變換(平移、縮放、旋轉和翻轉等)、基于33矩陣的透視變換。 仿射變換基本的圖像變換就是二維坐標的變換:從一種二維坐標(x,y)到另一種二維坐標(u,v)的線性變換: …

Linux學習第五篇之文件處理命令touch、cat、tac、more、less、head、tail

一、touch命令: 命令名稱:touch 命令所在路徑:/bin/touch 執行權限:所有用戶 語法:touch [文件名] 功能描述:創建空文件 例子: touch leanring.file 說明:在當前目錄下創建空文件l…

OpenCL 與 CUDA

根據網站資料,簡單地匯編一下CUDA與OpenCL的區別。如有錯誤請指出。 題外話: 美國Sandia國家實驗室一項模擬測試證明:由于存儲機制和內存帶寬的限制,16核、32核甚至64核處理器對于超級計算機來說,不僅不能帶來性能提升…

DBMS (數據庫管理系統) 是什么

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 數據庫管理系統(英語:database management system,縮寫:DBMS) 是一種針對對…

Eclipse4JavaEE安裝SpringBoot

第一步:下載SpringBoot SpringBoot官網下載鏈接 第二步:在Eclipse里進行安裝 打開Eclipse,菜單欄Help -》Install New Software,進入下圖界面,點擊Add 設置Name和Location,Name看自己喜好,Locat…

django中使用原生sql

django中使用原生sqlfrom django.db import connection cursor connection.cursor() cursor.execute("select * from xx where id1") row cursor.fetchone() users User.objects.raw("select * from user where namexx") for user in users: print(use…

從零開始玩轉 logback、完整配置詳解

官網地址:https://logback.qos.ch/manual/index.html 前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 概述 LogBack是一個日志框架,它與Log4j可以說是同出一源&a…

Rust 編程 前言

雖然不是那么明顯,但 Rust 程序設計語言的本質在于 賦能(empowerment):無論你現在編寫的是何種代碼,Rust 能讓你在更為廣泛的編程領域走得更遠,寫出自信。 比如,“系統層面”(“syst…

ffmpeg解碼器優化

在以前的視頻項目中,用到了幾種商業版的H.264解碼器。雖然性能穩定,支持DXVA或CUDA,在高清視頻播放效果上不錯,但是存在一個共同的缺陷-存在幀間延遲。經過我的測算,大概有3幀的緩沖延遲。當幀率在20fps以上時&#xf…

PHP 結合 Boostrap 結合 js 實現學生列表刪除編輯以及搜索功能(完結)

這個自己的小項目要先告一段落了。可能還有許多bug。請見諒 刪除學生功能 PHP: // 這里是通過前端代碼HTML中的 url 傳過來的&#xff0c;用 $_GET 來獲取(相關HTML代碼可以看一下到主頁看一下前幾條博客)if (empty($_GET[num])) exit(<h1>找不到您要刪除的學生的學號<…

ActiveMQ_Windows版本的安裝部署

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1, 保證電腦上安裝了jdk6以上版本的java&#xff0c;并配置了好環境變量 &#xff1b; 2, 官方下載地址&#xff1a;http://activemq.a…

Java 自定義異常(轉載)

1.異常的分類 1. 非運行時異常(Checked Exception) Java中凡是繼承自Exception但不是繼承自RuntimeException的類都是非運行時異常。 2. 運行時異常&#xff08;Runtime Exception/Unchecked Exception&#xff09; RuntimeException類直接繼承自Exception類&#xff0c;稱為運…

如何將markdown轉換為wxml

話說我要為技術博客寫一個小程序版&#xff0c;我的博客解決方案是 hexo github-page&#xff0c;格式當然是技術控們喜歡的 markdown 了 。但小程序使用的卻是獨有的模版語言 WXML。我總不能把之前的文章手動轉換成小程序的 wxml 格式吧&#xff0c;而網上也沒完善的轉換庫&a…

巧妙喝水打敗多種疾病

喝水&#xff0c;我們每天都會做的一件事&#xff0c;殊不知&#xff0c;喝水得當能打敗多種疾病問題! 方法/步驟 一、很多人都聽說過早晨喝一杯水對身體有好處&#xff0c;有人喝鹽水?有人喝蜂蜜水?還有人為了美白喝檸檬水?到底喝什么水最好呢?人體經過了一宿的代謝&…

git 幾個commit點合并成一個commit點

在用git做版本控制器的時候&#xff0c;經常會遇到以下情況&#xff1a; 1、在做1個功能的時候&#xff0c;你自己覺得代碼沒問題了&#xff0c;就本地commit&#xff0c;然后提交代碼&#xff0c;在gitlab上發起和并請求&#xff0c;老大看完之后&#xff0c;覺得你還有修改的…

JNDI 是什么

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 JNDI : 簡單理解&#xff0c;就是把固定的連接方式剝離出來&#xff0c;單獨寫在一個配置文件里。(下載.properties里面通過InputStream…

并發編程模型

并發編程模型 一.分類 按照線程通信機制可以分為共享內存模型和消息傳遞模型&#xff1a; 1.共享內存模型&#xff1a;線程之間共享程序的公共狀態&#xff0c;編程之間通過讀寫內存中的公共狀態來隱式進行通信。相互通信的進程共享某些數據結構或共享存儲區&#xff0c;進程通…