映象安裝
可以通過以下命令拉取nginx和tomcat映象作為測試
[root@docker /]# docker pull nginx
[root@docker /]# docker pull tomcat
nginx
- 映象下載完後,執行以下命令啟動nginx
[root@docker /]# docker run --name=my_nginx -p 8000:80 -d nginx
–name: 為nginx容器指定一個名稱方便管理
-p: 將nginx內部80埠代理到宿主機8000埠,可以通過宿主機:8000
訪問nginx 80埠
-d: 後臺執行
- 可以通過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
- 瀏覽器訪問
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容器後臺
[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工具)
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/
目錄下檢視
root@1833fcff605b:/etc/nginx# cd /etc/nginx/conf.d/
root@1833fcff605b:/etc/nginx/conf.d# ls
default.conf
default.conf
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)欄位代理到不同伺服器上
location->root:靜態資源目錄,web靜態資源如圖片,js,html可通過該方式存放
location->index:如使用者未指定請求資源名稱,預設訪問index指定的檔案,如訪問http://host:port/html/
則預設訪問http://host:port/html/index.html
測試場景
我們假設有以下三個場景
- 場景1
宿主機有個目錄儲存靜態資源,需要通過nginx代理出去,使用者訪問http://host:port/resource/xxxx
訪問
- 場景2
tomcat伺服器(docker容器)上執行一個web程式,需要通過nginx代理出去,web程式context root為WebTestApp
- 場景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負載均衡
- 修改/u01/nginx/nginx.conf在場景2的基礎上增加新的伺服器
upstream tomcat_server {
server t1:8080;
server t2:8080;
}
- 在啟動一個tomcat容器my_tomcat2
[root@docker ~]# docker run --name=my_tomcat2 -v /u01/webapps:/usr/local/tomcat/webapps -d tomcat
- 重啟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
- 可以分別登入兩個tomcat容器檢視access.log可以檢視結果,nginx在兩臺伺服器之間做輪詢.輪詢是nginx預設的負載均衡方式。