本文章為原創(chuàng)非復(fù)制行為
前言
nginx是一個(gè)非常輕量化的工具畅形,可以用來做文件服務(wù)器潮尝、反向代理服務(wù)器、負(fù)載均衡等薄料,使用nginx作為文件服務(wù)器處理靜態(tài)資源性能比同樣常見的apache更高获诈。在docker中部署nginx的好處是與宿主機(jī)仍源、其他容器之間環(huán)境隔離,創(chuàng)建一個(gè)docker容器資源占用比虛擬機(jī)小很多舔涎,而且可以方便地修改官方鏡像來定制自己的nginx鏡像笼踩,便于遷移。文章中的系統(tǒng)為Centos7终抽,Nginx版本為1.17.3
nginx作為文件服務(wù)器的一些問題
開啟nginx目錄瀏覽做文件服務(wù)器很簡單只需要添加幾行配置即可戳表,但是這樣不一定能滿足所有人的需求桶至。瀏覽器如果識別到了mime.types文件內(nèi)定義的類型時(shí)昼伴,點(diǎn)擊該類型文件是在瀏覽器中打開而不是下載。網(wǎng)上很多文章解決這個(gè)問題時(shí)直接在location中添加attachment附件方式镣屹,這樣需要一個(gè)個(gè)設(shè)置特定結(jié)尾(擴(kuò)展名)的文件圃郊,比較麻煩也不能覆蓋所有結(jié)尾(擴(kuò)展名)。
還有一種解決設(shè)置如下
location /download/ {
types { }
default_type application/octet-stream;
}
當(dāng)Url路徑中包含/download/時(shí)女蜈,MIME類型會被重置為application/octet-stream
這樣設(shè)置有一些缺點(diǎn):
-
對瀏覽目錄進(jìn)行美化例如fancyindex時(shí)持舆,如果將美化主題的css文件放在瀏覽目錄下它的MIME類型text/css會被重置為application/octet-stream不顯示正確的版式,同時(shí)瀏覽器Console可以看到Resource interpreted as Stylesheet but transferred with MIME type application/octet-stream
MIME類型被重置
- 重置為application/octet-stream類型不是對所有瀏覽器有效伪窖,ie內(nèi)核的瀏覽器和edge瀏覽器(非Chromium內(nèi)核)不能觸發(fā)下載請求逸寓,添加attachment附件方式則均可。
配置
先從官方拉取一個(gè)nginx鏡像
[root@ykxz ~]# docker pull nginx
創(chuàng)建nginx容器并綁定目錄
docker持久化主要使用兩種方式覆山,這兩種權(quán)限管理不同竹伸,可以自由選擇,綁定配置文件目錄或配置文件可以在宿主機(jī)修改,并且數(shù)據(jù)會一直存在宿主機(jī)即便刪除容器
1.volume
創(chuàng)建nginx容器時(shí)生成相關(guān)的默認(rèn)配置文件勋篓,這種方式只能綁定目錄不能綁定文件吧享,首先創(chuàng)建一個(gè)docker volume,它在宿主機(jī)的/var/lib/docker/volume/nginx_conf/_data目錄
[root@ykxz ~]# docker volume create nginx_conf
然后將volume綁定到容器內(nèi)目錄/etc/nginx譬嚣,創(chuàng)建容器時(shí)docker會把容器內(nèi)目錄/etc/nginx(生成的默認(rèn)配置文件)拷貝到volume
創(chuàng)建例子:
- [root@ykxz ~]# docker run --name nginx_container --restart=always --net=host \
??-e TZ="Asia/Shanghai" -v /etc/localtime:/etc/localtime:ro \
??-v nginx_conf:/etc/nginx \
??-d nginx
2.bind mounts
如果已經(jīng)有了配置文件可以將配置文件放在/host/path中钢颂,創(chuàng)建容器時(shí)會覆蓋容器內(nèi)目錄/etc/nginx,注意如果宿主機(jī)綁定的不是/或~/這樣的路徑拜银,docker會視為第一種處理
創(chuàng)建例子:
- [root@ykxz ~]# docker run --name nginx_container --restart=always --net=host \
??-e TZ="Asia/Shanghai" -v /etc/localtime:/etc/localtime:ro \
??-v /docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro -v /docker/nginx/conf.d:/etc/nginx/conf.d \
??-v /docker/nginx/logs:/var/log/nginx \
??-d nginx
需要注意的是如果將宿主機(jī)上的目錄/host/path綁定到容器內(nèi)目錄/etc/nginx凉翻,則創(chuàng)建nginx容器時(shí)會將/host/path目錄覆蓋容器內(nèi)目錄/etc/nginx莲镣,如果/host/path為空目錄則一創(chuàng)建好容器啟動就會報(bào)[emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)錯(cuò)誤:容器內(nèi)配置文件不存在已被空目錄覆蓋
如果沒有配置文件但是想選擇bind mounts方式綁定到宿主機(jī)上,官方配置教程先創(chuàng)建一個(gè)臨時(shí)容器生成默認(rèn)配置文件,然后將文件從容器拷貝到宿主機(jī)蕉汪,再用這個(gè)文件持久化綁定
創(chuàng)建容器時(shí)的一些解釋
--net=host 使用host網(wǎng)絡(luò)模式,docker創(chuàng)建新容器時(shí)會使用默認(rèn)的bridge涕蚤,因?yàn)閚ginx容器時(shí)常要修改一些開放的端口地来,每次創(chuàng)建一個(gè)新nginx容器實(shí)在不是一件方便的事情,使用host模式需要在firewalld開放對應(yīng)端口
-e TZ="Asia/Shanghai" 設(shè)置容器時(shí)區(qū)的環(huán)境變量幌蚊,容器時(shí)區(qū)默認(rèn)為UTC谤碳,會影響容器日志打印的時(shí)間
-v /etc/localtime:/etc/localtime:ro 將宿主機(jī)中的本地時(shí)間文件覆蓋到容器,設(shè)置容器本地時(shí)間
修改配置文件開啟目錄瀏覽功能
我不建議直接修改配置文件目錄/etc/nginx/下的nginx.conf文件溢豆,因?yàn)槿绻渲玫恼军c(diǎn)多起來之后配置文件會顯得特別冗長蜒简,應(yīng)該在開啟gzip傳輸壓縮或者其他功能時(shí)再修改nginx.conf文件,nginx.conf文件已經(jīng)有一行
include /etc/nginx/conf.d/*.conf
包含了同級目錄conf.d下的所有以.conf結(jié)尾的配置文件漩仙,我們應(yīng)該將新建的配置文件放在conf.d中搓茬,保持整潔
添加以下配置開啟目錄瀏覽功能:
autoindex on;
autoindex_exact_size off; #設(shè)置以MB、GB等單位顯示文件大小
autoindex_localtime on; #設(shè)置顯示目錄或文件的時(shí)間屬性
設(shè)置不下載請求結(jié)尾為xxx的特定文件(不區(qū)分大小寫)队他,這里設(shè)置的是mp4卷仑、mp3結(jié)尾,匹配mime.types文件內(nèi)定義的類型麸折,將在瀏覽器打開
set $flag 0;
if (-f $request_filename) {
set $flag 1;
}
if ($request_filename ~* \.(mp4|mp3)$) {
set $flag 0;
}
if ($flag = 1) {
add_header Content-Disposition attachment;
}
因?yàn)閚ginx不支持if的&&和||邏輯運(yùn)算符和嵌套锡凝,所以定義一個(gè)flag變量判斷請求的文件是否直接下載
以下是我的配置文件參考,可直接復(fù)制垢啼,必須修改的地方為
listen 7000;?nginx監(jiān)聽的端口
server_name your.domain.com;?不使用域名訪問可以刪除
alias file_server/;?文件服務(wù)器目錄窜锯,/不可以刪除
# vim: ft=conf
server {
listen 7000;
server_name your.domain.com;
charset utf-8;
location / {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
alias file_server/;
set $flag 0;
if (-f $request_filename) {
set $flag 1;
}
if ($request_filename ~* \.(mp4|mp3)$) {
set $flag 0;
}
if ($flag = 1) {
add_header Content-Disposition attachment;
}
}
error_log logs/error_your.domain.com:7000.log error;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
配置文件的解釋
- 開啟目錄瀏覽,頂層目錄是與配置文件同級的file_server目錄
- 請求的是文件而非目錄且結(jié)尾不為mp4芭析、mp3時(shí)添加attachment附件方式锚扎,保證所有瀏覽器都可以觸發(fā)下載請求
最后一步,在firewalld開放對應(yīng)端口并重啟nginx容器
[root@ykxz ~]# firewall-cmd --permanent --add-port=7000/tcp
[root@ykxz ~]# firewall-cmd --reload
[root@ykxz ~]# docker restart nginx_container