《Docker環境下的前后端分離部署與運維》課程腳本
[TOC]
一、Docker虛擬機常用命令
-
先更新軟件包
yum -y update
-
安裝Docker虛擬機
yum install -y docker
-
運行、重啟、關閉Docker虛擬機
service docker start service docker start service docker stop
-
搜索鏡像
docker search 鏡像名稱
-
下載鏡像
docker pull 鏡像名稱
-
查看鏡像
docker images
-
刪除鏡像
docker rmi 鏡像名稱
-
運行容器
docker run 啟動參數 鏡像名稱
-
查看容器列表
docker ps -a
停止、掛起、恢復容器
docker stop 容器ID
docker pause 容器ID
docker unpase 容器ID
-
查看容器信息
docker inspect 容器ID
-
刪除容器
docker rm 容器ID
-
數據卷管理
docker volume create 數據卷名稱 #創建數據卷 docker volume rm 數據卷名稱 #刪除數據卷 docker volume inspect 數據卷名稱 #查看數據卷
-
網絡管理
docker network ls 查看網絡信息 docker network create --subnet=網段 網絡名稱 docker network rm 網絡名稱
-
避免VM虛擬機掛起恢復之后,Docker虛擬機斷網
vi /etc/sysctl.conf
文件中添加`net.ipv4.ip_forward=1`這個配置
?```shell
#重啟網絡服務
systemctl restart network
?```
二、安裝PXC集群,負載均衡,雙機熱備
-
安裝PXC鏡像
docker pull percona/percona-xtradb-cluster:5.7.21
強烈推薦同學們安裝5.7.21版本的PXC鏡像,兼容性最好,在容器內可以執行apt-get安裝各種程序包。最新版的PXC鏡像內,無法執行apt-get,也就沒法安裝熱備份工具了。
-
為PXC鏡像改名
docker tag percona/percona-xtradb-cluster pxc
-
創建net1網段
docker network create --subnet=172.18.0.0/16 net1
-
創建5個數據卷
docker volume create --name v1 docker volume create --name v2 docker volume create --name v3 docker volume create --name v4 docker volume create --name v5
-
創建備份數據卷(用于熱備份數據)
docker volume create --name backup
-
創建5節點的PXC集群
注意,每個MySQL容器創建之后,因為要執行PXC的初始化和加入集群等工作,耐心等待1分鐘左右再用客戶端連接MySQL。另外,必須第1個MySQL節點啟動成功,用MySQL客戶端能連接上之后,再去創建其他MySQL節點。
#創建第1個MySQL節點 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql -v backup:/data --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc #創建第2個MySQL節點 docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v2:/var/lib/mysql -v backup:/data --privileged --name=node2 --net=net1 --ip 172.18.0.3 pxc #創建第3個MySQL節點 docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v3:/var/lib/mysql --privileged --name=node3 --net=net1 --ip 172.18.0.4 pxc #創建第4個MySQL節點 docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v4:/var/lib/mysql --privileged --name=node4 --net=net1 --ip 172.18.0.5 pxc #創建第5個MySQL節點 docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v5:/var/lib/mysql -v backup:/data --privileged --name=node5 --net=net1 --ip 172.18.0.6 pxc
-
安裝Haproxy鏡像
docker pull haproxy
-
宿主機上編寫Haproxy配置文件
vi /home/soft/haproxy/haproxy.cfg
配置文件如下:
global #工作目錄 chroot /usr/local/etc/haproxy #日志文件,使用rsyslog服務中local5日志設備(/var/log/local5),等級info log 127.0.0.1 local5 info #守護進程運行 daemon defaults log global mode http #日志格式 option httplog #日志中不記錄負載均衡的心跳檢測記錄 option dontlognull #連接超時(毫秒) timeout connect 5000 #客戶端超時(毫秒) timeout client 50000 #服務器超時(毫秒) timeout server 50000 #監控界面 listen admin_stats #監控界面的訪問的IP和端口 bind 0.0.0.0:8888 #訪問協議 mode http #URI相對地址 stats uri /dbs #統計報告格式 stats realm Global\ statistics #登陸帳戶信息 stats auth admin:abc123456 #數據庫負載均衡 listen proxy-mysql #訪問的IP和端口 bind 0.0.0.0:3306 #網絡協議 mode tcp #負載均衡算法(輪詢算法) #輪詢算法:roundrobin #權重算法:static-rr #最少連接算法:leastconn #請求源IP算法:source balance roundrobin #日志格式 option tcplog #在MySQL中創建一個沒有權限的haproxy用戶,密碼為空。Haproxy使用這個賬戶對MySQL數據庫心跳檢測 option mysql-check user haproxy server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000 server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000 server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000 server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000 server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000 #使用keepalive檢測死鏈 option tcpka
-
創建兩個Haproxy容器
#創建第1個Haproxy負載均衡服務器 docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --privileged --net=net1 --ip 172.18.0.7 haproxy #進入h1容器,啟動Haproxy docker exec -it h1 bash haproxy -f /usr/local/etc/haproxy/haproxy.cfg #創建第2個Haproxy負載均衡服務器 docker run -it -d -p 4003:8888 -p 4004:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h2 --privileged --net=net1 --ip 172.18.0.8 haproxy #進入h2容器,啟動Haproxy docker exec -it h2 bash haproxy -f /usr/local/etc/haproxy/haproxy.cfg
Haproxy容器內安裝Keepalived,設置虛擬IP
注意事項:云主機不支持虛擬IP,另外很多公司的網絡禁止創建虛擬IP(回家創建),還有宿主機一定要關閉防火墻和SELINUX,很多同學都因為這個而失敗的,切記切記
#進入h1容器
docker exec -it h1 bash
#更新軟件包
apt-get update
#安裝VIM
apt-get install vim
#安裝Keepalived
apt-get install keepalived
#編輯Keepalived配置文件(參考下方配置文件)
vim /etc/keepalived/keepalived.conf
#啟動Keepalived
service keepalived start
#宿主機執行ping命令
ping 172.18.0.201
配置文件內容如下:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.18.0.201
}
}
#進入h2容器
docker exec -it h2 bash
#更新軟件包
apt-get update
#安裝VIM
apt-get install vim
#安裝Keepalived
apt-get install keepalived
#編輯Keepalived配置文件
vim /etc/keepalived/keepalived.conf
#啟動Keepalived
service keepalived start
#宿主機執行ping命令
ping 172.18.0.201
配置文件內容如下:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
172.18.0.201
}
}
-
宿主機安裝Keepalived,實現雙機熱備
#宿主機執行安裝Keepalived yum -y install keepalived #修改Keepalived配置文件 vi /etc/keepalived/keepalived.conf #啟動Keepalived service keepalived start
Keepalived配置文件如下:
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.99.150 } } virtual_server 192.168.99.150 8888 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 172.18.0.201 8888 { weight 1 } } virtual_server 192.168.99.150 3306 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 172.18.0.201 3306 { weight 1 } }
-
熱備份數據
#進入node1容器 docker exec -it node1 bash #更新軟件包 apt-get update #安裝熱備工具 apt-get install percona-xtrabackup-24 #全量熱備 innobackupex --user=root --password=abc123456 /data/backup/full
-
冷還原數據
停止其余4個節點,并刪除節點docker stop node2 docker stop node3 docker stop node4 docker stop node5 docker rm node2 docker rm node3 docker rm node4 docker rm node5
node1容器中刪除MySQL的數據
#刪除數據 rm -rf /var/lib/mysql/* #清空事務 innobackupex --user=root --password=abc123456 --apply-back /data/backup/full/2018-04-15_05-09-07/ #還原數據 innobackupex --user=root --password=abc123456 --copy-back /data/backup/full/2018-04-15_05-09-07/
重新創建其余4個節點,組件PXC集群
三、PXC 特別注意事項
PXC的主節點和從節點分別代表什么意義?
PXC中的主節點和從節點跟Replication主從節點是有巨大差別的。
首先Replication集群的數據同步只能是從主節點到從節點,而且節點的身份是固定的,主節點永遠是Master,從節點永遠是Slave,不能互換。
但是PXC上的主節點指的是第一個啟動的節點,它不僅要啟動MySQL服務,還要用Galera創建PXC集群。這些工作完成之后,主節點自動降級成普通節點。其他節點啟動的時候只需要啟動MySQL服務,然后再加入到PXC集群即可,所以這些節點從啟動到關閉,身份一直都是普通節點。
為什么Node1能啟動,而其他的PXC節點啟動就閃退呢?
這是因為Node1啟動的時候要做跟多工作,上面已經提及了。所以你沒等node1把PXC集群創建出來,你就飛快的啟動其他PXC節點,它們找不到Node1啟動的PXC集群,所以就自動閃退了。
正確的辦法是啟動Node1之后,等待10秒鐘,然后用Navicat訪問一下,能訪問了,再去啟動其他PXC節點
如果PXC集群在運行的狀態下,在宿主機上直接關機,或者停止Docker服務,為什么下次啟動哪個PXC節點都會閃退?
這個要從PXC集群的節點管理說起,PXC節點的數據目錄是/var/lib/mysql,好在這個目錄被我們映射到數據卷上了。比如你訪問v1數據卷就能看到node1的數據目錄。這其中有個grastate.dat的文件,它里面有個safe_to_bootstrap參數被PXC用來記載誰是最后退出PXC集群的節點。比如node1是最后關閉的節點,那么PXC就會在把safe_to_bootstrap設置成1,代表node1節點最后退出,它的數據是最新的。下次啟動必須先啟動node1,然后其他節點與node1同步。
如果你在PXC節點都正常運行的狀態下關閉宿主機Docker服務或者電源,那么PXC來不及判斷誰是最后退出的節點,所有PXC節點一瞬間就都關上了,哪個節點的safe_to_boostrap參數就都是0。解決這個故障也很好辦,那就是挑node1,把該參數改成1,然后正常啟動node1,再啟動其他節點就行了。
PXC集群只有一個節點,關閉了這個節點的容器,下次還能啟動起來嗎?
當然是可以的,因為PXC里只有一個節點,那么這個節點一定是按照主節點啟動的,所以啟動它的時候,它會啟動MySQL服務,還創建出PXC集群。即便關閉了容器,下次再啟動還是這個步驟,不會出現啟動故障。如果說PXC集群是由多個節點組成的,node1停掉了,其他節點都正常運行。這時候啟動node1是會出現閃退的,node1剛啟動幾秒鐘就掛了。這是因為node2等一些節點正在現有的PXC中運行,這時候你啟動node1,再創建一個同名的PXC集群,肯定會引發沖突啊。所以node1就閃退了。
遇到這種情況,正確的處理辦法是,把node1容器刪除。別緊張,沒讓你刪除v1數據卷,所以數據丟不了。然后用從節點的命令方式創建一個node1,啟動參數中與某個節點同步的設置就隨便選擇一個現在運行的PXC節點,然后Node1就能啟動了。
關于搭建技術體系,深入學習方面的感言
? 本門課程的數據庫部分只講到數據庫集群怎么搭建,如果想要完全駕馭數據庫,僅憑這點知識還是遠遠不夠的。像我在PXC免費課中講到的,我們首先要有一個明確的知識體系,下一步就是做知識分解,一點點把技術拼圖給完成。我見過非常多,東學一下,西學一下的人,即便有10年的工作經驗,依然難成大器。比如說前些年VR挺火的,現在區塊鏈技術也挺火的。我是個快要畢業的大學生,我想學這些技術幫我找一份好的工作。其實這種想法不是不對,但是過于急功近利。我先把話題說的遠一點,咱們一會兒再回來說技術規劃的事情。
? 在2013年,雷軍和董明珠打了個賭,如果小米在5年內營業額超過格力,董明珠輸給雷軍10個億,反之也是如此。兩家企業相比較,大家更看好雷軍的小米。這是因為中國的制造業利潤太薄,制造業盈利存在上限的天花板,所以我們能準確預測出一家制造業企業未來的盈利空間。但是互聯網公司就不是這樣,想象空間太巨大。比如說馬云的阿里巴巴,從1999年創建,到2014年上市,用了15年時間。劉強東的京東商城,差不多也用了15年時間上市。但是到了黃錚的拼多多這里,只用了3年時間就完成了上市,他還一舉超過劉強東,成為中國第六富豪。IT界一夜成名的還有滴滴打車的程維、美團的王興等等。
? 也正是IT互聯網公司造富神話太多,也就越來越多的資本涌入IT圈。有的資本公司做長線,但是更多的資本公司炒短線。先投資一家小公司,然后再制造行業輿論和技術導向,當人們被技術忽悠的瘋狂的時候,有人肯接盤了,這時候再把投資的這家小公司賣掉,割一波韭菜就撤。于是我們看到太多太多被熱炒的技術,沒過1年時間就無人問津了。比如2014年的iOS技術,2015年的VR技術等等。當年VR技術被捧到天上,王雪紅一度被業界認為會用VR讓HTC翻身,可是到現在我們再也聽不到HTC這家公司的新聞了。活著還是倒閉了,我們都不知道,大家也不關心。
? 所以我們選擇一個技術方向的時候,首先要看這個領域是不是有太多的水分,是不是有太多的熱錢。比如今年3月的時候,真格基金的徐小平發了一個微博說自己非常看好以太坊技術,于是短短時間,中國各家資本公司紛紛涌入區塊鏈領域。甚至還出現了2萬塊錢的區塊鏈講師速成班,不管懂不懂計算機,都能給你在短期內培養成區塊鏈專家,然后你再去培訓機構忽悠人,月薪兩萬,割學技術大學生的韭菜。我想,徐小平在微博上把區塊鏈捧到天上,何嘗不是一種資本炒作的手法呢。
? 最后說回到技術領域這塊。比如你是一個大學生,想投身一個有發展的技術方向,那么不妨拿起手機看看那些常用的APP上都用到了什么技術,這才是能落地能普及的。比如說刷抖音很容易上癮,上劃一條是你喜歡的視頻,再上劃一下,又是你感興趣的視頻。還有每個人打開淘寶APP,首頁的內容都不一樣,都是你喜歡的商品,看什么東西都想賣。淘寶也很絕,即使你不花錢買東西,只要你點擊看了一個你喜歡的商品,從此以后,你各項愛好都被淘寶所感知了。這種技術是大數據上的協同過濾。說簡單一點,就是掌握了你很少資料的情況下,去分析跟你有相同行為的人的喜好,于是推算出你的喜好。比如你點擊了某個牌子的運動鞋,那么淘寶的協同過濾就會計算購買了這個運動鞋的用戶,還買了什么東西,這些用戶共性的東西,就是你的愛好。所以你再打開淘寶APP,看到的都是你喜歡的東西。抖音啊,今日頭條啊,都是這樣的技術。所以你學大數據,這個技術是能落地的,太多產品在用這個技術了。相比較而言,區塊鏈和人工智能就顯得太高冷了。不是說技術不好,但是距離大規模普及還是有很遠的距離。比如說區塊鏈吧,上半年好多企業都在炒作,不跟區塊鏈掛鉤好像都不是科技企業,甚至南方有家茶葉公司,把名字都改成了帶有區塊鏈字眼。這就像荷蘭的郁金香泡沫,當人們都意識到郁金香根本就不值那么高價格的時候,于是泡沫就破裂了。比如極路由公司,把自己的路由器搞成了能挖礦,每天平均賺4塊錢。我們知道1萬塊錢存到支付寶上,一天也產生不了1塊錢的利益。現在幾百塊錢的極路由每天產生4塊錢的收益,不就相當你花幾百塊錢享受幾萬塊錢的利息收益嗎,多讓人瘋狂啊。極路由一邊忽悠消費者,一邊又去忽悠投資人,還跟互聯網金融公司合作,弄了多種套餐玩法。投資人和消費者都被忽悠熱血沸騰,拿出十幾萬塊錢,買極路由器,幻想自己在家當地主,天天幾百塊錢收入。但是不到半年時間,極路由的技術+金融戲法就玩不下去了,老板欠了3.5個億跑路了。同學們也不妨搜索一下因為區塊鏈破產的消費者和炒作者。你投身這樣的領域覺得靠譜嗎?
? 所以選擇技術規劃一定要挑選成熟的,應用范圍廣泛的。比如大數據、Java體系、前端體系、Python體系等等。所以就像我在免費課里說到的,你選擇好一個發力的方向,剩下的就是如何分解知識點了。比如說,你學了Java的一部分,沒去深挖微服務架構和集群架構。如果你只停留在做單體項目,比如說SSM實現一個管理項目,VUE做一個網站等等,那我可以保證,你在IT開發這個領域很難堅持10年。經常聽說,做開發30歲要轉行,公司里幾乎看不見40歲還做開發的人。其中的原因很多人沒講到關鍵點,作為創業者和企業家的角度來看,如果一個開發者,技術只停留在用SSM架構套各種業務,今天做一個管理系統,明天做一個管理系統。因為單體項目很難支撐高并發,所以你做的項目基本都是在小公司內部使用。隨著你工作年限增加,對企業來說用人成本也就變高了。用一個2年經驗的開發者,也會使用SSM做項目,成本還低,那為什么不用這樣的人呢。所以你就被企業無情的拋棄了,根本原因是技術停滯,成本太高。這時候你再想跳槽到大企業,技術和年齡都達不到要求了。所以我建議年輕人,參加工作以后,雖然崗位有界限,但是技術無界限。前端、后臺、數據庫、原型設計、項目管理,多少都要學一些,沒人教,就自己總結。只有技術全才,才能勝任技術團隊的管理者,才不會被企業淘汰。
? 其實我見過很多項目都是被不稱職的管理者給弄黃的。也許你也有同感,這個項目A公司做過,B公司做過,現在客戶找到我們又要重做一版,這是為什么呢?項目開發的失敗率也太高了吧。這通常是項目管理者技術不過關導致的,比如說A客戶去南方考察,覺得某公司的管理系統特別好,我想也做一套。于是找到了你,A客戶是大老板,下面具體的業務細節說不太清楚,腦子里也沒有清晰的想法,反正想到什么就東一句、西一句的,然后你貿然選用了瀑布模型開發。經過了需求分析、文檔設計,總算進入到了開發。經過兩個月的開發,終于可以拿出半成品給A客戶了,這時候A客戶說你做的不是他想要的東西,要不你推到重做把,要不我找別的公司去做。然后別的公司做了,A客戶依然不滿意,于是開啟了無限的重做模式。
? 究其原因還是管理者用錯了開發模型,瀑布模型看似合理,但是問題在于編碼階段太靠后,等拿出半成品已經小半年時間過去了。因此瀑布模型適用于那種能提出明確需求,而且到每一處細節的客戶。像A客戶這樣的人,我們應該用螺旋模型去開發,小規模快速迭代,只開發最核心模塊,短期內就拿出演示品跟客戶確認。這種小步快跑的策略適合提不出具體需求和需求不明確的場合。所以說,同學,以后你想做管理者,是不是得了解“軟件工程”的知識啊!
? 這幾年我在教育部舉辦的互聯網+創新創業大賽預賽和決賽當評委的時候,跟很多大學生創業的同學講到了,你的創業想法很好,但是很可能項目會作廢了。起初他們不相信,覺得自己拿到風投的錢,幾個學軟件的同學會編程,這就足夠了。于是次年的時候,我又見到了這些同學,參賽的題目又換了。我就好奇的問他們,去年的創業項目做成了嗎?他們跟我說,創業項目做砸了。呵呵,果然是這樣。因為他們的團隊里缺少了技術方面的全才。僅靠專才是不能完成項目開發的。我再舉一個例子,某公司的開發者老張,他是做后端比較擅長,因為工作年頭比較長了,于是就被提拔成了項目經理。有一天,日方客戶發來一封郵件,說某模塊的業務流程要修改,看看中方這邊多長時間能實現,費用是多少。于是老張就召集團隊的人開了一次會。老張擅長后臺開發,這次需求覺得沒什么難度,然后問了問數據庫的哥們和前端的哥們,他們說也好實現,然后老張就承諾日方兩天就能做完。但是過于樂觀的態度,很容易引來噩夢般的后果。數據庫的哥們和前端的哥們,寫代碼的時候才發現實現難度很大,最后花了半個月才做完,浪費了大量的加班費用。因為老張不懂前端,也不懂數據庫集群,覺得底下人說什么就代表什么。由此看出,管理者技術必須全面,不能人云亦云,必須保持自己的判斷力。
? 說了這么多,也非常感謝大家在慕課網上支持我的課程,后續我還會在慕課網上錄制更多的實戰課,將我們的技術體系拼圖給逐步完成。目前正在錄制Python的課程和其他的開發課程,請大家稍加等待。下面列出來我在慕課網上所有課程的連接,以供大家學習。
《MySQL數據庫集群-PXC方案》
https://coding.imooc.com/class/274.html
《Docker環境下的前后端分離項目部署與運維》
https://coding.imooc.com/class/219.html
安裝Redis,配置RedisCluster集群
-
安裝Redis鏡像
docker pull yyyyttttwwww/redis
-
創建net2網段
docker network create --subnet=172.19.0.0/16 net2
-
創建6節點Redis容器
docker run -it -d --name r1 -p 5001:6379 --net=net2 --ip 172.19.0.2 redis bash docker run -it -d --name r2 -p 5002:6379 --net=net2 --ip 172.19.0.3 redis bash docker run -it -d --name r3 -p 5003:6379 --net=net2 --ip 172.19.0.4 redis bash docker run -it -d --name r4 -p 5004:6379 --net=net2 --ip 172.19.0.5 redis bash docker run -it -d --name r5 -p 5005:6379 --net=net2 --ip 172.19.0.6 redis bash
注意:redis配置文件里必須要設置bind 0.0.0.0,這是允許其他IP可以訪問當前redis。如果不設置這個參數,就不能組建Redis集群。
-
啟動6節點Redis服務器
#進入r1節點 docker exec -it r1 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf #進入r2節點 docker exec -it r2 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf #進入r3節點 docker exec -it r3 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf #進入r4節點 docker exec -it r4 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf #進入r5節點 docker exec -it r5 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf #進入r6節點 docker exec -it r6 bash cp /home/redis/redis.conf /usr/redis/redis.conf cd /usr/redis/src ./redis-server ../redis.conf
-
創建Cluster集群
#在r1節點上執行下面的指令 cd /usr/redis/src mkdir -p ../cluster cp redis-trib.rb ../cluster/ cd ../cluster #創建Cluster集群 ./redis-trib.rb create --replicas 1 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379
打包部署后端項目
-
進入人人開源后端項目,執行打包(修改配置文件,更改端口,打包三次生成三個JAR文件)
mvn clean install -Dmaven.test.skip=true
-
安裝Java鏡像
docker pull java
-
創建3節點Java容器
#創建數據卷,上傳JAR文件 docker volume create j1 #啟動容器 docker run -it -d --name j1 -v j1:/home/soft --net=host java #進入j1容器 docker exec -it j1 bash #啟動Java項目 nohup java -jar /home/soft/renren-fast.jar #創建數據卷,上傳JAR文件 docker volume create j2 #啟動容器 docker run -it -d --name j2 -v j2:/home/soft --net=host java #進入j1容器 docker exec -it j2 bash #啟動Java項目 nohup java -jar /home/soft/renren-fast.jar #創建數據卷,上傳JAR文件 docker volume create j3 #啟動容器 docker run -it -d --name j3 -v j3:/home/soft --net=host java #進入j1容器 docker exec -it j3 bash #啟動Java項目 nohup java -jar /home/soft/renren-fast.jar
-
安裝Nginx鏡像
docker pull nginx
-
創建Nginx容器,配置負載均衡
宿主機上/home/n1/nginx.conf配置文件內容如下:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; upstream tomcat { server 192.168.99.104:6001; server 192.168.99.104:6002; server 192.168.99.104:6003; } server { listen 6101; server_name 192.168.99.104; location / { proxy_pass http://tomcat; index index.html index.htm; } } }
創建第1個Nginx節點
docker run -it -d --name n1 -v /home/n1/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
宿主機上/home/n2/nginx.conf配置文件內容如下:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; upstream tomcat { server 192.168.99.104:6001; server 192.168.99.104:6002; server 192.168.99.104:6003; } server { listen 6102; server_name 192.168.99.104; location / { proxy_pass http://tomcat; index index.html index.htm; } } }
創建第2個Nginx節點
docker run -it -d --name n2 -v /home/n2/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
-
在Nginx容器安裝Keepalived
#進入n1節點 docker exec -it n1 bash #更新軟件包 apt-get update #安裝VIM apt-get install vim #安裝Keepalived apt-get install keepalived #編輯Keepalived配置文件(如下) vim /etc/keepalived/keepalived.conf #啟動Keepalived service keepalived start
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.99.151 } } virtual_server 192.168.99.151 6201 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.99.104 6101 { weight 1 } }
#進入n1節點 docker exec -it n2 bash #更新軟件包 apt-get update #安裝VIM apt-get install vim #安裝Keepalived apt-get install keepalived #編輯Keepalived配置文件(如下) vim /etc/keepalived/keepalived.conf #啟動Keepalived service keepalived start
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.99.151 } } virtual_server 192.168.99.151 6201 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.99.104 6102 { weight 1 } }
打包部署后端項目
-
在前端項目路徑下執行打包指令
npm run build
build目錄的文件拷貝到宿主機的/home/fn1/renren-vue、/home/fn2/renren-vue、/home/fn3/renren-vue的目錄下面
-
創建3節點的Nginx,部署前端項目
宿主機/home/fn1/nginx.conf的配置文件
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; server { listen 6501; server_name 192.168.99.104; location / { root /home/fn1/renren-vue; index index.html; } } }
#啟動第fn1節點 docker run -it -d --name fn1 -v /home/fn1/nginx.conf:/etc/nginx/nginx.conf -v /home/fn1/renren-vue:/home/fn1/renren-vue --privileged --net=host nginx
宿主機/home/fn2/nginx.conf的配置文件
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; server { listen 6502; server_name 192.168.99.104; location / { root /home/fn2/renren-vue; index index.html; } } }
#啟動第fn2節點 docker run -it -d --name fn2 -v /home/fn2/nginx.conf:/etc/nginx/nginx.conf -v /home/fn2/renren-vue:/home/fn2/renren-vue --privileged --net=host nginx
宿主機/home/fn3/nginx.conf的配置文件
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; server { listen 6503; server_name 192.168.99.104; location / { root /home/fn3/renren-vue; index index.html; } } }
啟動fn3節點
#啟動第fn3節點 docker run -it -d --name fn3 -v /home/fn3/nginx.conf:/etc/nginx/nginx.conf -v /home/fn3/renren-vue:/home/fn3/renren-vue --privileged --net=host nginx
-
配置負載均衡
宿主機/home/ff1/nginx.conf配置文件
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; upstream fn { server 192.168.99.104:6501; server 192.168.99.104:6502; server 192.168.99.104:6503; } server { listen 6601; server_name 192.168.99.104; location / { proxy_pass http://fn; index index.html index.htm; } } }
#啟動ff1節點 docker run -it -d --name ff1 -v /home/ff1/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
宿主機/home/ff2/nginx.conf配置文件
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; upstream fn { server 192.168.99.104:6501; server 192.168.99.104:6502; server 192.168.99.104:6503; } server { listen 6602; server_name 192.168.99.104; location / { proxy_pass http://fn; index index.html index.htm; } } }
#啟動ff2節點 docker run -it -d --name ff2 -v /home/ff2/nginx.conf:/etc/nginx/nginx.conf --net=host --privileged nginx
-
配置雙機熱備
#進入ff1節點 docker exec -it ff1 bash #更新軟件包 apt-get update #安裝VIM apt-get install vim #安裝Keepalived apt-get install keepalived #編輯Keepalived配置文件(如下) vim /etc/keepalived/keepalived.conf #啟動Keepalived service keepalived start
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.99.152 } } virtual_server 192.168.99.151 6701 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.99.104 6601 { weight 1 } }
#進入ff1節點 docker exec -it ff2 bash #更新軟件包 apt-get update #安裝VIM apt-get install vim #安裝Keepalived apt-get install keepalived #編輯Keepalived配置文件(如下) vim /etc/keepalived/keepalived.conf #啟動Keepalived service keepalived start
vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 52 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 192.168.99.152 } } virtual_server 192.168.99.151 6701 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.99.104 6602 { weight 1 } }
?