Nginx - 自定义镜像
笔记
虽然 DockerHub 已经有了 Nginx 或 OpenResty,但是不够「灵活」,我们无法安装第三方模块。本内容讲解如何利用 Dockerfile 构建属于自己的 Nginx 或 OpenResty 镜像。
2021-11-14 @Young Kbt
# 前言
之前我一直使用的是从 DockerHub 拉取下载的镜像,但是该镜像已经固定了模块,我在使用的过程时,尝试了 Nginx 自带的下载站点,但是界面比较简洁、普通,而且字体很「拥挤」,于是我踏上寻找优化下载站点页面的道路,然后我发现了第三方模块 ngx-fancyindex
,该模块优化了下载站点的页面,看起来更加舒服,于是我打算使用它。
但是我发现了一个问题,我的 Nginx 是从 DockerHub 拉取的,说明供应商已经设计好所需的模块,但是并没有我想要的 ngx-fancyindex
模块,供应商只提供了基础的 Nginx 镜像。于是我就无法针对这个 Nginx 镜像添加第三方模块,特别是后期,如果我需要添加多个第三方模块,那面对拉取的 Nginx 镜像无能为力。
于是,我就打算自己构建一个 Nginx 镜像,在构建的过程,添加第三方模块。
我的下载站点地址:https://www.youngkbt.cn/download/ (opens new window)
下面的内容有很多代码,如果不喜欢复制这些代码,这里提供源码文件的下载地址:https://www.youngkbt.cn/download/OpenResty构建/ (opens new window)
需要全部的源码,下载 openresty-resource.tar.gz
压缩包。需要单个文件,就点击单个文件。
如果想要了解如何构建我的下载站点,点击跳转
# 构建过程
最后的结果不繁琐,仅仅一个 Dockerfile 文件就解决,但是过程耗费了我半天,这里先提供 Dockerfile 文件内容:
FROM centos:7.9
# openrestry 版本
ARG OPENRESTY_VERSION="1.19.9.1"
# 第三方模块版本,我安装 ngx-fancyindex 模块
#ARG FANCYINDEX_VERSION="0.5.2"
# 镜像信息
LABEL AUTHOR=YoungKbt
# 如果事先下载第三模块的压缩包,则放入 Dockerfile 所在的目录下,取消注释
#ADD ngx-fancyindex-${FANCYINDEX_VERSION}.tar.xz /tmp
# 安装 Nginx 环境库,下载第三方模块和 Nginx 或 Openresty,并解压编译安装
RUN yum install -y \
gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel --nogpgcheck \
curl wget perl make vim tar \
&& cd /tmp \
&& wget https://openresty.org/download/openresty-${OPENRESTY_VERSION}.tar.gz \
# 如果不喜欢先下载第三方模块然后 ADD,则这里填写第三方模块的下载地址,然后取消下面两行注释
# && wget https://github.com/aperezdc/ngx-fancyindex/releases/download/v${FANCYINDEX_VERSION}/ngx-fancyindex-${FANCYINDEX_VERSION}.tar.xz \
# && tar xvf ngx-fancyindex-${FANCYINDEX_VERSION}.tar.xz \
&& tar zxvf openresty-${OPENRESTY_VERSION}.tar.gz \
&& cd openresty-${OPENRESTY_VERSION} \
&& ./configure \
--prefix=/usr/local/openresty \
--with-cc-opt='-O2 -DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/zlib/include -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl111/include' \
--with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib -L/usr/local/openresty/zlib/lib -L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl111/lib -Wl,-rpath,/usr/local/openresty/zlib/lib:/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl111/lib' \
--with-pcre-jit \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-http_v2_module \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_secure_link_module \
--with-http_random_index_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-threads --with-stream \
--with-http_ssl_module \
# --add-module=../ngx-fancyindex-${FANCYINDEX_VERSION} \
&& make build \
&& make install \
&& cd /tmp \
&& rm -rf ngx-fancyindex-${FANCYINDEX_VERSION}.tar.xz \
&& rm -rf openresty-${OPENRESTY_VERSION}.tar.gz \
&& yum clean all \
&& mkdir -p /etc/nginx/conf.d \
# 必须创建一个目录,如果这个目录不存在,则无法启动镜像
&& mkdir -p /var/run/openresty
# 将 nginx 命令添加至全局变量,这里演示常用的三个
ENV PATH=$PATH:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin
ENV LUA_PATH="/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua"
ENV LUA_CPATH="/usr/local/openresty/site/lualib/?.so;/usr/local/openresty/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so"
# 将 nginx 配置文件,覆盖 Nginx 自带的配置文件
COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
# 将 default.conf 配置文件,添加到指定目录下
COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf
# 启动容器时,执行该命令,如果不执行,则容器启动后会自动停止运行
CMD ["/usr/local/openresty/nginx/sbin/nginx", "-g", "daemon off;"]
# Use SIGQUIT instead of default SIGTERM to cleanly drain requests
# See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls
STOPSIGNAL SIGQUIT
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
代码虽然多,但是并不复杂,容我慢慢解释:
首先注意你的基础镜像,我是基于 Centos:7.9 系统,你可以是 Ubuntu 或者其他的系统,FROM 指令会先去本地找镜像,没有找到则去 DockerHub 下载到本地,再使用
我这里使用的是 OpenRestry,这个平台集成了 Nginx 和 Lua 语言,总体而言就是拥有更多功能的 Nginx。
4、7 行请填写 OpenRestry 或者 Nginx 的版本,以及第三方模块的版本号,我使用一个变量存储版本号,你也可以直接在下载的时候,写版本号
10 行的镜像信息
LABEL
可以不写,一般是镜像的关键词、作者信息等13 行的 ADD 可以不写,因为我的第三方模块地址在 GitHub,而通过
wget
下载经常连接超时、下载失败,所以我就先下载到 Windows,然后传输到服务器里。注意,如果采用这种方式,请将第三方模块放到 Dockerfile 所在的目录里17 - 18 行 是下载安装 Nginx 所需的运行环境,以及一些常用的命令,可以根据需求自行添加命令
20 行下载 OpenResty,可以更换为 Nginx 的下载地址,后面
${}
就是存储版本号的变量21 行表示在
/tmp
目录下执行安装操作,构建完成后,可以去该目录下查看源码22 - 23 行下载第三方模块并解压,如果采用第 13 行的 ADD 方式,就注释掉或者删除掉
26 - 54 行是编译并安装。第三方模块请添加在第 51 行代码后,第 52 行代码就是我添加的第三方模块,该路径与 OpenResty 同级,所以
../
就是返回上一级目录,找到第三模块的根目录名。52 行之前都是常用的自带模块,建议不要删除,日后可能用到。
55 - 57 行是删除下载的压缩包,但是并没有删除解压之后的目录,你可以根据需求决定要不要删除
58 行是清除之前 yum 安装的环境以及命令的缓存,注意:只是清除安装过程的缓存,不会卸载安装的库和命令。因为 yum 下载后成功后,将一份存在缓存,为了不占用空间,所以清除掉
59 行是为了适应官方的镜像配置处理。一般而言,我们不能直接操作 Nginx 的「核心」配置文件
nginx.conf
,而是操作「子」配置文件xxx.conf
。因为「核心」配置文件通过include
指令将「子」配置文件进行引入,所以我们只需在nginx.conf
加入include /etc/nginx/conf.d;
,即可把 conf.d 目录下的所有「子」配置文件引入其中。这样做是为了安全考虑,直接操作核心配置文件,容易引起安全问题。下面我会提供 nginx.conf 的模板,该模板已经使用了
include /etc/nginx/conf.d;
,不需要自己写。61 行是因为我在启动镜像的时候,报错:
/var/run/openresty
不存在,所以构建时候需要创建,如果你的报错不是这个目录,而修改即可64 - 66 行添加 nginx 命令到全局变量,如果是 OpenRestry 不需要修改,如果是 Nginx,你需要删除第一个和第三个路径,只留下第二个
69 行将宿主机的
nginx.conf
覆盖原来的 nginx.conf,因为原来的 nginx.conf 没有include /etc/nginx/conf.d;
,下面会有宿主机的nginx.conf
模板72 行给
/etc/nginx/conf.d
目录下添加一个 .conf 配置文件,以后我们只需要在这个配置文件添加 server 模块,下方有模板提供75 行是必须的,它是启动容器后不希望容器停止的命令
79 行是优化命令,可以不加
说了那么多,大家可能没有耐心看完,我想说,如果你想了解 OpenResty 或 Nginx 镜像的构建过程,请了解它。我这里也说明下简单的上手:
第 1 行可以修改
第 4、7 行可以修改版本,版本目前是最新的
第 10 行可以修改
第 22、23 行修改自己的第三方模块地址,如果下载失败,则看上方的第 5 个解释(黑点)
第 52 行以及后面的是第三模块路径(容器内的路径,并不是宿主机的路径)
第 65、66 行如果是 Nginx,请删除掉,并且 64 行删除掉第一个和第三个路径
第 75 行如果是 Nginx,请填写 nginx 可执行文件的路径
# 配置文件模板
下面提供 nginx.conf 的模板:
# nginx.conf -- docker-openresty
#
# This file is installed to:
# `/usr/local/openresty/nginx/conf/nginx.conf`
# and is the file loaded by nginx at startup,
# unless the user specifies otherwise.
#
# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server`
# section and adds this directive:
# `include /etc/nginx/conf.d/*.conf;`
#
# The `docker-openresty` file `nginx.vh.default.conf` is copied to
# `/etc/nginx/conf.d/default.conf`. It contains the `server section
# of the upstream `nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#
user nobody;
#worker_processes 1;
# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# Enables or disables the use of underscores in client request header fields.
# When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive.
# underscores_in_headers off;
#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 logs/access.log main;
# Log in JSON Format
# log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", '
# '"remote_addr": "$remote_addr", '
# '"body_bytes_sent": $body_bytes_sent, '
# '"request_time": $request_time, '
# '"response_status": $status, '
# '"request": "$request", '
# '"request_method": "$request_method", '
# '"host": "$host",'
# '"upstream_addr": "$upstream_addr",'
# '"http_x_forwarded_for": "$http_x_forwarded_for",'
# '"http_referrer": "$http_referer", '
# '"http_user_agent": "$http_user_agent", '
# '"http_version": "$server_protocol", '
# '"nginx_access": true }';
# access_log /dev/stdout nginxlog_json;
# See Move default writable paths to a dedicated directory (#119)
# https://github.com/openresty/docker-openresty/issues/119
client_body_temp_path /var/run/openresty/nginx-client-body;
proxy_temp_path /var/run/openresty/nginx-proxy;
fastcgi_temp_path /var/run/openresty/nginx-fastcgi;
uwsgi_temp_path /var/run/openresty/nginx-uwsgi;
scgi_temp_path /var/run/openresty/nginx-scgi;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
# Don't reveal OpenResty version to clients.
# server_tokens off;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
nginx.vh.default.conf 模板内容:
# nginx.vh.default.conf -- docker-openresty
#
# This file is installed to:
# `/etc/nginx/conf.d/default.conf`
#
# It tracks the `server` section of the upstream OpenResty's `nginx.conf`.
#
# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by
# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/local/openresty/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/openresty/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root /usr/local/openresty/nginx/html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
这里给出我的 Dockfile 所在的目录下所有内容:
可以看出,我并非 ADD nginx.conf
,而是 ADD mynginx.conf
,这是我修改后的 nginx.conf
,比如开启压缩、优化访问速度等指令,压缩包是我的第三方模块,因为 wget
下载的地址是 GitHub,太慢了。