<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>

          一個網(wǎng)站的微服務(wù)架構(gòu)實戰(zhàn)docker和 docker-compose

          共 7560字,需瀏覽 16分鐘

           ·

          2020-10-07 20:50

          作者:KerryWu
          來源:SegmentFault 思否社區(qū)




          前言


          這是一次完整的項目實踐,Angular頁面+Springboot接口+MySQL都通過Dockerfile打包成docker鏡像,通過docker-compose做統(tǒng)一編排。目的是實現(xiàn)整個項目產(chǎn)品的輕量級和靈活性,在將各個模塊的鏡像都上傳公共鏡像倉庫后,任何人都可以通過 “docker-compose up -d” 一行命令,將整個項目的前端、后端、數(shù)據(jù)庫以及文件服務(wù)器等,運行在自己的服務(wù)器上。


          本項目是開發(fā)一個類似于segmentfault的文章共享社區(qū),我的設(shè)想是當(dāng)部署在個人服務(wù)器上時就是個人的文章庫,部署在項目組的服務(wù)器上就是項目內(nèi)部的文章庫,部署在公司的服務(wù)器上就是所有職工的文章共享社區(qū)。突出的特點就是,項目相關(guān)的所有應(yīng)用和文件資源都是靈活的,用戶可以傻瓜式地部署并使用,對宿主機(jī)沒有任何依賴。


          目前一共有三個docker鏡像,考慮以后打在一個鏡像中,但目前只能通過docker-compose來編排這三個鏡像。


          1. MySQL鏡像:以MySQL為基礎(chǔ),將項目所用到的數(shù)據(jù)庫、表結(jié)構(gòu)以及一些基礎(chǔ)表的數(shù)據(jù)庫,通過SQL腳本打包在鏡像中。用戶在啟動鏡像后就自動創(chuàng)建了項目所有的數(shù)據(jù)庫、表和基礎(chǔ)表數(shù)據(jù)。
          2. SpringBoot鏡像:后臺接口通過SpringBoot開發(fā),開發(fā)完成后直接可以打成鏡像,由于其內(nèi)置tomcat,可以直接運行,數(shù)據(jù)庫指向啟動好的MySQL容器中的數(shù)據(jù)庫。
          3. Nginx(Angular)鏡像:Nginx鏡像中打包了Angular項目的dist目錄資源,以及default.conf文件。主要的作用有:部署Angular項目頁面;掛載宿主機(jī)目錄作為文件服務(wù)器;以及反向代理SpringBoot接口,解決跨域問題等等。

          最后三個docker容器的編排通過docker-compose來實現(xiàn),三個容器之間的相互訪問都通過容器內(nèi)部的別名,避免了宿主機(jī)遷移時ip無法對應(yīng)的問題。為了方便開發(fā),順便配了個自動部署。




          MySQL鏡像


          初始化腳本


          在項目完成后,需要生成項目所需數(shù)據(jù)庫、表結(jié)構(gòu)以及基礎(chǔ)表數(shù)據(jù)的腳本,保證在運行該docker容器中,啟動MySQL數(shù)據(jù)庫時,自動構(gòu)建數(shù)據(jù)庫和表結(jié)構(gòu),并初始化基礎(chǔ)表數(shù)據(jù)。


          Navicat for MySQL的客戶端支持導(dǎo)出數(shù)據(jù)庫的表結(jié)構(gòu)和表數(shù)據(jù)的SQL腳本。
          如果沒有安裝Navicat,可以在連接上容器中開發(fā)用的MySQL數(shù)據(jù)庫,通過mysqldump 命令導(dǎo)出數(shù)據(jù)庫表結(jié)構(gòu)和數(shù)據(jù)的SQL腳本。下文中就是將數(shù)據(jù)庫的SQL腳本導(dǎo)出到宿主機(jī)的/bees/sql 目錄:


          docker?exec?-it??mysql?mysqldump?-uroot?-pPASSWORD?數(shù)據(jù)庫名稱?>?/bees/sql/數(shù)據(jù)庫名稱.sql


          以上只是導(dǎo)出 表結(jié)構(gòu)和表數(shù)據(jù)的腳本,還要在SQL腳本最上方加上 生成數(shù)據(jù)庫的SQL:


          drop?database?if?exists?數(shù)據(jù)庫名稱;
          create?database?數(shù)據(jù)庫名稱;
          use?數(shù)據(jù)庫名稱;


          通過以上兩個步驟,數(shù)據(jù)庫、表結(jié)構(gòu)和表數(shù)據(jù)三者的初始化SQL腳本就生成好了。


          Dockerfile構(gòu)建鏡像


          我們生成的SQL腳本叫 bees.sql,在MySQL官方鏡像中提供了容器啟動時自動執(zhí)行/docker-entrypoint-initdb.d文件夾下的腳本的功能(包括shell腳本和sql腳本),我們在后續(xù)生成鏡像的時候,將上述生成的SQL腳本COPY到MySQL的/docker-entrypoint-initdb.d目錄下就可以了。
          現(xiàn)在我們寫Dockerfile,很簡單:


          FROM?mysql

          MAINTAINER?kerry([email protected])

          COPY?bees.sql?/docker-entrypoint-initdb.d


          將 bees.sql 和 Dockerfile 兩個文件放在同一目錄,執(zhí)行構(gòu)建鏡像的命令就可以了:


          docker?build?-t?bees-mysql?.


          現(xiàn)在通過 docker images,就能看到本地的鏡像庫中就已經(jīng)新建了一個 bees-mysql的鏡像啦。




          SpringBoot鏡像


          springboot構(gòu)建鏡像的方式很多,有通過代碼生成鏡像的,也有通過jar包生成鏡像的。我不想對代碼有任何污染,就選擇后者,通過生成的jar包構(gòu)建鏡像。
          創(chuàng)建一個目錄,上傳已經(jīng)準(zhǔn)備好的springboot的jar包,這里名為bees-0.0.1-SNAPSHOT.jar,然后同樣編寫Dockerfile文件:


          FROM?java:8
          VOLUME?/tmp
          ADD?bees-0.0.1-SNAPSHOT.jar?/bees-springboot.jar
          EXPOSE?8010
          ENTRYPOINT?["java","-Djava.security.egd=file:/dev/./urandom","-jar","-Denv=DEV","/bees-springboot.jar"]


          將bees-0.0.1-SNAPSHOT.jar和Dockerfile放在同一目錄執(zhí)行命令開始構(gòu)建鏡像,同樣在本地鏡像庫中就生成了bees-springboot的鏡像:


          docker?build?-t?bees-springboot?.




          Nginx(Angular)鏡像


          Nginx的配置


          該鏡像主要在于nginx上conf.d/default.conf文件的配置,主要實現(xiàn)三個需求:


          1、Angualr部署
          Angular的部署很簡單,只要將Angular項目通過 ng build --prod 命令生成dist目錄,將dist目錄作為靜態(tài)資源文件放在服務(wù)器上訪問就行。我們這里就把dist目錄打包在nginx容器中,在default.conf上配置訪問。


          2、文件服務(wù)器
          項目為文章共享社區(qū),少不了的就是一個存儲文章的文件服務(wù)器,包括存儲一些圖片之類的靜態(tài)資源。需要在容器中創(chuàng)建一個文件目錄,通過default.conf上的配置將該目錄代理出來,可以直接訪問目錄中的文件。
          當(dāng)然為了不丟失,這些文件最好是保存在宿主機(jī)上,在啟動容器時可以將宿主機(jī)本地的目錄掛載到容器中的文件目錄。


          3、接口跨域問題
          在前后端分離開發(fā)的項目中,“跨域問題”是較為常見的,SpringBoot的容器和Angular所在的容器不在同一個ip和端口,我們同樣可以在default.conf上配置反向代理,將后臺接口代理成同一個ip和端口的地址。

          話不多說,結(jié)合上面三個問題,我們最終的default.conf為:


          server?{
          ????listen???????80;

          ????server_name??localhost;
          ????
          ????gzip?on;
          ????gzip_min_length??1k;
          ????gzip_buffers?????4?16k;
          ????gzip_comp_level?3;
          ????gzip_types???????text/plain?application/x-javascript?application/javascript?text/css?application/xml?text/javascript?application/x-httpd-php?image/jpeg?image/gif?image/png;
          ????gzip_vary?on;

          ????location?/?{
          ????????root???/usr/share/nginx/html;
          ????????index??index.html?index.htm;
          ????????try_files?$uri?$uri/?/index.html;
          ????}
          ????
          ????location?/api/?{
          ????????proxy_pass?http://beesSpringboot:8010/;
          ????}

          ????location?/file?{
          ????????alias?/home/file;
          ????????index??index.html?index.htm;
          ????}

          ????error_page???500?502?503?504??/50x.html;
          ????location?=?/50x.html?{
          ????????root???/usr/share/nginx/html;
          ????}
          }


          1. location / :代理的是Angular項目,dist目錄內(nèi)通過Dockerfile
            COPY在容器內(nèi)的/usr/share/nginx/html目錄;
          2. location /file :代理/home/file 目錄,作為文件服務(wù)器;
          3. location /api/ :是為了解決跨域而做的反向代理,為了脫離宿主機(jī)的限制,接口所在容器的ip通過別名beesSpringboot來代替。別名的設(shè)置是在docker-compose.yml中設(shè)置的,后續(xù)再講。
          4. 添加了gzip,針對前端較大資源文件下載速度的優(yōu)化



          Dockerfile構(gòu)建鏡像


          同樣創(chuàng)建一個目錄,包含Angualr的dist目錄、Dockerfile和nginx的default.conf文件,目錄結(jié)構(gòu)如下:


          [root@Kerry?angular]#?tree
          .
          ├──?dist
          │???└──?Bees
          │???????├──?0.cb202cb30edaa3c93602.js
          │???????├──?1.3ac3c111a5945a7fdac6.js
          │???????├──?2.99bfc194c4daea8390b3.js
          │???????├──?3.50547336e0234937eb51.js
          │???????├──?3rdpartylicenses.txt
          │???????├──?4.53141e3db614f9aa6fe0.js
          │???????├──?assets
          │???????│???└──?images
          │???????│???????├──?login_background.jpg
          │???????│???????└──?logo.png
          │???????├──?favicon.ico
          │???????├──?index.html
          │???????├──?login_background.7eaf4f9ce82855adb045.jpg
          │???????├──?main.894e80999bf907c5627b.js
          │???????├──?polyfills.6960d5ea49e64403a1af.js
          │???????├──?runtime.37fed2633286b6e47576.js
          │???????└──?styles.9e4729a9c6b60618a6c6.css
          ├──?Dockerfile
          └──?nginx
          ????└──?default.conf


          Dockerfile文件如下:

          FROM?nginx

          COPY?nginx/default.conf?/etc/nginx/conf.d/

          RUN?rm?-rf?/usr/share/nginx/html/*

          COPY?/dist/Bees?/usr/share/nginx/html

          CMD?["nginx",?"-g",?"daemon?off;"]


          以上,通過下列命令,構(gòu)建bees-nginx-angular的鏡像完成:


          `docker?build?-t?bees-nginx-angular?.




          docker-compose容器服務(wù)編排


          上述,我們已經(jīng)構(gòu)建了三個鏡像,相對應(yīng)的至少要啟動三個容器來完成項目的運行。那要執(zhí)行三個docker run?太麻煩了,而且這三個容器之間還需要相互通信,如果只使用docker來做的話,不光啟動容器的命令會很長,而且為了容器之間的通信,docker --link 都會十分復(fù)雜,這里我們需要一個服務(wù)編排。docker的編排名氣最大的當(dāng)然是kubernetes,但我的初衷是讓這個項目輕量級,不太希望用戶安裝偏重量級的kubernetes才能運行,而我暫時又沒能解決將三個鏡像構(gòu)建成一個鏡像的技術(shù)問題,就選擇了適中的一個產(chǎn)品--docker-compse。


          安裝docker-compose很簡單,這里就不贅言了。安裝完之后,隨便找個目錄,寫一個docker-compose.yml文件,然后在該文件所在地方執(zhí)行一行命令就能將三個容器啟動了:


          #啟動
          docker-compose?up?-d
          #關(guān)閉
          docker-compose?down


          這里直接上我寫的docker-compose.yml文件


          version:?"2"
          services:

          ?beesMysql:
          ??restart:?always
          ??image:?bees-mysql
          ??ports:
          ???-?3306:3306
          ??volumes:
          ???-?/bees/docker_volume/mysql/conf:/etc/mysql/conf.d
          ???-?/bees/docker_volume/mysql/logs:/logs
          ???-?/bees/docker_volume/mysql/data:/var/lib/mysql
          ??environment:
          ???MYSQL_ROOT_PASSWORD:?kerry

          ?beesSpringboot:
          ??restart:?always
          ??image:?bees-springboot
          ??ports:
          ???-?8010:8010
          ??depends_on:
          ???-?beesMysql

          ?beesNginxAngular:
          ??restart:?always
          ??image:?bees-nginx-angular
          ??ports:
          ???-?8000:80
          ??depends_on:
          ???-?beesSpringboot
          ??volumes:
          ???-?/bees/docker_volume/nginx/nginx.conf:/etc/nginx/nginx.conf
          ???-?/bees/docker_volume/nginx/conf.d:/etc/nginx/conf.d
          ???-?/bees/docker_volume/nginx/file:/home/file


          • image:鏡像名稱

          • ports:容器的端口和宿主機(jī)的端口的映射

          • services:文中三個service,在各自容器啟動后就會自動生成別名,例如:在springboot中訪問數(shù)據(jù)庫,只需要通過“beesMysql:3306”就能訪問。

          • depends_on:會設(shè)置被依賴的容器啟動之后,才會啟動自己。例如:mysql數(shù)據(jù)庫容器啟動后,再啟動springboot接口的容器。

          • volumes:掛載卷,一些需要長久保存的文件,可通過宿主機(jī)中的目錄,掛載到容器中,否則容器重啟后會丟失。例如:數(shù)據(jù)庫的數(shù)據(jù)文件;nginx的配置文件和文件服務(wù)器目錄。




          其他


          自動部署


          為了提高開發(fā)效率,簡單寫了一個自動部署的腳本,直接貼腳本了:


          #!/bin/bash

          v_springboot_jar=`find?/bees/devops/upload/?-name?"*.jar"`
          echo?"找到j(luò)ar:"$v_springboot_jar
          v_angular_zip=`find?/bees/devops/upload/?-name?"dist.zip"`
          echo?"找到dist:"$v_angular_zip

          cd?/bees/conf/
          docker-compose?down
          echo?"關(guān)閉容器"

          docker?rmi?-f?$(docker?images?|??grep?"bees-springboot"??|?awk?'{print?$1}')
          docker?rmi?-f?$(docker?images?|??grep?"bees-nginx-angular"??|?awk?'{print?$1}')
          echo?"刪除鏡像"

          cd?/bees/devops/dockerfiles/springboot/
          rm?-f?*.jar
          cp?$v_springboot_jar?./bees-0.0.1-SNAPSHOT.jar
          docker?build?-t?bees-springboot?.
          echo?"生成springboot鏡像"

          cd?/bees/devops/dockerfiles/angular/
          rm?-rf?dist/
          cp?$v_angular_zip?./dist.zip
          unzip?dist.zip
          rm?-f?dist.zip
          docker?build?-t?bees-nginx-angular?.
          echo?"生成angular鏡像"

          cd?/bees/conf/
          docker-compose?up?-d
          echo?"啟動容器"
          docker?ps?|grep?bees


          遇到的坑


          一開始在docker-compose.yml文件中寫services時,每個service不是駝峰式命名,而是下劃線連接,例如:bees_springboot、bees_mysql、bees_nginx_angular 。


          在springboot中訪問數(shù)據(jù)
          庫的別名可以,但是在nginx中,反向代理springboot接口地址時死活代理不了 bees_springboot的別名。能在bees_nginx_angular的容器中ping通bees_springboot,但是代理不了bees_springboot地址的接口,通過curl -v 查看原因,是丟失了host。


          最后發(fā)現(xiàn),nginx默認(rèn)request的header中包含“_”下劃線時,會自動忽略掉。我因此把docker-compose.yml中service名稱,從下劃線命名都改成了駝峰式。


          當(dāng)然也可以通過在nginx里的nginx.conf配置文件中的http部分中添加如下配置解決:


          underscores_in_headers?on;



          點擊左下角閱讀原文,到?SegmentFault 思否社區(qū)?和文章作者展開更多互動和交流。

          -?END -

          瀏覽 86
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  人妻无码喷水 | 蜜乳AV一区二区三区 | 国产香蕉一区二区三区 | 一级色色| 精品精品国内视频 |