Nginx

起步

安装

容器

1
2
# TAG: 1.17.6, mainline, 1, 1.17, latest
podman pull nginx
托管一些简单的静态内容
1
podman run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
暴露外部端口
1
podman run --name some-nginx -d -p 8080:80 some-content-nginx

这样可以在浏览器中访问http://localhost:8080http://host-ip:8080

使用podman logs查看日志,如果出现 [warn] 1#1: conflicting server name "localhost" on 0.0.0.0:80, ignored错误,用如下命令查看是否多个地方使用了localhost的80端口。

1
grep -r localhost /etc/nginx/conf.d/
自定义配置
1
podman run --name my-custom-nginx-container -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx

如果希望在默认配置的基础上修改,可以将默认配置复制出来:

1
2
3
podman run --name tmp-nginx-container -d nginx
podman cp tmp-nginx-container:/etc/nginx/nginx.conf /host/path/nginx.conf
podman rm -f tmp-nginx-container
只读模式运行
1
podman run -d -p 80:80 --read-only -v $(pwd)/nginx-cache:/var/cache/nginx -v $(pwd)/nginx-pid:/var/run nginx
debug模式运行
1
podman run --name my-nginx -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx nginx-debug -g 'daemon off;'
用户和组id
1
2
$ id
uid=101(nginx) gid=101(nginx) groups=101(nginx)
以非root用户运行

需要修改nginx.conf

1
podman run -d -v $PWD/nginx.conf:/etc/nginx/nginx.conf nginx

其中nginx.conf需要重新定义如下内容:

1
pid        /tmp/nginx.pid;

还有如下内容:

1
2
3
4
5
6
7
8
http {
    client_body_temp_path /tmp/client_temp;
    proxy_temp_path       /tmp/proxy_temp_path;
    fastcgi_temp_path     /tmp/fastcgi_temp;
    uwsgi_temp_path       /tmp/uwsgi_temp;
    scgi_temp_path        /tmp/scgi_temp;
...
}

源码编译

官网下载最新版本的nginx。

一个常见的配置:

1
2
3
4
5
6
7
./configure
    --sbin-path=/usr/local/nginx/nginx
    --conf-path=/usr/local/nginx/nginx.conf
    --pid-path=/usr/local/nginx/nginx.pid
    --with-http_ssl_module
    --with-pcre=../pcre-8.44
    --with-zlib=../zlib-1.2.11

然后使用make命令安装。

启动、停止与重载配置

1
2
3
4
nginx -s stop #快速停止
nginx -s quit #在worker进程完成当前请求后停止nginx进程
nginx -s reload #重新加载配置文件以生效
nginx -s reopen #重新打开log文件

一旦主进程接收到重新加载配置的信号,它将检查新配置文件的语法有效性并尝试应用其中提供的配置。 如果成功,则主进程将启动新的工作进程,并将消息发送到旧的工作进程,要求它们关闭。 否则,主进程将回滚更改并继续使用旧配置。 旧的工作进程接收到关闭命令,停止接受新的连接并继续为当前请求提供服务,直到为所有此类请求提供服务。 之后,旧的工作进程退出。

也可以使用kill命令发送信号,nginx主进程id默认写入/usr/local/nginx/logs或/var/run目录中的nginx.pid 。例如给主进程id为1628的nginx发送QUIT信号:

1
kill -s QUIT 1628

使用ps命令获取所有nginx进程:

1
ps -ax | grep nginx

配置文件结构

nginx配置文件包含简单指令和块指令。简单指令由空格分割的名字和参数组成,并以分号结尾;块指令包含简单指令并用花括号括起来。每个块指令也是一个context,不在任何一个context中的指令处于main context中。

提供静态内容

假设本地的html文件在目录 data/www,图片资源在 data/images。则编辑配置文件,在http块中server块里设置两个location块。接下来是具体步骤:首先创建 data/www目录,并放置一个index.html,创建/data/images目录放一些图片。接下来编辑配置文件,添加如下内容:

1
2
3
4
http {
    server {
    }
}

一般来说,一个配置文件包含多个server块,由它们监听的端口和server name不同区分。一旦nginx确定了由哪个server处理请求,就会将请求头中的URI与server中location块的参数匹配。添加如下location块到server块中:

1
2
3
location / {
    root /data/www;
}

如果有/images开头的请求,也一样进行配置,如下:

1
2
3
4
5
6
7
8
9
server {
    location / {
        root /data/www;
    }

    location /images/ {
        root /data;
    }
}

现在就会有一个监听标准80端口的服务器在工作,这样就可以通过访问http://localhost/ 来访问此服务。

如果服务不正常,可以在/usr/local/nginx/logs或/var/log/nginx目录中查看access.log和 error.log文件来找出原因。

实战

用nginx提供groovy官网文档的浏览,首先下载文档后,解压将其中的documetation目录内容放置在服务器~/html目录中,然后开始设置。

1
podman run -i --rm nginx:1.19.0 cat /etc/nginx/nginx.conf > nginx.conf

编辑/host/path/nginx.conf文件。

1
2
3
4
5
6
7
8
server {
    listen       8080;
    server_name  localhost;

    location / {
        root /data/www;
    }
}
1
podman run --name groovy-docs -v $(pwd)/html:/data/www:ro -v $(pwd)/conf.d/nginx.conf:/etc/nginx/nginx.conf:ro -d -p 8080:8080 nginx:1.19.0

接下来只需要使用 http://hostip:8080访问服务即可。

设置代理服务器

nginx的一种常用用法是将其设置为代理服务器,这意味着服务器可以接收请求,将请求传递给代理服务器,从请求中检索响应并将它们发送给客户端。

我们将配置一个基本的代理服务器,该服务器为图像请求和本地目录中的文件提供服务,并将所有其他请求发送到代理服务器。 在此示例中,两个服务器都将在单个nginx实例上定义。

首先,通过向nginx的配置文件中添加一个包含以下内容的服务器块来定义代理服务器:

1
2
3
4
5
6
7
server {
    listen 8080;
    root /data/up1;

    location / {
    }
}

这将是一个简单的服务器,它在端口8080上侦听(以前,由于使用了标准端口80,因此未指定listen指令),并将所有请求映射到本地文件系统上的/data/up1目录。 创建此目录,并将index.html文件放入其中。 请注意,root指令位于server context中。 当选择用于服务请求的location块不包括自己的root指令时,将使用这种root指令。

接下来,使用上一部分中的服务器配置并对其进行修改以使其成为代理服务器配置。 在第一个location块中,将proxy_pass指令与参数中指定的代理服务器的协议,名称和端口放在一起(在本例中为http://localhost:8080):

1
2
3
4
5
6
7
8
9
server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location /images/ {
        root /data;
    }
}

第二个location块当前将带有/images/前缀的请求映射到/data/images目录下的文件,现在修改它以使其与具有典型文件扩展名的图像的请求匹配。 修改后的location块如下所示:

1
2
3
location ~ \.(gif|jpg|png)$ {
    root /data/images;
}

该参数是一个正则表达式,它匹配所有以.gif, .jpg, 或.png.结尾的URI。 正则表达式应以〜开头。 相应的请求将映射到/data/images目录。

当nginx选择一个location块来服务请求时,它首先检查指定前缀的location指令,记住最长前缀的location,然后检查正则表达式。 如果与正则表达式匹配,则nginx会选择此location,否则,它将选择之前记住的位置。

代理服务器的最终配置如下所示:

1
2
3
4
5
6
7
8
9
server {
    location / {
        proxy_pass http://localhost:8080/;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

该服务器将过滤以.gif,.jpg或.png结尾的请求,并将它们映射到/data/images目录(通过将URI添加到root指令的参数中),并将所有其他请求传递给上面配置的代理服务器。

实战

接下来,通过nginx代理访问groovy官网文档,而不是服务器上的本地内容。添加如下配置

1
2
3
4
5
6
server {
    listen       3000;
    location / {
        proxy_pass http://groovy-lang.org/;
    }
}

运行服务:

1
podman run --name groovy-docs-proxy -v $(pwd)/conf.d/nginx.conf:/etc/nginx/nginx.conf:ro -d -p 3000:3000 nginx:1.19.0

访问http://hostip:3000

设置FastCGI代理

nginx可用于将请求路由到FastCGI服务器,该服务器运行使用各种框架和编程语言(例如PHP)构建的应用程序。

与FastCGI服务器一起使用的最基本的nginx配置包括使用fastcgi_pass指令而不是proxy_pass指令,以及fastcgi_param指令来设置传递给FastCGI服务器的参数。 假设可在localhost:9000上访问FastCGI服务器。 以上一节中的代理配置为基础,用fastcgi_pass指令替换proxy_pass指令,并将参数更改为localhost:9000。 在PHP中,SCRIPT_FILENAME参数用于确定脚本名称,而QUERY_STRING参数用于传递请求参数。 结果配置为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

这将设置一个服务器,该服务器将通过FastCGI协议将除静态图像请求之外的所有请求路由到在localhost:9000上运行的代理服务器。