在docker中搭建nginx文件服务器

本文章为原创非复制行为

前言

nginx是一个非常轻量化的工具,可以用来做文件服务器、反向代理服务器、负载均衡等,使用nginx作为文件服务器处理静态资源性能比同样常见的apache更高。在docker中部署nginx的好处是与宿主机、其他容器之间环境隔离,创建一个docker容器资源占用比虚拟机小很多,而且可以方便地修改官方镜像来定制自己的nginx镜像,便于迁移。文章中的系统为Centos7,Nginx版本为1.17.3

nginx作为文件服务器的一些问题

开启nginx目录浏览做文件服务器很简单只需要添加几行配置即可,但是这样不一定能满足所有人的需求。浏览器如果识别到了mime.types文件内定义的类型时,点击该类型文件是在浏览器中打开而不是下载。网上很多文章解决这个问题时直接在location中添加attachment附件方式,这样需要一个个设置特定结尾(扩展名)的文件,比较麻烦也不能覆盖所有结尾(扩展名)。

还有一种解决设置如下

location /download/ {
    types        { }
    default_type application/octet-stream;
}
当Url路径中包含/download/时,MIME类型会被重置为application/octet-stream

这样设置有一些缺点:

  1. 对浏览目录进行美化例如fancyindex时,如果将美化主题的css文件放在浏览目录下它的MIME类型text/css会被重置为application/octet-stream不显示正确的版式,同时浏览器Console可以看到Resource interpreted as Stylesheet but transferred with MIME type application/octet-stream


    MIME类型被重置
  1. 重置为application/octet-stream类型不是对所有浏览器有效,ie内核的浏览器和edge浏览器(非Chromium内核)不能触发下载请求,添加attachment附件方式则均可。

配置

先从官方拉取一个nginx镜像
[root@ykxz ~]# docker pull nginx

创建nginx容器并绑定目录

docker持久化主要使用两种方式,这两种权限管理不同,可以自由选择,绑定配置文件目录或配置文件可以在宿主机修改,并且数据会一直存在宿主机即便删除容器

1.volume
创建nginx容器时生成相关的默认配置文件,这种方式只能绑定目录不能绑定文件,首先创建一个docker volume,它在宿主机的/var/lib/docker/volume/nginx_conf/_data目录
[root@ykxz ~]# docker volume create nginx_conf

然后将volume绑定到容器内目录/etc/nginx,创建容器时docker会把容器内目录/etc/nginx(生成的默认配置文件)拷贝到volume

创建例子:

  • [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
如果已经有了配置文件可以将配置文件放在/host/path中,创建容器时会覆盖容器内目录/etc/nginx,注意如果宿主机绑定的不是/或~/这样的路径,docker会视为第一种处理

创建例子:

  • [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

需要注意的是如果将宿主机上的目录/host/path绑定到容器内目录/etc/nginx,则创建nginx容器时会将/host/path目录覆盖容器内目录/etc/nginx,如果/host/path为空目录则一创建好容器启动就会报[emerg] open() "/etc/nginx/nginx.conf" failed (2: No such file or directory)错误:容器内配置文件不存在已被空目录覆盖



如果没有配置文件但是想选择bind mounts方式绑定到宿主机上,官方配置教程先创建一个临时容器生成默认配置文件,然后将文件从容器拷贝到宿主机,再用这个文件持久化绑定

https://hub.docker.com/_/nginx

创建容器时的一些解释
--net=host 使用host网络模式,docker创建新容器时会使用默认的bridge,因为nginx容器时常要修改一些开放的端口,每次创建一个新nginx容器实在不是一件方便的事情,使用host模式需要在firewalld开放对应端口
-e TZ="Asia/Shanghai" 设置容器时区的环境变量,容器时区默认为UTC,会影响容器日志打印的时间
-v /etc/localtime:/etc/localtime:ro 将宿主机中的本地时间文件覆盖到容器,设置容器本地时间

修改配置文件开启目录浏览功能
我不建议直接修改配置文件目录/etc/nginx/下的nginx.conf文件,因为如果配置的站点多起来之后配置文件会显得特别冗长,应该在开启gzip传输压缩或者其他功能时再修改nginx.conf文件,nginx.conf文件已经有一行
include /etc/nginx/conf.d/*.conf
包含了同级目录conf.d下的所有以.conf结尾的配置文件,我们应该将新建的配置文件放在conf.d中,保持整洁

添加以下配置开启目录浏览功能:

autoindex on;
autoindex_exact_size off;    #设置以MB、GB等单位显示文件大小
autoindex_localtime on;    #设置显示目录或文件的时间属性

设置不下载请求结尾为xxx的特定文件(不区分大小写),这里设置的是mp4、mp3结尾,匹配mime.types文件内定义的类型,将在浏览器打开

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;
}

因为nginx不支持if的&&和||逻辑运算符和嵌套,所以定义一个flag变量判断请求的文件是否直接下载

以下是我的配置文件参考,可直接复制,必须修改的地方为

listen 7000; nginx监听的端口
server_name your.domain.com; 不使用域名访问可以删除
alias file_server/; 文件服务器目录,/不可以删除

# 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;
    }
}

配置文件的解释

  1. 开启目录浏览,顶层目录是与配置文件同级的file_server目录
  2. 请求的是文件而非目录且结尾不为mp4、mp3时添加attachment附件方式,保证所有浏览器都可以触发下载请求

最后一步,在firewalld开放对应端口并重启nginx容器
[root@ykxz ~]# firewall-cmd --permanent --add-port=7000/tcp
[root@ykxz ~]# firewall-cmd --reload
[root@ykxz ~]# docker restart nginx_container

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容