摘要:于是,程序不再是原先單一的服務(wù),而是,變成了一系列密切相關(guān)的服務(wù)。需要注意的是,在模式下申請(qǐng)證書(shū),需要向證明服務(wù)器能被訪問(wèn)。
首先,祝各位新年快樂(lè),萬(wàn)事如意,雞年大吉。
這次要來(lái)說(shuō)說(shuō)一個(gè)和前端并不太相關(guān)的東西——docker compose,一個(gè)整合發(fā)布應(yīng)用的利器。
如果,你對(duì) docker 有一些耳聞,那么,你可能知道它是什么。
不過(guò),你不了解也沒(méi)有關(guān)系,在作者眼中,docker 就類似于一個(gè)沙箱,而你的應(yīng)用起在這個(gè)沙箱里,不受服務(wù)器系統(tǒng)環(huán)境的影響,同時(shí)也不污染服務(wù)器,配置完成之后往服務(wù)器部署或移除應(yīng)用都相當(dāng)方便。
而 compose 就如同它的字面意思組合,它就好像是一個(gè)大箱子,可以把幾個(gè)不相關(guān)的沙箱給組合起來(lái),變成一個(gè)整體,就如同小時(shí)候動(dòng)畫(huà)片中變形金剛的合體變身。
理論知識(shí)就沒(méi)有什么比官方文檔更好的了,這里就不講了,主要來(lái)看看如何應(yīng)用。本文主要包含以下幾個(gè)部分:
安裝
Hello world
常用命令
Real world
docker 到 docker-compose 的轉(zhuǎn)換
引入 nginx
Letsencrypt 鏡像生成 SSL 證書(shū)
最后
如果,你只對(duì)前端技術(shù)感興趣,那么,這篇文章可能不適合你。
安裝常言道:一個(gè)不懂運(yùn)維的設(shè)計(jì),不是一個(gè)好前端。
Windows 和 Mac 裝了 Docker 之后已經(jīng)自帶 docker-compose,其他環(huán)境根據(jù) Docker 官網(wǎng)介紹,簡(jiǎn)單幾步也能完成安裝。
這里要提一下,在亞馬遜 aws 上安裝 docker-compose,由于沒(méi)有 root 權(quán)限會(huì)遇到官網(wǎng)上所提到的 Permission denied 錯(cuò)誤,加了 sudo 也是無(wú)法直接下載到 /usr/local/bin 目錄下的。
硬來(lái)不行,還可以曲線救國(guó)嘛~
先將文件下載到 aws 服務(wù)器上,再將文件移動(dòng)到 /usr/local/bin 目錄就可以了。
curl -L https://github.com/docker/compose/releases/download/1.9.0/docker-compose-`uname -s`-`uname -m` > docker-compose sudo chown root docker-compose sudo mv docker-compose /usr/local/bin sudo chmod +x /usr/local/bin/docker-compose
驗(yàn)證是否安裝成功,試試 docker-compose version。如果有輸出版本信息,就說(shuō)明 docker-compose 已經(jīng)安裝好了。
docker-compose 雖然安裝好了,但并不一定能用,因?yàn)?docker 和 docker-compose 是分開(kāi)安裝,即使它倆各自運(yùn)行正常,在一起就不一定合拍了。
那怎么知道它倆合不合拍?答案很簡(jiǎn)單,hello world~
Hello world在任意的目錄下,創(chuàng)建一個(gè) docker-compose.yml 文件,并添加下面的內(nèi)容。
version: "2" services: helloworld: image: "hello-world"
然后,在當(dāng)前目錄下使用 docker-compose up 啟動(dòng) docker-compose。
啟動(dòng)時(shí),如遇到
client and server don"t have same version (client : 1.22, server: 1.18)
類似這樣的錯(cuò)誤,可以通過(guò)設(shè)置 docker-compose 的 api 版本來(lái)解決。
COMPOSE_API_VERSION=auto
不要嘗試通過(guò)一次次安裝不同的 docker-compose 版本來(lái)解決,你會(huì) ? 的。如果,還遇到
docker.errors.InvalidVersion: inspect_network is not available for version < 1.21
這是 Ubuntu 14.04 LTS 默認(rèn)的 docker 版本太低引起的,需要升級(jí) docker。然而,在 aws 的服務(wù)器上升級(jí) docker 版本時(shí),需要先創(chuàng)建 /etc/apt/sources.list.d/docker.list 文件,并添加
deb https://packages.docker.com/1.12/apt/repo ubuntu-trusty main
再運(yùn)行
sudo apt-get update && sudo apt-get upgrade docker-engine
就能升級(jí)成功??吹?這樣的結(jié)果,就表示 docker 和 docker-compose 都安裝成功,而且它倆很搭。
常用命令docker-compose 的命令很簡(jiǎn)單,它已經(jīng)將一些 docker 常用關(guān)于 image, container & volume 的命令都整合在了一起,使發(fā)布變得極其簡(jiǎn)單。比如,之前剛剛提到的 docker-compose up,就類似于 docker build & run,用來(lái)創(chuàng)建并啟動(dòng) container。
其他常用的命令有:
build:構(gòu)建或重新構(gòu)建 services
config:驗(yàn)證 docker-compose 配置文件
create:創(chuàng)建 services
down:與 up 相對(duì),停止并刪除 container, image, volumn 等
kill:殺死某個(gè) container
logs:查看 container 日志
ps:查看 container 信息
restart:重啟 services
rm:刪除已經(jīng)停止的 container
start:?jiǎn)?dòng) services
stop:停止 service
version:顯示 docker-compose 版本
是不是發(fā)現(xiàn)有幾個(gè)命令和 docker 的命令一樣?的確,但就如同之前的安裝過(guò)程一樣,docker-compose 是依賴于 docker 的,docker 命令更底層。比如 docker-compose ps 這個(gè)命令,它只會(huì)顯示由 docker-compose 啟動(dòng)的容器信息,但不包含 docker 啟動(dòng)的容器信息,相反 docker ps 可以查看由 docker-compose 啟動(dòng)的容器信息。
還剩幾個(gè)命令沒(méi)有列出來(lái),有興趣的童鞋可以通過(guò) docker-compose help 命令或上官網(wǎng)查看更多信息。
光說(shuō)不練假把式。docker-compose 究竟好不好用,只有用了才知道。
Real world之前,個(gè)人博客的靜態(tài)資源一直都是通過(guò) node 提供服務(wù)。這的確可以,但這不是 node 的強(qiáng)項(xiàng)。
專業(yè)的事交給專業(yè)的人去做。 - by S(ome)B(ody)
這個(gè)專業(yè)的人就是 nginx。
除此之外,2017 年起水果和古哥都強(qiáng)推 https,升級(jí) https 也是箭在弦上(雖然一直有這個(gè)打算,也拖到了現(xiàn)在彡(-_-;)彡)。
于是,程序不再是原先單一的 node 服務(wù),而是,變成了一系列密切相關(guān)的服務(wù)。如果,通過(guò)基礎(chǔ)的 docker 命令來(lái)一個(gè)個(gè)啟動(dòng)、停止服務(wù)的話,那么,就需要額外添加一個(gè)復(fù)雜的腳本來(lái)控制。
docker-compose 就是用來(lái)處理類似的問(wèn)題。它可以做到通過(guò)一條命令來(lái)控制一個(gè)應(yīng)用相關(guān)的一系列服務(wù)的啟動(dòng)、停止等,并且不依賴于機(jī)器環(huán)境,作到隨時(shí)可以將應(yīng)用遷移至其他的機(jī)器上發(fā)布。
知道了準(zhǔn)備做什么,先看看最終設(shè)計(jì)的應(yīng)用結(jié)構(gòu)和之前的對(duì)比。
直接看這張圖可能有點(diǎn)蒙圈,沒(méi)事,一點(diǎn)點(diǎn)來(lái)看。
docker 到 docker-compose 的轉(zhuǎn)換本文一開(kāi)始就有提到,docker 可以看做是一個(gè)小箱子,而 docker-compose 是一個(gè)大箱子用來(lái)裝這些小箱子。
那么,如何將小箱子放入這個(gè)大箱子里哪?
非常簡(jiǎn)單!只需告訴 docker-compose 如何啟動(dòng)你的應(yīng)用就可以了,那就先看看原先的啟動(dòng)命令。
docker run -d -p 80:8080 --name blog
啟動(dòng)命令中,主要配置了一個(gè)端口的映射 -p,以及命名了容器名,用于方便地啟動(dòng)、停止應(yīng)用。清楚了這些,那么改成 docker-compose 的文件也就輕而易舉了。
version: "2" services: node: build: . container_name: node ports: - "80:8080"
docker 到 docker-compose 的轉(zhuǎn)換就這樣完成了,這些更新都不需要修改任何的業(yè)務(wù)邏輯或者打包配置。
試著使用 docker-compose up -d 啟動(dòng)服務(wù)驗(yàn)證看看。
啟動(dòng)正常之后,還是一步步來(lái),先引入 nginx。
引入 NginxNginx 是一個(gè)高性能的 Web 服務(wù)器,它具有配置簡(jiǎn)單、運(yùn)行穩(wěn)定和負(fù)載均衡等特點(diǎn),常被作為靜態(tài)資源服務(wù)器。(詳細(xì)的 Nginx 信息,請(qǐng)自行查詢資料,這方面本人也不是行家)
Nginx 在 docker hub 上有現(xiàn)成的官方鏡像,直接拿來(lái)用就可以了。
version: "2" services: # ... nginx: image: nginx:stable container_name: nginx ports: - "80:80" restart: always
此時(shí),啟動(dòng)服務(wù)會(huì)失敗并報(bào)錯(cuò),因?yàn)?nginx 和原有的 node 容器都綁定到了 80 端口。docker-comopse 各個(gè)容器之間是相互獨(dú)立的,容器內(nèi)部的接口相互之間不影響,但對(duì)外暴露的接口不能相同,不然就會(huì)引起沖突。
從之前的結(jié)構(gòu)圖可以看到,請(qǐng)求全部由 nginx 接受并轉(zhuǎn)發(fā)到 node 服務(wù),也就是說(shuō),node 不直接對(duì)外提供服務(wù)。那么,docker-compose 中也就可以移除 ports 部分(這里便于測(cè)試 node 服務(wù)依舊暴露 8080 端口)。
其次,靜態(tài)文件是由 node 打包后生成的,也就是說(shuō)需要將 node 服務(wù)中的數(shù)據(jù)共享給 nginx 服務(wù),這就需要用到 volume(數(shù)據(jù)卷)。數(shù)據(jù)卷可以將數(shù)據(jù)在宿主機(jī)和容器之間、容器和容器之間共享,即使容器被刪除了,數(shù)據(jù)卷依舊存在。
這里就需要將服務(wù)器上的 nginx 配置文件和 node 構(gòu)建之后的靜態(tài)文件共享給 nginx。
version: "2" services: node: build: . container_name: node # node service port export for test ports: - "8080:8080" volumes: - ./log/node:/var/log/node nginx: image: nginx:stable container_name: nginx depends_on: - node volumes: - ./config/nginx:/etc/nginx/conf.d:ro - ./log/nginx:/var/log/nginx volumes_from: - node:ro ports: - "80:80" restart: always
volume 是 docker 中相當(dāng)重要及常用的一部分,理解它對(duì)使用 docker 解決問(wèn)題有巨大的幫助。推薦一篇關(guān)于 docker volume 的文章,有助于理解 volume。
負(fù)載均衡docker-compose 配置完了,再來(lái)看看 nginx 配置。本章一開(kāi)始有提到 nginx 可以做負(fù)載均衡,那該如何配置哪?
在 nginx 中配置負(fù)載均衡相當(dāng)簡(jiǎn)單,只需在 upstream 里配置一下目標(biāo)服務(wù)器。
然而,這里就會(huì)遇到一個(gè)問(wèn)題。由于,容器之間是相互獨(dú)立的,于是,localhost 便無(wú)法在容器之間相互訪問(wèn)。不過(guò),由同一 docker-compose 所起的容器之間可以通過(guò)容器名相互訪問(wèn),這里就是
upstream node_server { server node:8080 max_fails=2 fail_timeout=30s; }
如果要額外再起一個(gè)服務(wù),只需在 docker-compose 文件中再啟動(dòng)一個(gè)容器(可以依賴同一套代碼),并將之前所配的 upstream 中額外多添加一條 server 信息,比如:
upstream node_server { server node:8080 max_fails=2 fail_timeout=30s; server node-backup:8080 max_fails=2 fail_timeout=30s; }
這樣即使一個(gè)服務(wù)掛了,只要另一個(gè)服務(wù)還運(yùn)行正常,nginx 會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給運(yùn)行正常的服務(wù)。一個(gè)最簡(jiǎn)單的復(fù)雜均衡就做好了,所有這些都不需要修改任何功能性的代碼。
知道了 nginx 可以提供負(fù)載均衡,但也不要忘了老朋友 pm2。
pm2 通過(guò)命令行參數(shù) -i,或配置文件通過(guò)起多個(gè)實(shí)例來(lái)做負(fù)載均衡(本人的小博客也是用的這個(gè)方式)。
引入 nginx 之后,將全站升級(jí)成 https 就輕而易舉了,只需在配置文件中標(biāo)明證書(shū)及秘鑰文件的位置就可以了。接下去,就看看如何生成證書(shū)和秘鑰。
使用 Letsencrypt 生成 SSL 證書(shū)獲取 ssl 證書(shū)的方式有許多種,有的買域名就送證書(shū),這里介紹一下用 letsencrypt(現(xiàn)已更名為 certbot)獲取免費(fèi) ssl 證書(shū)。
常言道:前人栽樹(shù),后人乘涼。
同樣的,letsencrypt 在 docker hub 上也有現(xiàn)成的鏡像。鏡像有了,剩下的就只需根據(jù)不同的場(chǎng)景來(lái)生成證書(shū)。
certbot 支持 5 種生成證書(shū)的模式,分別是:apache, nginx, webroot, standalone 和 manual,分別用于不同的場(chǎng)景。這里 nginx 和 certbot 使用的是不同的鏡像,所以選用的模式是 webroot。
選定了鏡像和模式,那么參照 certbot 的文檔就能夠簡(jiǎn)單地生成證書(shū)了。
docker run -it --rm --name certbot -v /letsencrypt/etc/letsencrypt:/etc/letsencrypt -v /letsencrypt/lib/letsencrypt:/var/lib/letsencrypt -v /letsencrypt/challenge:/usr/share/nginx/html -v /var/log/letsencrypt:/var/log/letsencrypt deliverous/certbot certonly --webroot -w /usr/share/nginx/html
需要注意的是,在 webroot 模式下申請(qǐng)證書(shū),需要向 certbot 證明服務(wù)器能被訪問(wèn)。certbot 驗(yàn)證程序會(huì)訪問(wèn) web root 目錄(這里是 /usr/share/nginx/html)來(lái)驗(yàn)證。這里又要用到之前提到的 volume 將目錄共享給 nginx,讓 nginx 能夠訪問(wèn)到目錄內(nèi)部的文件。
server { listen 80; listen [::]:80; server_name discipled.me; # ... # letsencrypt challenge file location location /.well-known { root /usr/share/nginx/html; access_log /var/log/nginx/challenge-access.log main; allow all; } ... }
修改 nginx 配置之后,別忘重啟 nginx 服務(wù)。
docker-compose restart nginx
重啟 nginx 之后,然后再運(yùn)行上面生成證書(shū)的命令就能生成證書(shū)了。
看到 Congratulations!,證書(shū)就生成成功了。
再一次修改 nginx 配置,添加 ssl 證書(shū)信息,并監(jiān)聽(tīng) 443 端口。
# redirect host http://domain to https://domain server { listen 80; listen [::]:80; server_name discipled.me; # letsencrypt challenge file location location /.well-known { root /usr/share/nginx/html; access_log /var/log/nginx/challenge-access.log main; allow all; } location / { return 301 https://discipled.me$request_uri; } } # https://domain server server { listen 443 ssl; listen [::]:443 ssl; server_name discipled.me; charset utf-8; gzip on; gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css; root /usr/app/build/client/; ssl_certificate /etc/letsencrypt/live/discipled.me/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/discipled.me/privkey.pem; location / { try_files $uri @node; } location @node { proxy_pass http://node_server; 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; } }
重啟 nginx 服務(wù)后,訪問(wèn)網(wǎng)站就可以看到
小鎖加上,大功告成。
證書(shū)更新七牛的圖床用 https 還要實(shí)名認(rèn)證,為了保護(hù)(pa)個(gè)(cha)人(shui)隱(biao)私,就暫時(shí)用 Github 來(lái)救一下急。(誰(shuí)知道有啥好用的圖床麻煩推薦一下,像七牛一樣支持 qrsync 用腳本批量上傳的就最好了~先謝過(guò)...)
letsencrypt 生成的證書(shū)有效期是 3 個(gè)月,所以,至少 3 個(gè)月內(nèi)需要更新一次證書(shū)。
certbot 提供了 renew 命令可以方便地更新證書(shū),使用 --dry-run 參數(shù)可以驗(yàn)證證書(shū)更新命令是否正確。
docker run -it --rm --name certbot -v /letsencrypt/etc/letsencrypt:/etc/letsencrypt -v /letsencrypt/lib/letsencrypt:/var/lib/letsencrypt -v /letsencrypt/challenge:/usr/share/nginx/html -v /var/log/letsencrypt:/var/log/letsencrypt deliverous/certbot renew --dry-run
同樣,看到 Congratulations 說(shuō)明證書(shū)更新成功了。
由于,本人每月都會(huì)發(fā)布文章并重啟服務(wù),就可以把證書(shū)更新一起交由 docker-compose 管理。(這里偷了個(gè)懶,增加了證書(shū)同應(yīng)用之間的耦合關(guān)系,還是建議大家證書(shū)是通過(guò)系統(tǒng)定時(shí)任務(wù)來(lái)更新,省得哪天忘更新證書(shū),證書(shū)就過(guò)期了)。
最后看一下最終的 docker-compose 配置文件和發(fā)布腳本。
# docker-compose.yml version: "2" services: node: build: . image: "blog:${TAG_NAME}" container_name: node # node service port export for test ports: - "8080:8080" volumes: - ./log/node:/var/log/node nginx: image: nginx:stable container_name: nginx depends_on: - node - letsencrypt volumes: - ./config/nginx:/etc/nginx/conf.d:ro - ./letsencrypt/etc/letsencrypt:/etc/letsencrypt - ./letsencrypt/lib/letsencrypt:/var/lib/letsencrypt - ./letsencrypt/challenge:/usr/share/nginx/html - ./log/nginx:/var/log/nginx volumes_from: - node:ro ports: - "80:80" - "443:443" restart: always letsencrypt: image: deliverous/certbot container_name: certbot volumes: - ./letsencrypt/etc/letsencrypt:/etc/letsencrypt - ./letsencrypt/lib/letsencrypt:/var/lib/letsencrypt - ./letsencrypt/challenge:/usr/share/nginx/html - ./log/letsencrypt:/var/log/letsencrypt command: renew
發(fā)布腳本主要用來(lái)更新代碼,以及獲取應(yīng)用版本號(hào)。
# deploy.sh # git operation git reset HEAD --hard git fetch git pull # TAG_NAME used to set docker image tag export TAG_NAME=`git tag -l | sort -r | head -n 1` # docker operation docker-compose down --volumes docker-compose up --build -d
其他配置可以上 github 查看。
一扯似乎又扯遠(yuǎn)了,歡迎提意見(jiàn)和建議,順便再問(wèn)一下有啥好的圖床推薦。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26788.html
摘要:于是,程序不再是原先單一的服務(wù),而是,變成了一系列密切相關(guān)的服務(wù)。需要注意的是,在模式下申請(qǐng)證書(shū),需要向證明服務(wù)器能被訪問(wèn)。 首先,祝各位新年快樂(lè),萬(wàn)事如意,雞年大吉。 這次要來(lái)說(shuō)說(shuō)一個(gè)和前端并不太相關(guān)的東西——docker compose,一個(gè)整合發(fā)布應(yīng)用的利器。 如果,你對(duì) docker 有一些耳聞,那么,你可能知道它是什么。 不過(guò),你不了解也沒(méi)有關(guān)系,在作者眼中,docker 就...
摘要:相關(guān)基于項(xiàng)目和項(xiàng)目,并遵循應(yīng)用的十二因素風(fēng)格。相關(guān)在設(shè)計(jì)上,項(xiàng)目盡量保持驅(qū)動(dòng)和模塊化,以便模塊支持不同的實(shí)現(xiàn)方案。相關(guān)不僅可以管理眾多虛擬機(jī),其計(jì)算服務(wù)還支持對(duì)的驅(qū)動(dòng),管理引擎的子項(xiàng)目還可用于通過(guò)模板管理容器?,F(xiàn)已整合公司所支持的項(xiàng)目。 整理自《Docker技術(shù)入門與實(shí)踐》 PaaS(Platform as a Service) PaaS 是希望提供一個(gè)統(tǒng)一的可供所有軟件直接運(yùn)行而無(wú)需...
摘要:如今前端工程越來(lái)越復(fù)雜,打造一個(gè)好用的工作流也顯得越來(lái)越重要。如果用戶啟動(dòng)容器時(shí)指定了運(yùn)行的命令,則會(huì)覆蓋掉指定的命令。個(gè)人感覺(jué)在項(xiàng)目多協(xié)作人數(shù)多的情況下,還是很方便的。 showImg(https://segmentfault.com/img/remote/1460000011553749?w=1100&h=225); 如今前端工程越來(lái)越復(fù)雜,打造一個(gè)好用的工作流也顯得越來(lái)越重要。本...
摘要:如今前端工程越來(lái)越復(fù)雜,打造一個(gè)好用的工作流也顯得越來(lái)越重要。如果用戶啟動(dòng)容器時(shí)指定了運(yùn)行的命令,則會(huì)覆蓋掉指定的命令。個(gè)人感覺(jué)在項(xiàng)目多協(xié)作人數(shù)多的情況下,還是很方便的。 showImg(https://segmentfault.com/img/remote/1460000011553749?w=1100&h=225); 如今前端工程越來(lái)越復(fù)雜,打造一個(gè)好用的工作流也顯得越來(lái)越重要。本...
摘要:全面支持后端服務(wù)的高可用調(diào)整優(yōu)化后端服務(wù)組件個(gè)中等級(jí)別以上的修復(fù)云幫社區(qū)版迎來(lái)了年月升級(jí)版本,我們優(yōu)化了云幫的安裝部署流程,全面支持后端服務(wù)的高可用,改進(jìn)了相關(guān)提示信息文案,完善了平臺(tái)日志模塊,升級(jí)了部分核心組件版本。 全面支持后端服務(wù)的高可用、調(diào)整優(yōu)化后端服務(wù)組件、4個(gè)中等級(jí)別以上的bug修復(fù)、云幫社區(qū)版迎來(lái)了2017年5月升級(jí)版本,我們優(yōu)化了云幫的安裝部署流程,全面支持后端服務(wù)的高...
閱讀 1314·2023-04-26 01:03
閱讀 1949·2021-11-23 09:51
閱讀 3313·2021-11-22 15:24
閱讀 2675·2021-09-22 15:18
閱讀 1023·2019-08-30 15:55
閱讀 3494·2019-08-30 15:54
閱讀 2264·2019-08-30 15:53
閱讀 2401·2019-08-30 15:44