天天看点

【BUG记录】Nginx 出现 403:forbiden

我这里只记录一下我的情况。可能和大家的问题原因不对应。

BUG背景

我采用docker 部署Nginx,当我将html文件夹挂载到宿主机之后,访问nginx的默认页面的时候,出现了403:forbiden的情况。

查看日志文件

一般nginx的日志文件在/var/log/nginx文件夹下面,我这里docker部署nginx的时候挂载出来了,挂载到了宿主机的如下图示文件夹。

【BUG记录】Nginx 出现 403:forbiden

查看日志文件error.log文件,看到如下错误

2022/01/18 04:05:17 [error] 24#24: *1 directory index of “/usr/share/nginx/html/” is forbidden, client: x.x.x.x(我自己电脑的公网IP地址), server: localhost, request: “GET / HTTP/1.1”, host: “x.x.x.x:8080(这里是我容器宿主机的IP和端口号,8080是映射到nginx容器80的端口号)”

403 forbidden是什么意思?

403 Forbidden是HTTP协议中的一个状态码(Status Code)。可以简单的理解为没有权限访问此站。该状态表示服务器理解了本次请求但是拒绝执行该任务。(根据我的情况,我的是因为指定文件夹下面缺少html文件,但是这应该是404的范畴啊,这里我们暂时不管这个,可能是配置文件的原因)

default.conf(Nginx的server配置文件)

监听80端口,客户端访问容器的80端口,就可以访问到index.html文件

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    
}      

BUG探究

使用如下命令创建运行容器nginx

docker run -itd \
        --name nginx \
        -p 442:443\
        -p 8080:80 \
        -v /usr/local/nginx/html:/usr/share/nginx/html \
        -v /usr/local/nginx/config/nginx.conf:/etc/nginx/nginx.conf \
        -v /usr/local/nginx/config/conf.d/default.conf:/etc/nginx/conf.d/default.conf \
        -v /usr/local/nginx/logs:/var/log/nginx \
        -v /usr/local/nginx/ssl:/ssl \
        nginx      

html文件夹

容器里面的/usr/share/nginx/html文件夹我挂载到了宿主机的/usr/local/nginx/html

-v /usr/local/nginx/html:/usr/share/nginx/html      

我在使用docker 将容器内部的/usr/share/nginx/html的文件夹挂载出去的时候,宿主机(也就是我服务器)的/usr/local/nginx/html对应文件夹是没有任何文件的。

所以说docker 挂载文件夹的时候,并不会把容器文件夹下的东西拷贝到我的宿主机对应的文件夹里面。

并且进入容器内部的时候,在这个/usr/share/nginx/html文件夹下面也找不到index.html文件,大概是因为这个时候这个文件夹已经挂载到了宿主机的/usr/local/nginx/html上面,访问这个文件夹就等于访问宿主机的/usr/local/nginx/html,所以缺少index.html文件,就是default.conf配置文件中index index.html index.htm这行指定的文件,访问的时候,找不到文件,就发生了403

日志文件

日志文件夹我也挂载了出去

-v /usr/local/nginx/logs:/var/log/nginx \      

但是容器启动后,宿主机下面却多了两个日志文件。我想应该是docker调用nginx的脚本文件启动nginx服务的时候写入的。(所以容器启动时和启动后生成的文件是没有问题的,都是能够正常使用的)。

​​docker是怎么运行容器服务的​

【BUG记录】Nginx 出现 403:forbiden

ssl文件夹

我挂载了一个ssl文件夹,但是这个文件夹在nginx镜像里面是肯定没有的

所以docker会帮我们去创建容器内部的/ssl文件夹

-v /usr/local/nginx/ssl:/ssl \      

总结:

使用docker -v 挂载文件的时候,最好是把容器里面的文件都放到宿主机上面。容器服务启动的时候所生成的文件可以不用管他,他会自动生成到宿主机上面。

使用docker搭建服务,目前我想到的最好方法就是先生成一个比较简单的容器服务运行,然后将配置文件等拷贝到服务器准备做挂载的文件夹下面

比如像下面这样,先run一个简单的容器

docker run -itd --name nginx  nginx      

使用docker exec命令进入容器内部,查看里面有啥文件是需要挂载出来的

一般就是日志文件,配置文件这些挂载出来比较好

docker exec -it 容器名/容器ID /bin/bash      

进入到容器里面以后,和平常的linux文件系统一样,你可以到处看看,或者查看官网和其他博客看他的文件结构是怎样的,日志文件夹和配置文件放在哪里

可以使用find命令查找文件的路径,像下面这样

# 查找nginx配置文件nginx.conf 
# 这个在/etc/nginx/nginx.conf
find / -name "nginx.conf"      

docker cp 指令可以将容器里面的文件拷贝到宿主机的指定文件夹

docker cp nginx(容器名):/etc/nginx/conf.d/default.conf /usr/local/nginx/config/conf.d/default.conf      

弄好了之后退出容器

exit      

Nginx 403:forbiden的其他可能原因

文件夹权限问题

如果nginx没有web目录的操作权限,也会出现403错误

解决办法:修改web目录的读写权限,或者是把nginx的启动用户改成目录的所属用户,重启Nginx即可解决

如下方式是比较暴力的,文件所有者(Owner)、用户组(Group)、其它用户(Other Users)都赋予了最高权限:可读可写可执行

chmod -R 777 文件夹      

由于启动用户和nginx工作用户不一致所致

查看启动用户是谁

ps aux | grep "nginx: worker process" | awk'{print $1}'      

​​Linux ps 命令​​​​Linux grep 命令​​​​Linux awk 命令​​ shell “|” ,代表有管道。"|" 左右被理解为简单命令,即前一个(左边)简单命令的标准输出指向后一个(右边)标准命令的标准输入

awk会根据分隔符将输入分成若干个字段,$0为整行,$1为第一个字段,$2 为第2个地段,依此类推…

为打印一个字段或所有字段,使用print命令。这是一个awk动作

nginx.conf 配置文件定义了user, 这里默认的user 是 nginx

将user替换为查询到的启动用户

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}      

selinux

SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统。NSA是在Linux社区的帮助下开发了一种访问控制体系,在这种访问控制体系的限制下,进程只能访问那些在他的任务中所需要文件。SELinux 默认安装在 Fedora 和 Red Hat Enterprise Linux 上,也可以作为其他发行版上容易安装的包得到。

seLinux设置为开启状态(enabled),也可能导致403

查看当前selinux的状态

/usr/sbin/sestatus      

你可以修改他的配置文件

vi /etc/selinux/config      

设置为关闭,一般默认状态是关闭的

SELINUX=disabled      

使得source命令修改立即生效或者reboot服务器。

source /etc/selinux/config
. /etc/selinux/config      

References:

  • ​​https://baike.baidu.com/item/SELinux/8865268?fr=aladdin​​
  • ​​https://www.linuxprobe.com/linux-awk-clever.html​​

继续阅读