借助docker展現(xiàn)的nginx反向代理實(shí)例

概述

這節(jié)其實(shí)是上一篇nginx教程的補(bǔ)充,因?yàn)橛信笥芽戳酥髮τ诜聪虼砟菈K還有點(diǎn)疑問.所以這邊就舉一個簡單的例子(負(fù)載均衡).順便加上了一些docker的知識。所以廢話不說,進(jìn)入正題吧~

nginx反向代理

上一篇文章提到了反向代理的概念.概念其實(shí)很簡單,但是實(shí)際上有什么應(yīng)用呢?
有個最簡單也是很實(shí)用的例子,也就是負(fù)載均衡.作為反向代理的nginx在收到請求后按照一定規(guī)則再分發(fā)給下游的服務(wù)器.在這里對服務(wù)端而言客戶端是明確的,并且通常配置的時候會帶上realip.但是對于客戶端來講卻不知道請求最后落到了哪臺機(jī)器,這就是一個常見的反向代理的場景.這里并沒有其他可以補(bǔ)充的知識,在nginx的官網(wǎng)上都是有相關(guān)介紹的.
這就著重以一個例子來實(shí)現(xiàn).

這邊會借助docker來實(shí)現(xiàn)這個例子.
最簡單的一個例子就是兩個服務(wù)容器一個nginx容器.
nginx容器就是直接使用官方鏡像即可.

首先是server的代碼,go語言編寫

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        log.Println(r)
        hostName, _ := os.Hostname()
        w.Write([]byte(fmt.Sprintf("server:%s\n", hostName)))
        return
    })

    log.Println("start...")

    log.Panic(http.ListenAndServe(":8081", nil))
}

本身沒什么難度,主要是會輸出自己的hostname,這個在后面幫助我們區(qū)分實(shí)際訪問的服務(wù)器.

然后go build 編譯即可,根據(jù)自己的實(shí)際需求選擇編譯條件.這里我提供了現(xiàn)成的docker鏡像,地址為(https://cloud.docker.com/u/evanshao/repository/docker/evanshao/lbserver),

就不多贅述了.
然后是Dockerfile

FROM debian
MAINTAINER evan
COPY server /
ENTRYPOINT ["./server"]

這個也很簡單,就是借助debian基礎(chǔ)鏡像運(yùn)行編譯好的server.

然后是nginx配置(已經(jīng)提供了鏡像,地址是:https://cloud.docker.com/u/evanshao/repository/docker/evanshao/lbnginx).

這里可以參考上一篇文章的基礎(chǔ)配置:

#user nobody;
worker_processes 4; # 按照機(jī)器情況定

events {
    worker_connections 10240; # 按照機(jī)器情況定
}

http{
    include  mime.types;
    default_type  application/json;  # 按照自己服務(wù)設(shè)置
    error_page 500 502 503 504 /50x.html;
    error_page 404 /404.html; # 這個自己寫了放到html目錄下,不然應(yīng)該是nginx代碼里寫死的
     resolver 114.114.114.114;
    # 定義日志格式  這個別名是main
    log_format main '$remote_addr - $remote_user [$time_local] "$request"  $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';

  sendfile on;
 keepalive_timeout 30;

 include sites/*.http.conf;  # 具體的server放在這里

}

重點(diǎn)是sites下需要兩個新建的配置文件,
一個是ups.http.upstream:

upstream test_server{
    server serverA:8081;
    server serverB:8081;
}

這里其實(shí)是有兩個注意點(diǎn)的,一個是serverA 這個是配合后面的dockerDNS使用的,還有個自然是端口號,和server程序監(jiān)聽的端口號一致.

另外一個文件是 ups.http.conf,這里在開頭引用了upsream文件,并利用proxy_pass實(shí)現(xiàn)了轉(zhuǎn)發(fā).

include sites/ups.http.upstream;
server{
    listen 80 default_server;
    server_name localhost;
    access_log logs/ups.log main;
    
    location /{
        set $upstream_host $host;
        proxy_pass http://test_server;
        
    }
}

這邊是Dockerfile,myconf下就是上面的文件nginx.conf以及sites文件夾,sites里是其他兩個文件.另外還創(chuàng)建了一個空的logs文件夾

FROM nginx
MAINTAINER evan
COPY myconf/  /etc/nginx
EXPOSE 80
ENTRYPOINT ["nginx","-g","daemon off;"]

到這里實(shí)驗(yàn)環(huán)境就準(zhǔn)備好了,下面其實(shí)就是docker部分了,時間有限,這里僅僅提下使用方法.如果docker沒有安裝的話可以參考官方文檔進(jìn)行操作,后面有機(jī)會我也會開始寫一些docker的簡單教程~

上文提到的dockerDNS其實(shí)是docker提供的一種容器間通信的方法.具體的就不贅述了,如果有興趣的話可以自行搜索或者等我的blog哦.
首先我們要創(chuàng)建自己的docker子網(wǎng)

docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net

這里相當(dāng)于創(chuàng)建了一個局域網(wǎng),網(wǎng)段是172.22.16.然后在運(yùn)行server和nginx容器的時候我會把他們都指定到這個網(wǎng)段,這樣才能保證局域網(wǎng)內(nèi)各容器的網(wǎng)絡(luò)通信.
接下來首先啟動兩臺server容器

docker run -itd --rm --name serverA --hostname serverA --network=my_net evanshao/lbserver
docker run -itd --rm --name serverB --hostname serverB --network=my_net evanshao/lbserver

這里用--hostname 指定機(jī)器的host配合server的取值,--name相當(dāng)于指定局域網(wǎng)內(nèi)的通信域名,這里需要注意的是--name 指定的才是我們訪問的域名,這里我順手寫成和hostname一樣的了,不要混淆.

然后我們需要啟動nginx

docker run -itd --rm --name lbnginx -p 80:80 --network=my_net evanshao/lbnginx

這時候?qū)嶒?yàn)環(huán)境就已經(jīng)搭建完成了,我們通過瀏覽器訪問http://192.168.31.147/test就可以看到效果了:

lbserverA.png

刷新就變成

lbserverB.png

這邊配置默認(rèn)應(yīng)該是輪詢,當(dāng)你停掉一個容器的時候就會只訪問到活著的那臺機(jī)器了.
這里如果沒時間自己操作的話,直接按照我上面的三條docker run命令執(zhí)行即可.
后面可以慢慢還原.

這里寫的有些粗略了,因?yàn)樯弦黄恼乱呀?jīng)有提到一些nginx關(guān)鍵字的用法,官方也寫得很詳細(xì)了.主要還是展示下如果通過docker展現(xiàn)這一場景,后續(xù)我也會慢慢補(bǔ)充一些docker的知識,希望到時候能對你們有所幫助.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容