docker4-nginx容器反向代理springboot


docker運行nginx容器

快速安裝運行

  • docker-hub文檔
    https://hub.docker.com/_/nginx
  • 拉取nginx1.6.0 docker pull nginx:1.16.0
  • 快速運行 docker run --name mynginx -d -p 80:80 ae893c58d83f
  • 外部訪問80端口驗證

關鍵文件目錄掛載

  • 進入容器內部查看配置目錄 docker exec -it mynginx /bin/bash
    默認的關鍵目錄位置:
    • 主(配置)目錄 /etc/nginx
    • 頁面目錄 /usr/share/nginx/html
    • 日志目錄 /var/log/nginx
  • 新運行容器,掛載上面目錄容器數據卷
    docker run --name mynginx -d -p 80:80 \
    -v /usr/local/dcv/nginx/html:/usr/share/nginx/html \
    -v /usr/local/dcv/nginx/conf:/etc/nginx \
    ae893c58d83f    
    
  • 運行失敗:

    本地fs有掛載目錄,但是 docker ps 沒有記錄。
    查看容器運行日志 docker logs mynginx :
    2019/09/05 03:03:46 [emerg] 1#1: open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
    nginx: [emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)
    容器內目錄原有的東西被外部fs同步覆蓋清空了..=_=

  • 解決:先從容器拷貝出需要的信息,然后子目錄掛載
    • 先簡單運行一個容器,從其中拷貝出配置文件和頁面的目錄文件
      //運行容器
      docker run --name mynginx -d -p 80:80 ae893c58d83f
      docker ps
      //本地fs建立相關目錄
      mkdir -p /usr/local/dcv/nginx/conf
      mkdir -p /usr/local/dcv/nginx/html
      mkdir -p /usr/local/dcv/nginx/log
      //從容器內copy文件和目錄到宿主機
      docker cp mynginx:/etc/nginx/nginx.conf /usr/local/dcv/nginx/conf
      docker cp mynginx:/etc/nginx/conf.d /usr/local/dcv/nginx/conf
      docker cp mynginx:/usr/share/nginx/html /usr/local/dcv/nginx
      docker cp mynginx:/var/log/nginx /usr/local/dcv/nginx/log
      //移動外部日志目錄
      cp -rf $(pwd)/log/nginx/* $(pwd)/log
      rm -rf $(pwd)/log/nginx
      
    • 重新掛載運行
      docker rm -f mynginx
      //新掛載運行一個容器
      docker run --name mynginx -d -p 80:80 \
      -v /usr/local/dcv/nginx/html:/usr/share/nginx/html \
      -v /usr/local/dcv/nginx/log:/var/log/nginx \
      -v /usr/local/dcv/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
      -v /usr/local/dcv/nginx/conf/conf.d:/etc/nginx/conf.d \
      ae893c58d83f
      //驗證
      docker ps
      
    • 宿主機修改index.html 外部訪問81驗證效果

nginx容器代理宿主機的springboot服務(即tomcat)

簡單的springboot包

  • 新建一個極簡的springboot應用,只有一個/hello接口返回JSON串,其他默認
    @RestController
    public class HellowCtrller {
    	@ResponseBody
    	@RequestMapping("/hello")
    	public String hello() {
    		return "hello docker @" + LocalDateTime.now();
    	}
    }
    
  • cmd到pom.xml目錄,mvn package 打jar包,上傳宿主機hello.jar
  • 宿主機運行hello.jar nohup java -jar hello-0.0.1-SNAPSHOT.jar &
  • 宿主機8080訪問驗證 curl http://localhost:8080/hello,OK

nginx代理配置

  • nginx容器內訪問宿主機ip的問題
    • 直接在nginx容器內配置localhost:8080是訪問不到外部tomcat的
    • 因為nginx容器有自己的ip,外部使用 docker inspect mynginx可以看到如下信息:
      "Gateway": "172.17.0.1",
      "GlobalIPv6Address": "",
      "GlobalIPv6PrefixLen": 0,
      "IPAddress": "172.17.0.2",
      "IPPrefixLen": 16,
      "IPv6Gateway": "",
      "MacAddress": "02:42:ac:11:00:02",
      "Networks": {
          "bridge": {
              "IPAMConfig": null,
              "Links": null,
              "Aliases": null,
              "NetworkID": "77b4c6b988b085d697f896ec4d19493294c0296dc99e20e6492b2cf79d7a6682",
              "EndpointID": "3933c9ccb7de29d19d82247bd1c0b4a5ed971e505fdce4455acb0df3d48a64b1",
              "Gateway": "172.17.0.1",
              "IPAddress": "172.17.0.2",
              "IPPrefixLen": 16,
              "IPv6Gateway": "",
              "GlobalIPv6Address": "",
              "GlobalIPv6PrefixLen": 0,
              "MacAddress": "02:42:ac:11:00:02",
              "DriverOpts": null
          }
      }
      
    • 其中的IPAddress就是容器自己的ip,Gateway則是外部docker安裝是產生的虛擬網關docker0,外部使用 ip addr可以看到。
    • 通過docker0的地址(即上面Gateway地址),容器內可以訪問宿主機
    • docker0網關的地址值在Linux上一般是固定的172.17.0.1,Mac系統則不同,移植時需要注意下。
  • 修改/usr/local/dcv/nginx/conf/conf.d下的 default.conf
    #后端負載集群
    upstream hello_server {
    	ip_hash; #session綁定節點
    	server 172.17.0.1:8080 weight=1;
    	#server 172.17.0.1:8081 weight=1;
    	#keepalive 100; #for長連接
    }
    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;
        }
    
        location /api/ {
            proxy_pass http://hello_server/;
            #for 后端獲取遠程客戶端真實ip
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #自定義添加header
            #proxy_set_header applicationto blog;
            #proxy_http_version 1.1;
    
            #for后端返回狀態攔截 >> 后端404自定義錯誤頁面
            #proxy_intercept_errors on;
        }
        #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;
        }
    }
    
  • nginx容器內驗證配置+重啟
    docker exec -t mynginx nginx -t
    docker exec -t mynginx nginx -s reload
    
  • 外部訪問驗證 curl http://localhost/api/hello

nginx容器代理springboot容器服務

制作springboot鏡像運行

  • 簡單的DockerFile文件(為方便名字就叫DockerFile)
    FROM java:8
    add hello-0.0.1-SNAPSHOT.jar app.jar
    expose 8080
    entrypoint ["java","-jar","/app.jar"]
    
  • build該文件為鏡像 hello_img docker build -t hello_img .
  • 運行兩個hello容器 端口分別8080和8081
    docker run -d --name hello1 -p 8080:8080 hello_img
    docker run -d --name hello2 -p 8081:8080 hello_img
    
  • 訪問兩個hello容器服務
    curl http://localhost:8080/hello
    curl http://localhost:8081/hello
    

nginx配置代理訪問hello容器

  • 運行nginx容器時使用 docker run 的--link參數傳遞hello容器ip
  • 重新運行mynginx容器
    //停掉
    docker stop mynginx
    docker rm mynginx
    //加--link運行
    docker run --name mynginx \
    --link=hello1:hello1ip --link=hello2:hello2ip \
    -v /usr/local/dcv/nginx/html:/usr/share/nginx/html \
    -v /usr/local/dcv/nginx/log:/var/log/nginx \
    -v /usr/local/dcv/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
    -v /usr/local/dcv/nginx/conf/conf.d:/etc/nginx/conf.d \
    -p 80:80 -d ae893c58d83f
    //查看
    docker ps
    
  • 修改 default.conf 中的后端負載集群配置
    upstream hello_server {
    	ip_hash; #session綁定節點
    	server hello1ip:8080 weight=1;
    	server hello2ip:8081 weight=1;
    	#keepalive 100; #for長連接
    }
    
  • 驗證重啟nginx
    docker exec -t mynginx nginx -t
    docker exec -t mynginx nginx -s reload
    
  • 外部訪問驗證 curl http://localhost/api/hello OK!

碰到的問題

外部訪問虛擬機的springboot8080端口

關掉防火牆:
直接關閉防火牆: systemctl stop firewalld.service
禁止firewall開機啟動: systemctl disable firewalld.service
重啟docker(不然后面可能有問題):systemctl restart docker

容器內無法使用ping

apt-get update
apt install iputils-ping #for ping
//apt install net-tools #for ifconfig

容器中nginx訪問日志問題

  • docker logs mynginx 命令 stdout 出來的時間不對
  • 原因:原生容器系統的時區為0時期,而國內系統為東八區,相差8小時
  • 其他容器估計也會有這個問題
  • 解決,關鍵要使容器時區和宿主機一致
    主參考:https://blog.lqdev.cn/2018/07/15/docker/docker-time-diff/
    1. 運行容器時掛載宿主機的時區 -v /etc/localtime:/etc/localtime:ro
    2. 運行后cp宿主機的時區到容器 docker cp /etc/localtime mynginx:/etc/localtime
      執行出錯=_=:具體原因還不知道,應該是容器內已經有的文件/夾不能通過docker cp覆蓋。。還是使用第一種掛載吧
      Error response from daemon: Error processing tar file(exit status 1): invalid symlink "/usr/share/zoneinfo/UCT" -> "../usr/share/zoneinfo/Asia/Shanghai"
    3. 使用DockerFile,生產上,建議有一個base_image,里面直接定義好時區等信息,后面的from base_img構建官方鏡像,DockerFile待有時間單獨整理文章。

感受

  • 咔咔咔一頓操作下來(DockerFile待深入),使用體驗並沒有預期的辣么爽。
  • 環境一層套一層,碰到問題和疑惑也就多了一個層次,在細節效果配置時難免會碰到一些壁壘(比如nginx更復雜的配置),解決下來的時間成本不小。
  • 所以,在公司或者個人開發上沒有docker剛需時,不用急着整治,但是整套環境打包鏡像,解決換環境又得重新安裝、環境配置的煩惱還是很爽的(比如mysql)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM