Docker 自動化 Nginx 反向代理

自動化 Nginx 反向代理 Docker

標籤(空格分隔): Docker Nginx Automatedjavascript


本文做者是 jwilder,原文地址是 Automated Nginx Reverse Proxy for Dockercss

爲何 Docker 要使用反向代理

Docker 容器被分配隨機 IP 和端口,這使得從客戶端角度來尋址它們是很是複雜的。默認,IP 和端口是專用於主機的,而且不能被外部訪問除非它們被綁定到主機上。html

綁定容器到主機端口能夠防止多個容器在同一個主機上運行。好比,在同一時間僅僅只有一個容器能夠被綁定到 80 端口。這也使得新版本的容器無停機的推出複雜化了,由於老版本必須在新版本啓動以前先中止。java

一個反向代理能夠幫助處理這些問題,同時經過減輕零停機部署的困難來提高可用性。nginx

生成反向代理配置文件

當一個容器被啓動和中止的時候,設置一個反向代理配置多是複雜的。一般的配置須要手動更新,這容易出錯而且費時。git

幸運的是,Docker 提供了一個遠程 API 來 inspect containers 和訪問他們的 IP,端口和其餘配置元數據。另外,它也提供一個實時事件 API能夠被用於通知何時容器被啓動和中止。這些 API 能夠被用於自動地生成一個反向代理配置。github

docker-gen 是一個使用這些 API 的小工具,並導出容器的元數據到模板中。模板被渲染以及一個可選的通知命令能夠被運行來重起服務。golang

使用 docker-gen,咱們能夠自動的生成 Nginx 的配置並重載 Nginx當它們改變的時候。一樣的方法可被用於 Docker 日誌管理web

Nginx 反向代理 Docker

這個例子 Nginx 模板能夠被用於生成一個 Docker 容器使用虛擬主機路由的反向代理配置文件。這個模板是使用 golang text/template package 實現的。它使用一個通用的 groupBy 模板函數經過它們的 VIRTUAL_HOST 環境變量來分組運行的容器。這簡化了遍歷容器來生成一個負載均衡後端以及使得零停機部署可行。docker

{{ range $host, $containers := groupBy $ "Env.VIRTUAL_HOST" }}
upstream {{ $host }} {

{{ range $index, $value := $containers }}
    {{ with $address := index $value.Addresses 0 }}
    server {{ $address.IP }}:{{ $address.Port }};
    {{ end }}
{{ end }}

}

server {
    #ssl_certificate /etc/nginx/certs/demo.pem;
    #ssl_certificate_key /etc/nginx/certs/demo.key;

    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    server_name {{ $host }};

    location / {
        proxy_pass http://{{ $host }};
        include /etc/nginx/proxy_params;
    }
}
{{ end }}

這個模板可使用 docker-gen 來運行:

docker-gen -only-exposed -watch -notify "/etc/init.d/nginx reload" templates/nginx.tmpl /etc/nginx/sites-enabled/default
  • -only-exposed - 僅僅使用容器已經暴露的端口。
  • -watch - 啓動以後,監控 docker 容器事件和從新生成模板。
  • -notify "/etc/init.d/nginx reload" - 在模板生成後重載 nginx 配置。
  • templates/nginx.tmpl - nginx 模板。
  • /etc/nginx/sites-enabled/default - 目標文件。

這是兩個容器配置了 VIRTUAL_HOST=demo1.localhostVIRTUAL_HOST=demo2.localhost 的渲染模板。

upstream demo1.localhost {
    server 172.17.0.4:5000;
    server 172.17.0.3:5000;
}

server {
    #ssl_certificate /etc/nginx/certs/demo.pem;
    #ssl_certificate_key /etc/nginx/certs/demo.key;

    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    server_name demo1.localhost;

    location / {
        proxy_pass http://demo.localhost;
        include /etc/nginx/proxy_params;
    }
}

upstream demo2.localhost {
    server 172.17.0.5:5000;
}

server {
    #ssl_certificate /etc/nginx/certs/demo.pem;
    #ssl_certificate_key /etc/nginx/certs/demo.key;

    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    server_name demo2.localhost;

    location / {
        proxy_pass http://demo2.localhost;
        include /etc/nginx/proxy_params;
    }
}

試驗

我使用這個設置建立了一個可信任的構建來使得它很是容易試驗。

運行 nginx-proxy 容器:

$ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock -t jwilder/nginx-proxy

使用一個 VIRTUAL_HOST 環境變量啓動你的容器:

docker run -e VIRTUAL_HOST=foo.bar.com -t ...

總結

爲 docker 容器生成 nginx 反向代理配置能夠經過使用 Docker APIs 和一些基礎的模板自動化,這能夠簡化部署同時提高可用性。

雖然這很是適用於單臺主機上運行的容器,爲遠程主機生成配置須要自動發現。看一下 Docker 自動發現 對這個問題的解決。

更新:這有一些相似觀點和變種的其餘文章值得一看:

相關文章
相關標籤/搜索