Docker安装Nginx

常规安装

参考官网:https://nginx.org/en/linux_packages.html#Ubuntu

安装先决条件

1
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring

导入官方 nginx 签名密钥,以便 apt 可以验证软件包的真实性。

1
2
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

验证下载的文件是否包含正确的密钥:

1
gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg

以稳定的 nginx 包设置 apt 存储库,请运行以下命令:

1
2
3
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

使用主线 nginx 包,请运行以下命令:

1
2
3
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

设置存储库固定,使我们的软件包优于发行版提供的软件包

1
2
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx

安装:

1
2
3
4
5
sudo apt update
sudo apt install nginx

# 移除
sudo apt autoremove --purge nginx

配置站点

在线配置参考:https://www.digitalocean.com/community/tools/nginx?domains.0.https.certType=custom&global.app.lang=zhCN

迁移配置

1
2
3
4
cp -r /etc/nginx /lims/nginx
cd /lims/nginx
mkdir nginxconfig.io www ssl
chmod 666 nginxconfig.io www ssl

生成 Diffie-Hellman keys:

1
2
# 在服务器上运行此命令生成Diffie-Hellman keys
openssl dhparam -out dhparam.pem 2048

Docker Compose 安装

新建 docker-compose.yml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: "3.1"

services:
nginx:
image: nginx:1.22.0
container_name: nginx
restart: always
volumes:
- /lims/nginx/www:/var/www
- /lims/nginx/logs:/var/log/nginx
- /lims/nginx:/etc/nginx
ports:
- 8080:80
- 8081:443
environment:
- NGINX_PORT=80
- TZ=Asia/Shanghai
privileged: true

目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.
├── conf.d
│ └── default.conf
├── dhparam.pem
├── docker-compose.yml
├── fastcgi_params
├── logs
│ ├── access.log
│ └── error.log
├── mime.types
├── modules -> /usr/lib/nginx/modules
├── modules-enabled
├── nginx.conf
├── nginxconfig.io
│ ├── general.conf
│ ├── proxy.conf
│ └── security.conf
├── scgi_params
├── ssl
│ ├── laas.ponytest.com.crt
│ └── laas.ponytest.com.key
├── uwsgi_params
└── www

权限配置

授权 www 文件夹下执行权限:

1
chmod a+rwx www/*
1
2
3
4
5
6
7
# 启动
docker compose up -d

# 移除
docker-compose down -v

docker ps | grep nginx

Nginx 配置参考

Nginx1.22.0.7z

nginx.conf 配置:

1
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
# Generated by nginxconfig.io
# https://www.digitalocean.com/community/tools/nginx?domains.0.https.hstsPreload=true&domains.0.https.certType=custom&domains.0.php.php=false&domains.0.reverseProxy.reverseProxy=true&domains.0.reverseProxy.path=%2Fapi&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&domains.0.logging.accessLog=true&domains.0.logging.errorLog=true&global.logging.logNotFound=true&global.app.lang=zhCN

user nginx;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;

# Load modules
include /etc/nginx/modules-enabled/*.conf;

events {
multi_accept on;
worker_connections 65535;
}

http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
types_hash_max_size 2048;
types_hash_bucket_size 64;
client_max_body_size 16M;

# MIME
include mime.types;
default_type application/octet-stream;

# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;

# SSL
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

# Diffie-Hellman parameter for DHE ciphersuites
ssl_dhparam /etc/nginx/dhparam.pem;

# Mozilla Intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# OCSP Stapling (证书在线查询,需要关闭)
# ssl_stapling on;
# ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;

# Connection header for WebSocket reverse proxy
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}

map $remote_addr $proxy_forwarded_elem {

# IPv4 addresses can be sent as-is
~^[0-9.]+$ "for=$remote_addr";

# IPv6 addresses need to be bracketed and quoted
~^[0-9A-Fa-f:.]+$ "for=\"[$remote_addr]\"";

# Unix domain socket names cannot be represented in RFC 7239 syntax
default "for=unknown";
}

map $http_forwarded $proxy_add_forwarded {

# If the incoming Forwarded header is syntactically valid, append to it
"~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";

# Otherwise, replace it
default "$proxy_forwarded_elem";
}

# Load configs
include /etc/nginx/conf.d/*.conf;
}

nginxconfig.io/general.conf 配置:

1
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
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}

# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}

# assets, media
# 如果代理 minio等文件服务器,需要删除通用规则,添加到具体 server 配置中;
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
expires 7d;
access_log off;
}

# svg, fonts
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
expires 7d;
access_log off;
}

# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

nginxconfig.io/proxy.conf 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
proxy_http_version                 1.1;
proxy_cache_bypass $http_upgrade;

# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header REMOTE-HOST $remote_addr;

proxy_hide_header X-Powered-By;

# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

nginxconfig.io/security.conf 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# security headers
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Download-Options "noopen" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;

# . files
location ~ /\.(?!well-known) {
deny all;
}

conf.d/laas.ponytest.com.conf 配置:

1
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
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name laas.ponytest.com;
root /var/www/laas.ponytest.com/public;

# SSL
ssl_certificate /etc/nginx/ssl/laas.ponytest.com.crt;
ssl_certificate_key /etc/nginx/ssl/laas.ponytest.com.key;

# security
include /etc/nginx/nginxconfig.io/security.conf;

# logging
access_log /var/log/nginx/laas.ponytest.com.access.log;
error_log /var/log/nginx/laas.ponytest.com.error.log warn;

# index.html fallback
location / {
try_files $uri $uri/ @router;
index index.html index.htm;
error_page 405 =200 http://$host$request_uri;
}

# reverse proxy
location /api/ {
proxy_pass https://laas.ponytest.com:8082; #转发请求的地址
rewrite ^/api/(.*)$ /$1 break;
include /etc/nginx/nginxconfig.io/proxy.conf;
}

location @router {
rewrite ^.*$ /index.html last;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# additional config
include /etc/nginx/nginxconfig.io/general.conf;
}

# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name laas.ponytest.com;
return 301 https://laas.ponytest.com$request_uri;
}