利用docker與shell指令碼進行懶人伺服器搭建

MasonChow發表於2018-01-29

前言

最近在學習後端的知識,自己搞了個自己玩的全棧專案,在需要釋出上線的時候,一開始是在伺服器用的是git拉程式碼->編譯構造->重新啟動的手動擋模式,釋出次數頻繁了或者前後端需要同時釋出就覺得十分的繁瑣,所以就想著怎麼可以通過指令碼就把所有過程自動化執行,讓自己敲少幾次命令

思路簡介

阿里雲有個CodePipeline服務,類似jenkins那樣可以進行編譯構建,不過到最後一步想部署容器的話,貌似需要開通叢集之類的,但是錢要留著給女朋友花,所以就先放棄研究這一塊的實現了...,然後只能想點比較簡單暴力的方法去實現,結合自己的實際情況,一臺筆記本走天下的,所以通過shell指令碼來實現應該是比較合適的方案了

原材料:

ssh shell docker node

前端程式碼:

通過本地編譯出dist檔案用scp命令把檔案放上去伺服器對應的站點目錄

後端程式碼:

通過dockerFile編譯出image上傳到自己的倉庫再觸發伺服器的對應指令碼重新啟動對應的container

伺服器:

用的是Ubuntu 16.04,建立一個資料夾存著一系列對應專案的指令碼,讓本地通過ssh觸發執行指令碼

實現

使用docker是為了方便環境的構建,因為自己只有一個伺服器,使用docker就可以很從容的部署以及管理多個專案,docker的規劃如下圖

利用docker與shell指令碼進行懶人伺服器搭建

伺服器配置

配置ssh免密登陸
  1. 把本地的~/.ssh/id_rsa.pub複製到伺服器~/.ssh/authorized_keys裡面

  2. 重新登陸一次即可

安裝docker以及存放指令碼
  1. docker簡介以及安裝 如何使用下面會說
  2. 在伺服器喜歡的地方建一個存放執行指令碼的資料夾,例如我就放在根目錄下/server_sh,然後給個777許可權

本機配置

  1. 在本機建立一個資料夾server_sh,並給個777許可權,同時建立一個存放阿里雲伺服器上面的指令碼的資料夾aliyun,此資料夾對應伺服器上面的server_sh
  2. 在server_sh下面建立一個自動更新伺服器檔案update_aliyun.sh,通過scp命令把aliyun資料夾裡面的shell指令碼同步到伺服器,只要修改了指令碼,執行一次./update_aliyun.sh,即可完成同步
#!/bin/sh

#更新伺服器指令碼

scp -r ./aliyun/* root@(伺服器ip):/server_sh/
複製程式碼
  1. 在aliyun資料夾建立首次執行docker的指令碼、需要安裝的資料庫型別指令碼,這裡使用了nginx、mongodb、mysql
注意1:db型別的映象run的時候需要使用內部或者掛載主機目錄資料卷來存放db資料,不然容器被刪除,資料就會丟失
注意2:容器內容通訊需要建立一次內部網路,不然只能每個埠都暴露出去,我為了方便除錯,所有的埠好都暴露了出來,從正式環境來講,應該只暴露nginx的80埠即可,其他都使用容器內部通訊
  • docker_create.sh
#!/bin/sh

# 首次安裝docker跑的指令碼

# 建立docker內部網路
docker network create --subnet 192.168.0.0/16 local-network

#啟動web服務
./webserver.sh

#啟動mongodb資料庫
./mongodb.sh

#啟動mysql資料庫
./mysql.sh

複製程式碼
  • webserver.sh(根據需要,由官方nginx為基礎配置的映象,後面會說)
#!/bin/sh

# 啟動Nginx服務

#停止正在執行的映象
docker container stop webserver

#刪除舊映象
docker container rm webserver

#刪除image,確保啟動的時候能拿到最新的映象
docker image rm masonchow/webserver

#下載最新映象並啟動
docker run -d -p 80:80 --name webserver -v /dockerVolume/web:/web:ro masonchow/webserver

複製程式碼
  • mongodb.sh
#!/bin/sh

#停止正在執行的映象
docker container stop mongo

#刪除舊映象
docker container rm mongo

#刪除image,確保啟動的時候能拿到最新的映象,若不需要拿最新版本映象則不用執行
docker image rm mongo

# 安裝並啟動mongodb
docker run -d -p 27017:27017 -v /dockerVolume/db/mongo/data:/data/db --name mongo --network local-network --ip 192.168.0.101 mongo
複製程式碼
  • mysql.sh
#!/bin/sh

#停止正在執行的映象
docker container stop mysql

#刪除舊映象
docker container rm mysql

#刪除image,確保啟動的時候能拿到最新的映象,若不需要拿最新版本映象則不用執行
# docker image rm mysql

# 安裝並啟動mysql
docker run -d -p 3306:3306 -v /dockerVolume/db/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root --name mysql --network local-network --ip 192.168.0.100 mysql
複製程式碼
  1. 執行update_aliyun.sh同步指令碼到伺服器並且在伺服器執行一次docker_create.sh之後,在伺服器打docker container ls就可以看到正在執行的容器資訊

專案配置

Nginx

因為只有一個伺服器,如果多個前端專案的話,每次增加一個前端專案,就需要更改一次nginx的配置,所以就根據官方的nginx加以自己的配置,利用指令碼把定製好的dockerfile構造一個image更新到自己的docker倉庫上,給伺服器下載使用即可

  • DockerFile
FROM nginx:latest

#一些nginx配置
ADD conf/nginx.conf /etc/nginx/nginx.conf

#nginx站點配置
ADD conf/server_app.conf /etc/nginx/conf.d/default.conf

ADD conf/gzip.conf /etc/nginx/conf.d/gzip.conf

RUN cd / \ && mkdir /web 

WORKDIR /web

CMD ["nginx", "-g", "daemon off;"]
複製程式碼

這裡監聽的web目錄是docker監聽的本地目錄,是由於在上文啟動nginx的時候跑了-v /dockerVolume/web:/web:ro

前端專案

前端專案只需要在本地構建完之後把dist資料夾同步到伺服器對應的資料夾即可,例如我在專案資料夾下會建立一個publsh.sh,同時給個777的許可權即可

#!/bin/sh

#刪除本地的依賴包
rm -rf ./node_modules

#重新安裝
npm i

#開始構建
npm run build

#刪除遠端本身的檔案
ssh root@120.78.190.53 "rm -rf /dockerVolume/web/專案資料夾"

#把本地編譯的檔案放上去遠端
scp -r ./wallet root@伺服器IP:/dockerVolume/web/
複製程式碼

後端專案

後端專案的思路是每次更新發布就跑一次專案的指令碼,通過dockerflie把後端編譯成一個新的image更新到自己的docker倉庫讓伺服器的docker跑最新的映象

  • publish.sh
#開始構建
npm run build

#構建最新映象
docker build -t 使用者名稱/映象名 .

#釋出映象
docker push 使用者名稱/映象名

# 刪除構建之後的程式碼
rm -rf ./dist

# 伺服器現實新映象
ssh root@伺服器IP "cd /server_sh && ./伺服器上面對應的指令碼.sh"
複製程式碼
  • DockerFile
FROM node:8.9.3

COPY /dist /server

WORKDIR /server

ENV NODE_ENV=production

COPY /package.json /server

RUN npm install

CMD ["node", "./app.js"]
複製程式碼
  • 伺服器上面的指令碼
#!/bin/sh

# 啟動後端服務

#停止正在執行的映象
docker container stop 容器名

#刪除舊映象
docker container rm 容器名

#刪除image,確保下載的是最新映象
docker image rm 使用者名稱/映象名

#下載最新映象並啟動
docker run -d -p 3005:3005 --name 容器名 --network local-network --ip 192.168.0.105 使用者名稱/映象名
複製程式碼

最後

畢業一年多,第一次寫文章,不足之處,請求指出,十分感謝

相關文章