docker下nginx反向代理和負載均衡配置

鏡像安裝

能夠經過如下命令拉取nginx和tomcat鏡像做爲測試php

[root@docker /]# docker pull nginx
[root@docker /]# docker pull tomcat

nginx

  1. 鏡像下載完後,執行如下命令啓動nginx
[root@docker /]# docker run --name=my_nginx -p 8000:80 -d nginx

--name: 爲nginx容器指定一個名稱方便管理
-p: 將nginx內部80端口代理到宿主機8000端口,能夠經過宿主機:8000訪問nginx 80端口
-d: 後臺運行html

  1. 能夠經過docker ps 命令查看容器運行狀況
[root@docker /]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                            NAMES
1833fcff605b        nginx                 "nginx -g 'daemon off"   2 minutes ago       Up 2 minutes        0.0.0.0:8000->80/tcp             my_nginx
  1. 瀏覽器訪問http://192.168.43.32:8000/查看是否可以訪問,或者使用curl命令(推薦)
[root@docker /]# curl http://192.168.43.32:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
....

nginx配置文件

進入nginx容器後臺java

[root@docker /]# docker exec -it my_nginx bash
root@1833fcff605b:/# cd /etc/nginx/
root@1833fcff605b:/etc/nginx# ls -l
total 36
drwxr-xr-x. 2 root root   26 Dec 26 18:16 conf.d
-rw-r--r--. 1 root root 1007 Dec 26 11:11 fastcgi_params
-rw-r--r--. 1 root root 2837 Dec 26 11:11 koi-utf
-rw-r--r--. 1 root root 2223 Dec 26 11:11 koi-win
-rw-r--r--. 1 root root 5170 Dec 26 11:11 mime.types
lrwxrwxrwx. 1 root root   22 Dec 26 11:11 modules -> /usr/lib/nginx/modules
-rw-r--r--. 1 root root  643 Dec 26 11:11 nginx.conf
-rw-r--r--. 1 root root  636 Dec 26 11:11 scgi_params
-rw-r--r--. 1 root root  664 Dec 26 11:11 uwsgi_params
-rw-r--r--. 1 root root 3610 Dec 26 11:11 win-utf

nginx.conf是nginx主要配置文件,能夠經過more命令查看nginx.conf(容器默認不安裝vi工具)node

root@1833fcff605b:/etc/nginx# more 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;

    include /etc/nginx/conf.d/*.conf;
}

注意到最後一行配置
include /etc/nginx/conf.d/*.conf;
include能夠將其餘配置文件導入,進入/etc/nginx/conf.d/目錄下查看nginx

root@1833fcff605b:/etc/nginx# cd /etc/nginx/conf.d/
root@1833fcff605b:/etc/nginx/conf.d# ls
default.conf

default.confweb

root@1833fcff605b:/etc/nginx/conf.d# more default.conf
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

#表示註釋能夠忽略
server:表明虛擬服務器,下面會解釋什麼是虛擬服務器
server_name:服務器名稱
location:訪問路徑匹配規則,這也是nginx最靈活的地方,可使用正則表達式
解釋下什麼是虛擬服務器
若是給nginx服務器在dns上配置兩個域名
domain1.nginx.com
domain2.nginx.com
用戶訪問這兩個域名,你可能但願他們訪問同一個後臺服務,也可能但願訪問不一樣的後臺服務
那麼在nginx裏就能夠配置兩個虛擬服務器也就是兩個server節點正則表達式

server {
    listen       80;
    server_name  domain1.nginx.com;
    ...
}
server {
    listen       80;
    server_name  domain2.nginx.com;
    ...
}

兩個虛擬服務器監聽同一個端口80.nginx能夠根據用戶訪問的host(http頭部host)字段代理到不一樣服務器上docker

location->root:靜態資源目錄,web靜態資源如圖片,js,html可經過該方式存放
location->index:如用戶未指定請求資源名稱,默認訪問index指定的文件,如訪問http://host:port/html/則默認訪問http://host:port/html/index.htmlshell

測試場景

咱們假設有如下三個場景瀏覽器

  1. 場景1

宿主機有個目錄存儲靜態資源,須要經過nginx代理出去,用戶訪問http://host:port/resource/xxxx訪問

  1. 場景2

tomcat服務器(docker容器)上運行一個web程序,須要經過nginx代理出去,web程序context root爲WebTestApp

  1. 場景3

該web程序運行在兩個tomcat容器中,須要經過nginx作負載均衡

nginx配置文件掛載

docker容器每次重啓都是一個新的環境,也就是說在docker容器內作的任何修改都將被還原,但nginx的配置文件是在docker容器內,咱們若是直接進行修改每次重啓後都會被還原,這並非咱們所但願的,因此首先須要將配置文件從docker容器中"搬到"宿主機上,這裏會經過docker的卷(volume)實現。
volume能夠將本地文件掛載到docker容器內,這樣容器重啓後信息不會丟失
對於nginx,能夠將nginx.conf文件和conf.d目錄從容器內部"搬"出來
在本地建立nginx.conf文件和conf.d目錄

[root@docker /]# mkdir -p /u01/nginx
[root@docker /]# mkdir -p /u01/nginx/conf.d
[root@docker /]# touch /u01/nginx/nginx.conf
[root@docker /]# touch /u01/nginx/conf.d/default.conf

nginx.conf文件和default.conf內容能夠直接從容器內部複製

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;

    include /etc/nginx/conf.d/*.conf;
}

default.conf

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

從新啓動nginx

[root@docker /]# docker stop my_nginx
my_nginx
[root@docker /]# docker rm my_nginx
my_nginx
[root@docker nginx]# docker run --name=my_nginx -v /u01/nginx/nginx.conf:/etc/nginx/nginx.conf -v /u01/nginx/conf.d:/etc/nginx/conf.d -p 8000:80 -d nginx
6efe91858f071a50197da104cdccf8500234f1bf6d0f4f56d3dc5de02261272c
[root@docker /]# curl http://192.168.43.32:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
....

注意到執行了一個 docker rm my_nginx 命令,這是由於容器每次啓動須要指定不一樣的名字,一個名字不能使用屢次,能夠經過 docker ps -a查看全部容器,包括未運行的容器。rm命令能夠刪除指定容器
下面正式配置上面三個場景

場景1-靜態資源代理

在u01目錄下建立目錄resource,並上傳靜態資源

[root@docker resource]# pwd
/u01/resource
[root@docker resource]# ll
total 164
-rw-r--r--. 1 root root 147291 Oct  8  2015 angular.min.js
-rw-r--r--. 1 root root  17189 Nov  3 10:32 docker.jpg
[root@docker resource]#

修改/u01/nginx/conf.d/default.conf文件

default.conf

server {
    listen       80;
    server_name localhost;
    location /resource {
        root   /u01;
        index  index.html index.htm;
    }
}

ps:root是/u01不是/u01/resource。若是root配置成/u01/resource/則nginx會去/u01/resource/resource目錄下尋找文件
從新啓動nginx容器,將resource目錄掛載到容器內部

[root@docker u01]# docker stop my_nginx
my_nginx
[root@docker u01]# docker rm my_nginx
my_nginx
[root@docker u01]# docker run --name=my_nginx -v /u01/nginx/nginx.conf:/etc/nginx/nginx.conf -v /u01/nginx/conf.d:/etc/nginx/conf.d -v /u01/resource:/u01/resource -p 8000:80 -d nginx

訪問
http://192.168.43.32:8000/resource/docker.jpg
http://192.168.43.32:8000/resource/angular.min.js
測試配置是否成功(將上面ip替換成宿主機ip)

場景2-tomcat代理

準備一個servet做爲測試

package com.df.demo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.*;
import javax.servlet.http.*;

public class WebTestService extends HttpServlet {
    private static final String CONTENT_TYPE = "text/html; charset=UTF-8";

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                                                           IOException {
        response.setContentType(CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        out.print("hello docker tomcat");
        out.close();
    }
}

打成war包,包名爲WebTestApp.war,在u01上建立webapps目錄並上傳war包

[root@docker webapps]# pwd
/u01/webapps
[root@docker webapps]# ls
WebTestApp.war

啓動tomcat容器,並將/u01/webapps目錄掛載到tomcat的/usr/local/tomcat/webapps目錄下

[root@docker ~]# docker run --name=my_tomcat1 -v /u01/webapps:/usr/local/tomcat/webapps -p 8001:8080 -d tomcat
[root@docker ~]# curl http://localhost:8001/WebTestApp
hello docker tomcat

程序已經成功部署到tomcat上
修改/u01/nginx/conf.d/default.conf文件

default.conf

server {
    listen       80;
    server_name localhost;
    location / {
        proxy_pass   http://tomcat_server;
    }
}

修改/u01/nginx/nginx.conf在http配置節點中增長如下配置

upstream tomcat_server {
      server t1:8080;
    }

upstream 能夠定義一組服務器
proxy_pass 設置代理的服務器,格式爲http://upstream_name

重啓nginx容器,這裏咱們須要使用一個新的docker參數--link

[root@docker u01]# docker run --name=my_nginx1 --link=my_tomcat1:t1 -v /u01/nginx/nginx.conf:/etc/nginx/nginx.conf -v /u01/nginx/conf.d:/etc/nginx/conf.d -p 8000:80 -d nginx
[root@docker ~]# curl http://192.168.43.32:8000/WebTestApp
hello docker tomcat

ps:這裏換了一個名字my_nginx1,用原來的名字my_nginx沒法啓動容器,會報如下錯誤

2018/01/27 08:40:44 [emerg] 1#1: host not found in upstream "t1:8080" in /etc/nginx/nginx.conf:30
nginx: [emerg] host not found in upstream "t1:8080" in /etc/nginx/nginx.conf:30

t1沒法找到,但若是不使用--name指定名稱可正常啓動,緣由未知。
link參數能夠在兩個容器之間創建網絡鏈接,格式爲--link=my_tomcat1:t1 my_tomcat1爲容器名稱,t1爲取的別名
可登陸nginx容器查看/etc/hosts文件,docker會將t1加入到hosts文件中

[root@docker ~]# docker exec -it my_nginx1 bash
root@fa5f782b9448:/# more /etc/hosts
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
ff00::0    ip6-mcastprefix
ff02::1    ip6-allnodes
ff02::2    ip6-allrouters
172.17.0.5    t1 1f9b1d432ab0 my_tomcat1
172.17.0.6    fa5f782b9448

場景3-tomcat負載均衡

  1. 修改/u01/nginx/nginx.conf在場景2的基礎上增長新的服務器
upstream tomcat_server {
      server t1:8080;
      server t2:8080;
    }
  1. 在啓動一個tomcat容器my_tomcat2
[root@docker ~]# docker run --name=my_tomcat2 -v /u01/webapps:/usr/local/tomcat/webapps -d tomcat
  1. 重啓nginx
[root@docker /]# docker stop my_nginx1
[root@docker /]# dcoker rm my_nginx1
[root@docker /]# docker run --name=my_nginx1 --link=my_tomcat1:t1 --link=my_tomcat2:t2 -v /u01/nginx/nginx.conf:/etc/nginx/nginx.conf -v /u01/nginx/conf.d:/etc/nginx/conf.d -p 8000:80 -d nginx
[root@docker ~]# curl http://192.168.43.32:8000/WebTestApp
hello docker tomcat
  1. 能夠分別登陸兩個tomcat容器查看access.log能夠查看結果,nginx在兩臺服務器之間作輪詢.輪詢是nginx默認的負載均衡方式。
相關文章
相關標籤/搜索