<-
Apache > HTTP Server > 文件 > 版本 2.4 > 虛擬主機

虛擬主機範例

可用的語言:  en  |  fr  |  ja  |  ko  |  tr 

這份文件試圖解答設定 虛擬主機 時常見的問題。這些情境都是透過 基於名稱基於 IP 虛擬主機,於單一伺服器上執行多個網站。

Support Apache!

另請參閱

top

在單一 IP 位址上執行多個基於名稱的網站。

你的伺服器有多個解析到單一位址之主機名稱,且你希望對 www.example.comwww.example.org 做出不同的回應方式。

注意

在 Apache 伺服器上建立虛擬主機設定並不會神奇地為這些主機名稱建立 DNS 條目。你必須在 DNS 中有這些名稱解析到你的 IP 位址,否則沒有人能看到你的網站。你可以將條目放在你的 hosts 檔案中以進行本機測試,但這只有擁有那些 hosts 條目的機器才能執行。

# Ensure that Apache listens on port 80
Listen 80
<VirtualHost *:80>
    DocumentRoot "/www/example1"
    ServerName www.example.com

    # Other directives here
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot "/www/example2"
    ServerName www.example.org

    # Other directives here
</VirtualHost>

星號比對所有位址,因此主伺服器不會處理任何要求。由於載有 ServerName www.example.com 的虛擬主機在設定檔中的順序最優先,因此可視為預設伺服器。這代表如果接獲的請求未比對任一個指定的 ServerName 指令,就會由這個第一個 <VirtualHost> 處理。

上述設定是您在幾乎所有基於名稱的虛擬主機狀況下會想要使用的設定。事實上,這個設定唯一無法處理的狀況,就是根據不同的 IP 位址或埠提供不同內容時。

注意

您可以在系統上用特定的 IP 位址取代 *。此虛擬主機將只用於與指定的 IP 位址建立連線時接收到的 HTTP 請求。

但是,如果系統上的 IP 位址無法預測(例如向 ISP 取得動態 IP 位址且正在使用某種動態 DNS 解決方案時),使用 * 也額外有用。由於 * 比對任何 IP 位址,因此這個設定在您的 IP 位址變更時不需更動就能運作。

top

多個 IP 位址上的基於名稱的主機。

注意

在此討論的任何技術都可以延伸到任何數量的 IP 位址。

伺服器有兩個 IP 位址。我們將在其中一個(172.20.30.40)提供「主」伺服器,server.example.com,且將在另一個(172.20.30.50)提供兩個或更多個虛擬主機。

Listen 80

# This is the "main" server running on 172.20.30.40
ServerName server.example.com
DocumentRoot "/www/mainserver"

<VirtualHost 172.20.30.50>
    DocumentRoot "/www/example1"
    ServerName www.example.com

    # Other directives here ...
</VirtualHost>

<VirtualHost 172.20.30.50>
    DocumentRoot "/www/example2"
    ServerName www.example.org

    # Other directives here ...
</VirtualHost>

所有寄往非 172.20.30.50 位址的請求都將由主伺服器提供。寄往 172.20.30.50 有未知主機名稱,或沒有 Host: 標頭的請求,將由 www.example.com 提供。

top

在不同的 IP 位址提供相同的內容(例如內部和外部位址)。

伺服器機器有兩個 IP 位址(192.168.1.1172.20.30.40)。這部機器位於內部(區域網路)網路和外部(網際網路)網路之間。在網路外部,server.example.com 這個名稱解析為外部位址(172.20.30.40),但在網路內部,這個相同的名稱解析為內部位址(192.168.1.1)。

只要用一個 <VirtualHost> 區段,伺服器就能用相同的內容回應內部和外部請求。

<VirtualHost 192.168.1.1 172.20.30.40>
    DocumentRoot "/www/server1"
    ServerName server.example.com
    ServerAlias server
</VirtualHost>

現在,來自兩個網路的請求都將由同一個 <VirtualHost> 提供。

注意

在內部網路中,人們只要使用名稱 server 就可以,不用使用完全限定主機名稱 server.example.com

另請注意,在上述範例中,你可以將 IP 位址清單替換成 *,這將使得伺服器對所有位址回應相同內容。

top

在不同埠上執行不同網站。

您有多個網域會轉到相同的 IP,同時您也想要提供多個埠。下列範例說明,在確定最相符的 IP 位址和埠配對後,就會進行名稱配對。

Listen 80
Listen 8080

<VirtualHost 172.20.30.40:80>
    ServerName www.example.com
    DocumentRoot "/www/domain-80"
</VirtualHost>

<VirtualHost 172.20.30.40:8080>
    ServerName www.example.com
    DocumentRoot "/www/domain-8080"
</VirtualHost>

<VirtualHost 172.20.30.40:80>
    ServerName www.example.org
    DocumentRoot "/www/otherdomain-80"
</VirtualHost>

<VirtualHost 172.20.30.40:8080>
    ServerName www.example.org
    DocumentRoot "/www/otherdomain-8080"
</VirtualHost>
top

IP-based 的虛擬主機

該伺服器具有兩個 IP 位址(172.20.30.40172.20.30.50),它們分別解析為 www.example.comwww.example.org 網址。

Listen 80

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/example1"
    ServerName www.example.com
</VirtualHost>

<VirtualHost 172.20.30.50>
    DocumentRoot "/www/example2"
    ServerName www.example.org
</VirtualHost>

對於在任一 <VirtualHost> 指令中未指定之任何位址(例如 localhost)的要求,都會轉到主要伺服器(如果有的話)。

top

混合埠和 IP-based 的虛擬主機

該伺服器機器具有兩個 IP 位址(172.20.30.40172.20.30.50),它們分別解析為 www.example.comwww.example.org 網址。在每種情況中,我們都希望在埠 80 和 8080 上執行主機。

Listen 172.20.30.40:80
Listen 172.20.30.40:8080
Listen 172.20.30.50:80
Listen 172.20.30.50:8080

<VirtualHost 172.20.30.40:80>
    DocumentRoot "/www/example1-80"
    ServerName www.example.com
</VirtualHost>

<VirtualHost 172.20.30.40:8080>
    DocumentRoot "/www/example1-8080"
    ServerName www.example.com
</VirtualHost>

<VirtualHost 172.20.30.50:80>
    DocumentRoot "/www/example2-80"
    ServerName www.example.org
</VirtualHost>

<VirtualHost 172.20.30.50:8080>
    DocumentRoot "/www/example2-8080"
    ServerName www.example.org
</VirtualHost>
top

混合名稱和 IP-based 的虛擬主機

在 virtualhost 引數中指定之任何未出現在另一個 virtual host 中的位址,都是一個嚴格的 IP-based 虛擬主機。

Listen 80
<VirtualHost 172.20.30.40>
    DocumentRoot "/www/example1"
    ServerName www.example.com
</VirtualHost>

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/example2"
    ServerName www.example.org
</VirtualHost>

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/example3"
    ServerName www.example.net
</VirtualHost>

# IP-based
<VirtualHost 172.20.30.50>
    DocumentRoot "/www/example4"
    ServerName www.example.edu
</VirtualHost>

<VirtualHost 172.20.30.60>
    DocumentRoot "/www/example5"
    ServerName www.example.gov
</VirtualHost>
top

共同使用 Virtual_host 和 mod_proxy

下列範例讓前端機器透過執行於另一台機器上的伺服器來代理虛擬主機。在該範例中,於 192.168.111.2 的機器上設定了名稱相同的虛擬主機。使用 ProxyPreserveHost On 指令,以便轉送所需的主機名稱,以防我們將多個主機名稱代理至單一機器。

<VirtualHost *:*>
    ProxyPreserveHost On
    ProxyPass        "/" "http://192.168.111.2/"
    ProxyPassReverse "/" "http://192.168.111.2/"
    ServerName hostname.example.com
</VirtualHost>
top

使用 _default_ vhost

所有埠的 _default_ vhost

接收任何未指定的 IP 位址和埠的所有要求,也就是未用於任何其他虛擬主機的位址/埠配對。

<VirtualHost _default_:*>
    DocumentRoot "/www/default"
</VirtualHost>

使用具有萬用字元埠的此類預設 vhost,可有效禁止任何要求轉送至主要伺服器。

預設 vhost 絕不會提供已傳送至用於名稱為基礎 vhost 之位址/埠的要求。如果要求包含未知或不存在的 Host: 標頭,將會始終從主要名稱為基礎 vhost 提供服務(設定檔中最早出現對應於該位址/埠的 vhost)。

您可以使用 AliasMatchRewriteRule 將任一要求改寫至單一資訊頁面(或指令碼)。

不同埠的 _default_ vhost

與設定 1 相同,但伺服器聆聽多個埠,並且我們想要使用第二個 _default_ vhost 針對埠 80。

<VirtualHost _default_:80>
    DocumentRoot "/www/default80"
    # ...
</VirtualHost>

<VirtualHost _default_:*>
    DocumentRoot "/www/default"
    # ...
</VirtualHost>

埠 80 的預設 vhost(必須出現在任何具有萬用字元埠的預設 vhost 之前)會擷取所有已傳送到未指定 IP 位址的要求。主伺服器絕不用於提供要求。

單一埠的_default_ vhost

我們想要為埠 80 有一個預設 vhost,但沒有其他預設 vhost。

<VirtualHost _default_:80>
    DocumentRoot "/www/default"
...
</VirtualHost>

埠 80 沒有指定地址的要求會由預設 vhost 提供。任何其他沒有指定地址與埠的要求會由主伺服器提供。

虛擬主機宣告中任何使用*都會具有高於 _default_的優先權。

top

將基於名稱的 vhost 移轉到基於 IP 的 vhost

具有主機名稱 www.example.org的基於名稱的 vhost(取自於我們的 基於名稱的範例,設定 2)應取得其自己的 IP 位址。為了避免名稱伺服器或代理程式快取基於名稱的 vhost 的舊 IP 位址的問題,我們想要在移轉期間提供兩個變體。

解決方案很簡單,因為我們可以只將新 IP 位址(172.20.30.50)新增到 VirtualHost 指令。

Listen 80
ServerName www.example.com
DocumentRoot "/www/example1"

<VirtualHost 172.20.30.40 172.20.30.50>
    DocumentRoot "/www/example2"
    ServerName www.example.org
    # ...
</VirtualHost>

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/example3"
    ServerName www.example.net
    ServerAlias *.example.net
    # ...
</VirtualHost>

現在可以透過新地址(作為基於 IP 的 vhost)和舊地址(作為基於名稱的 vhost)存取 vhost。

top

使用 ServerPath 指令

我們有一個具有兩個基於名稱的 vhost 的伺服器。為了符合正確的虛擬主機,客戶端必須傳送正確的Host:標頭。舊的 HTTP/1.0 客戶端不會傳送這樣的標頭,而 Apache 也無法了解客戶端嘗試要接觸哪個 vhost(然後從主要 vhost 提供要求)。為了提供最大的向後相容性,我們創造了一個主要 vhost,它會傳回包含連結的單一頁面,其中連結包含到基於名稱的虛擬主機的 URL 字首。

<VirtualHost 172.20.30.40>
    # primary vhost
    DocumentRoot "/www/subdomain"
    RewriteEngine On
    RewriteRule "." "/www/subdomain/index.html"
    # ...
</VirtualHost>

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/subdomain/sub1"
    ServerName www.sub1.domain.tld
    ServerPath "/sub1/"
    RewriteEngine On
    RewriteRule "^(/sub1/.*)" "/www/subdomain$1"
    # ...
</VirtualHost>

<VirtualHost 172.20.30.40>
    DocumentRoot "/www/subdomain/sub2"
    ServerName www.sub2.domain.tld
    ServerPath "/sub2/"
    RewriteEngine On
    RewriteRule "^(/sub2/.*)" "/www/subdomain$1"
    # ...
</VirtualHost>

由於有 ServerPath 指令,對 URL http://www.sub1.domain.tld/sub1/ 的要求會永遠由 sub1-vhost 提供。
對 URL http://www.sub1.domain.tld/ 的要求只有在客戶端傳送正確的Host:標頭時才會由 sub1-vhost 提供。如果沒有傳送Host:標頭,客戶端會從主要主機取得資訊頁面。

請注意有一個奇怪的地方:如果客戶端沒有傳送Host:標頭,對 http://www.sub2.domain.tld/sub1/ 的要求也會由 sub1-vhost 提供。

RewriteRule 指令用來確保傳送正確的Host:標頭的客戶端可以使用兩個 URL 變體,也即是,有或沒有 URL 字首。

可用的語言:  en  |  fr  |  ja  |  ko  |  tr 

top

留言

注意事項
本區段並非 Q&A 區段。放在此區段的意見應針對改善文件或伺服器的建議,如果我們的管理員認為建議已實施或應視為無效/與主題無關,可能會將其移除。有關如何管理 Apache HTTP 伺服器的問題,可導向我們的 IRC 頻道 (#httpd) 於 Libera.chat 發問,或傳送至我們的寄送清單