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/- 運行容器時掛載宿主機的時區
-v /etc/localtime:/etc/localtime:ro
- 運行后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"
- 使用DockerFile,生產上,建議有一個base_image,里面直接定義好時區等信息,后面的
from base_img
構建官方鏡像,DockerFile待有時間單獨整理文章。
- 運行容器時掛載宿主機的時區
感受
- 咔咔咔一頓操作下來(DockerFile待深入),使用體驗並沒有預期的辣么爽。
- 環境一層套一層,碰到問題和疑惑也就多了一個層次,在細節效果配置時難免會碰到一些壁壘(比如nginx更復雜的配置),解決下來的時間成本不小。
- 所以,在公司或者個人開發上沒有docker剛需時,不用急着整治,但是整套環境打包鏡像,解決換環境又得重新安裝、環境配置的煩惱還是很爽的(比如mysql)。