2017/02/27

Reverse Proxy For Docker

前言

現在很流行用 docker 處理一些服務,以我這行來講用來處理 LAMP 或者是 LNMP 最常見,也可能是產生個 gitlab 之類的,docker 最大的優點是服務都跑在 container,安裝快啟動也快,要幾個有幾個,寫好 config 像是 Dockerfile 之類的設定還可以一個指令搞定,讓你的電腦可以保持很乾淨,網站使用 80 port 當作預設的入口,但每個 server port 都是唯一的,所以假設你有很多網站服務,可能會指派很多不同的 port,像是 localhost:66666 或者是 localhost:66667,但有些測試你可能想要盡可能逼真,希望是用網址來跑服務的話,我們可以在 80 port 假一個反向的 proxy server,讓你可以將 domain 指定到帶 port 的 IP,下面會示範 nginx 以及 apache 的設定方式

Docker

我測試的環境是 Windows,我先使用 Vagrant 安裝一個 ubuntu 16 的 VM,IP 為 10.10.10.22,之後將會在這個 VM 裡面跑 nginx 以及 apache servie,還有 docker

我 container 使用的 image 是 novice/lnmp,我先啟動兩個 web service 服務

$ sudo docker run -itd --name web1 -p 33333:80 novice/lnmp
$ sudo docker run -itd --name web2 -p 33334:80 novice/lnmp

我將 33333 port 給 nginx 這個 web service 使用,33334 給 apache 使用,然後我們將 Windows 的 hosts 設定一下

10.10.10.22 docker.web1
10.10.10.22 docker.web2

接著我進到 apache container 的 /var/www 目錄,加上一個 hello.php

<?php

echo 'hello I am web1';

同樣在 nginx 的 container /var/www 加入 hello.php。

<?php

echo 'hello I am web2';

在網址輸入 http://docker.web1:33333/hello.php 以及 http://docker.web2:33334/hello.php 各別會看到 hello I am web1 以及 hello I am web2,不過其實目前兩個網址互換得到的結果也會一樣,因為現在主要是因為不同的 port 帶出不同的 web service,而我們要做的事情就是把 port 拿掉以後還會成立

nginx

先在這個 VM 安裝 nginx。

$ sudo apt-get install nginx

安裝好之後,我們在 /etc/nginx/sites-available的目錄建立一個 proxy.conf內容如下

server {
    listen 80;
    sendfile off;
    server_name docker.web1;

    location / {
        proxy_pass http://127.0.0.1:33333;
        proxy_redirect     off;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

server {
    listen 80;
    sendfile off;
    server_name docker.web2;

    location / {
        proxy_pass http://127.0.0.1:33334;
        proxy_redirect     off;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

接著設定 config,然後將服務重啟

$ sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
$ sudo service nginx restart

此時如果你將 port 拿掉還是可以看到正確結果的話表示成功了,說明一下 sendfile off 主要是因為我使用 VM,這個不關的話會一直看到 cache,如果你是直接在 Linux 環境的話應該是不用特別設定

Apache

首先來安裝 apache,記得先將 nginx 關掉,並且確認兩個 proxy 必要的 module 有開

$ sudo service nginx stop
$ sudo apt-get install apache2
$ sudo a2enmod proxy
$ sudo a2enmod proxy_http

接著在 /etc/apache2/sites-available加入 proxy.conf,內容如下

<VirtualHost *:80>
    ServerName docker.web1
    ProxyPass / http://127.0.0.1:33334/
    ProxyPassReverse  / http://127.0.0.1:33334/
</VirtualHost>

<VirtualHost *:80>
    ServerName docker.web2
    ProxyPass / http://127.0.0.1:33333/
    ProxyPassReverse  / http://127.0.0.1:33333/
</VirtualHost>

接著我們製作 link,以及重起 apache

$ sudo a2ensite proxy.conf
$ sudo service apache2 restart

如果那兩個網址重整以後一樣可以看到對應的文字,表示 apache reserse proxy 也成功了