使用 nginx / docker 将 next.js 部署到 openshift

问题描述 投票:0回答:1

在使用默认的 next.js 导出类型时,使用 docker 和 nginx 部署到 openshift 时,我收到 nginx 403 禁止。

如果我执行 next.config.js 输出:'导出,我得到了网站,但不时刷新页面时遇到 503 或发生客户端应用程序错误。

如果我默认不输出“导出”,我会得到 403。

理想情况下,我想在没有静态导出的情况下进行部署。我正在使用使用节点的 docker 容器,部署到 openshift。

这是错误。

这是我的 nginx.conf 文件。

# Set worker processes based on your CPU cores, nginx does not benefit from setting more than that
worker_processes auto;

# Load perl module for env var subsitution
load_module modules/ngx_http_perl_module.so;

# read in env variable
env runtimeEnvironment;
env applicationName;

# number of file descriptors used for nginx
# the limit for the maximum FDs on the server is usually set by the OS.
# if you don't set FD's then OS settings will be used which is by default 2000
worker_rlimit_nofile 100000;

# change pid loc for lower privileged account
pid        /tmp/nginx.pid;

# Log errors/emerg/crit to syslog (splunk)
# Log crit events to local container output
error_log syslog:server=splunk-dmz.nvthbs.local:21514 error;
error_log /var/log/nginx/error.log crit;

# provides the configuration file context in which the directives that affect connection processing are specified.
events {
    # determines how many clients will be served per worker
    # max clients = worker_connections * worker_processes
    # max clients is also limited by the number of socket connections available on the system (~64k)
    worker_connections 4000;

    # optimization to serve multiple clients per thread
    use epoll;

    # enable multiple connections
    multi_accept on;
}

http {
    # set env vars
    perl_set $runtimeenv 'sub { return $ENV{"runtimeEnvironment"};}';
    perl_set $appName 'sub { return $ENV{"applicationName"};}';

    # limit the number of connections per single IP - DDOS Protection
    limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;

    # limit the number of requests for a given session - DDOS Protection
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

    # if the request body size is more than the buffer size, then the entire (or partial)
    # request body is written into a temporary file
    # affects any POST actions sent to nginx
    client_body_buffer_size  128k;

    # buffer size for reading client request header
    client_header_buffer_size 10K;

    # maximum number and size of buffers for large headers to read from client request
    large_client_header_buffers 4 256k;

    # time a server will wait for client header to be sent after request
    client_header_timeout 12;

    # time a server will wait for client body to be sent after request
    client_body_timeout 12;

    # timeout for keep-alive connections to client
    keepalive_timeout 30;

    # timeout between two reads - keeps memory free -- default 60
    send_timeout 10;

    # set log format for access logs
    log_format  custom 'Application:$appname Environment:$runtimeenv '
                              '- $remote_addr - $remote_user [$time_local] '
                                 '"$request" $status $body_bytes_sent '
                                 '"$http_referer" "$http_user_agent" '
                                 '"$http_x_forwarded_for" $request_id ';
    
    # Condition map to reduce access logging and eliminate 200 / 300
    map $status $loggable {
        ~^[23]  0;
        default 1;
    }

    # Access log configuration with conditional statement applied to reduce logging events
    # access_log syslog:server=splunk-dmz.nvthbs.local:21514,facility=local7,tag=nginx custom if=$loggable;

    # access logging all events
    access_log syslog:server=splunk-dmz.nvthbs.local:21514,facility=local7,tag=nginx custom;

    # copies data between one FD and other from within the kernel
    # faster than read() + write()
    sendfile on;

    # send headers in one piece - more performant
    tcp_nopush on;

    # don't buffer data sent, good for small data bursts in real time
    tcp_nodelay on;

    # enable gzip compression
    gzip on;
    gzip_min_length 1024;
    gzip_comp_level 2;
    gzip_vary on;
    gzip_disable msie6;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types
        # text/html is always compressed by HttpGzipModule
        text/css
        text/javascript
        text/xml
        text/plain
        text/x-component
        application/javascript
        application/x-javascript
        application/json
        application/xml
        application/rss+xml
        application/atom+xml
        font/truetype
        font/opentype
        application/vnd.ms-fontobject
        image/svg+xml;

    # allow the server to close connection on non responding client, this will free up memory
    reset_timedout_connection on;

    # number of requests client can make over keep-alive
    # having high value can be especially beneficial in testing load generation
    # Consider evaluating for production
    keepalive_requests 100000;

    # Set temp paths - need to be explicitly set to /tmp due to permissions
    proxy_temp_path /tmp/proxy_temp;
    client_body_temp_path /tmp/client_temp;
    fastcgi_temp_path /tmp/fastcgi_temp;
    uwsgi_temp_path /tmp/uwsgi_temp;
    scgi_temp_path /tmp/scgi_temp;

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

  server {
    # zone which we want to limit by upper values, we want limit whole server
      limit_conn conn_limit_per_ip 10;
      limit_req zone=req_limit_per_ip burst=10 nodelay;

      listen 8080;
      listen 5000 ssl;
      ssl_certificate    /etc/ssl/crt/tls.crt; 
      ssl_certificate_key    /etc/ssl/key/tls.key;
      ssl_protocols     TLSv1.2;

      default_type application/octet-stream;

      root /usr/share/nginx/apps;

      location / {
        try_files $uri $uri/ /index.html =404;
        add_header 'Access-Control-Allow-Origin' '*' always;
      }

       # To allow POST on static pages
        error_page  405     =200 $uri;
  }
}

如果不使用输出:“导出”,我如何不获取 403 或向 openshift 添加日志记录,或者如何在某处记录 nginx 文件,以便我可以看到它的哪一部分导致了 403。

next.config.js

const nextConfig = {
output: 'export'
distDir: 'dist'
}

module.exports = nextConfig;

Dockerfile

## Stage 0 : Set Base Image and Version ##
## Note: By default, these are pulled from the myorg-images project in the OpenShift repo. 
##       This requires auth orization to OpenShift via a docker login command prior to build.
##       To build from the public Node image, replace the following ARGs and uncomment all
##       segments labeled PUBLIC NODE
##       ARG nodeBaseImage=node
##       ARG nodeBaseVersion=latest
ARG nodeBaseImage=default-route-openshift-image-registry.apps.oscp2.myorg.com/myorg-images/myorg_node
ARG nodeBaseVersion=18.17.1

## Stage 1 : Build ##
FROM ${nodeBaseImage}:${nodeBaseVersion} AS node
LABEL maintainer="DevOps <[email protected]>"
EXPOSE 4200
ARG build=true 

##### PUBLIC NODE #####
## Note: Uncomment the following if using the public, non-myorged node image
##       ENV CHROME_BIN=/usr/bin/chromium-browser
##       ENV SASS_BINARY_NAME=linux-x64-67
##       RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub d| apt-key add - && \
##           echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list && \
##           apt-get update && apt-get install --no-install-recommends -y google-chrome-stable
##       RUN npm install -g next
## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
COPY package.json package-lock.json .npmrc ./
RUN npm ci && mkdir /app && mv ./node_modules ./app
WORKDIR /app
COPY . .

## Build the next app in production mode and store the artifacts in out folder
## Note: Subfolders match the runtimeEnvironment parameter in OpenShift
RUN if [ "$build" = "true" ]; then \
npm run build --output-path=app/Test && \
npm run build --output-path=app/Stage && \
npm run build --output-path=app/Production; fi

### Default entrypoint references start-docker script in package.json
##ENTRYPOINT [ "next", "start" ]
ENTRYPOINT [ "npm", "start", "start-docker" ]

nginx.Dockerfile

## Stage 0 : Set Base Image and Version ##
## Note: nodeImageName and buildID refer to the image produced by the other Dockerfile in this
##       project. nodeImageName is a REQUIRED argument to run this build. ##
##       nginxBaseImage is the Myorged nginx image. This can be replaced with 'nginx' to use
##       the standard public nginx image. This does not include Myorg certificates or OS permissions
ARG nginxBaseImage=default-route-openshift-image-registry.apps.oscp2.myorg.com/myorg-images/myorg_nginx
ARG nodeImageName
ARG buildID=latest
ARG nginxVersion=1.17.10-perl

## STAGE 1: Create Builder Image from app image ##
FROM ${nodeImageName}:${buildID} AS builder

## STAGE 2: Create web server image ##
FROM ${nginxBaseImage}:${nginxVersion} as final
LABEL maintainer="DevOps <[email protected]>"
ENV runtimeEnvironment=Development
EXPOSE 5000
EXPOSE 8080

## Remove default nginx website ##
RUN rm -rf /usr/share/nginx/html


## From ‘builder’ stage copy over the artifacts in dist folder ##
COPY --from=builder /app /usr/share/nginx/app

## From 'builder' stage copy over nginx config file ##
COPY nginx.conf /etc/nginx/nginx.conf

## Set user context to www-data for non OpenShift envs ##
USER www-data

## Container launch command creates symbolic link between environment build and default nginx website ##
CMD ["/bin/bash","-c","ln -s /usr/share/nginx/app/${runtimeEnvironment} /usr/share/nginx/html && nginx -g 'daemon off;'"]
docker nginx next.js openshift
1个回答
0
投票

你有:

[Next.js App] --build--> [Node Docker Container]
       |
       |--copy artifacts--> [NGINX Docker Container]
                                |
                                |--deploy--> [OpenShift Environment]

我将从修改

nginx.conf
文件开始,以正确服务 Next.js 应用程序。确保
root
指令
指向 NGINX 容器中 Next.js 构建工件所在的目录。

要向 OpenShift 添加日志记录并调查 403 错误的原因,请配置 NGINX 将日志写入到您可以访问的路径。例如,将

error_log
access_log
指令设置为文件路径而不是
syslog

server {
    listen 8080;
    listen 5000 ssl;
    ...
    root /usr/share/nginx/app;  # Update this to the correct path of your Next.js build

    location / {
        try_files $uri $uri/ /index.html;  # Make sure this line correctly serves your Next.js app
        ...
    }

    error_log /path/to/your/nginx/error.log warn;  # Update log file paths
    access_log /path/to/your/nginx/access.log warn;
}

在部署之前,使用

nginx -t
测试 NGINX 配置,以确保没有语法错误。

在 NGINX Dockerfile 中,确保

COPY
命令将构建的 Next.js 应用程序从 Node 容器正确传输到 NGINX 容器中的正确目录。

...
## From ‘builder' stage copy over the artifacts in dist folder ##
COPY --from=builder /app/.next /usr/share/nginx/app  # Make sure this path is correct

## From 'builder' stage copy over nginx config file ##
COPY nginx.conf /etc/nginx/nginx.conf
...

如果您不想使用静态导出 (

output: 'export'
),请确保您的 Next.js 应用程序配置为处理服务器端渲染。 NGINX 配置应该指向服务器渲染的页面。

© www.soinside.com 2019 - 2024. All rights reserved.