【问题标题】:Is there a way to use nextjs with docker and nginx有没有办法将 nextjs 与 docker 和 nginx 一起使用
【发布时间】:2020-12-16 21:43:57
【问题描述】:

我有一个希望使用 Docker 和 nginx 运行的 nextjs 项目。

我希望使用在后台连接nextjs的nginx(只有nginx可以与nextjs对话,用户需要与nginx对话才能与nextjs对话)。

假设它是标准的nextjs项目结构和dockerfile内容(如下提供),有没有办法在docker中使用nginx和nextjs?

我知道我可以使用 Docker-compose。但我想把它放在一个 docker 图像下。由于我打算将图像推送到 heroku 虚拟主机。

注意:我正在使用服务器端渲染

码头文件

# Base on offical Node.js Alpine image
FROM node:latest as builder

# Set working directory
WORKDIR /usr/app

# install node-prune (https://github.com/tj/node-prune)
RUN curl -sfL https://install.goreleaser.com/github.com/tj/node-prune.sh | bash -s -- -b /usr/local/bin

# Copy package.json and package-lock.json before other files
# Utilise Docker cache to save re-installing dependencies if unchanged
COPY package.json ./
COPY yarn.lock ./

# Install dependencies
RUN yarn install --frozen-lockfile

# Copy all files
COPY ./ ./

# Build app
RUN yarn build

# remove development dependencies
RUN yarn install --production

# run node prune. Reduce node_modules size
RUN /usr/local/bin/node-prune

####################################################### 

FROM node:alpine

WORKDIR /usr/app

# COPY package.json next.config.js .env* ./
# COPY --from=builder /usr/app/public ./public
COPY --from=builder /usr/app/.next ./.next
COPY --from=builder /usr/app/node_modules ./node_modules

EXPOSE 3000

CMD ["node_modules/.bin/next", "start"]

dockerfile 灵感来自https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile.multistage

编辑:nginx default.conf

upstream nextjs_upstream {
  server nextjs:3000;

  # We could add additional servers here for load-balancing
}

server {
  listen 80 default_server;

  server_name _;

  server_tokens off;

  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection 'upgrade';
  proxy_set_header Host $host;
  proxy_cache_bypass $http_upgrade;

  location / {
    proxy_pass http://nextjs_upstream;
  }
}

【问题讨论】:

  • 我不知道nextjs,但是如果它在服务器端做东西并且你想把它隐藏在nginx后面,那么让nextjs只在你不知道的内部端口上监听localhost从 docker 镜像中导出,只让 nginx 监听导出的端口并转发到内部端口。见stackoverflow.com/questions/5009324/node-js-nginx-what-now?rq=1
  • 这就是我所看到的。在 3000 端口运行 NextJS,让 nginx 端口转发到 NextJS。但我不知道如何在 Docker 中做到这一点。
  • 由于在上面的示例中,nginx 在端口 80 上运行,因此您必须 EXPOSE 80。然后当你运行容器时,你需要告诉 docker 将该端口 80 绑定到哪里。前任docker run -p 80:80 <image name> 会告诉 docker 使暴露的端口 80(在 docker 容器上)在端口 80(在主机上)可用。

标签: docker nginx next.js


【解决方案1】:

为了能够在单个 Docker 容器中同时使用 Nginx 和 NextJS,无需使用 Docker-Compose,您需要使用 Supervisord

Supervisor 是一个客户端/服务器系统,允许其用户控制 类 UNIX 操作系统上的许多进程。

问题不在于 nginx 配置或 dockerfile。启动容器时它同时运行 nginx 和 nextjs。由于我找不到同时运行这两种方法的方法,因此使用 supervisord 是我需要的工具。

它的工作需要以下内容

Dockerfile

# Base on offical Node.js Alpine image
FROM node:latest as builder

# Set working directory
WORKDIR /usr/app

# Copy package.json and package-lock.json before other files
# Utilise Docker cache to save re-installing dependencies if unchanged
COPY package.json ./
COPY yarn.lock ./

# Install dependencies
RUN yarn install --frozen-lockfile

# Copy all files
COPY ./ ./

# Build app
RUN yarn build

# remove development dependencies
RUN yarn install --production

####################################################### 

FROM nginx:alpine

WORKDIR /usr/app

RUN apk add nodejs-current npm supervisor
RUN mkdir mkdir -p /var/log/supervisor && mkdir -p /etc/supervisor/conf.d

# Remove any existing config files
RUN rm /etc/nginx/conf.d/*

# Copy nginx config files
# *.conf files in conf.d/ dir get included in main config
COPY ./.nginx/default.conf /etc/nginx/conf.d/

# COPY package.json next.config.js .env* ./
# COPY --from=builder /usr/app/public ./public
COPY --from=builder /usr/app/.next ./.next
COPY --from=builder /usr/app/node_modules ./node_modules

# supervisor base configuration
ADD supervisor.conf /etc/supervisor.conf

# replace $PORT in nginx config (provided by executior) and start supervisord (run nextjs and nginx)
CMD sed -i -e 's/$PORT/'"$PORT"'/g' /etc/nginx/conf.d/default.conf && \
  supervisord -c /etc/supervisor.conf

supervisor.conf

[supervisord]
nodaemon=true

[program:nextjs]
directory=/usr/app
command=node_modules/.bin/next start
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=true

[program:nginx]
command=nginx -g 'daemon off;'
killasgroup=true
stopasgroup=true
redirect_stderr=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=true

nginx 配置(default.conf)

upstream nextjs_upstream {
  server localhost:3000;

  # We could add additional servers here for load-balancing
}

server {
  listen $PORT default_server;

  server_name _;

  server_tokens off;

  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection 'upgrade';
  proxy_set_header Host $host;
  proxy_cache_bypass $http_upgrade;

  location / {
    proxy_pass http://nextjs_upstream;
  }
}

注意:使用 nginx 作为反向代理。 NextJS 将在端口 3000 上运行。用户将无法直接访问它。它必须通过nginx。


构建docker镜像

docker build -t nextjs-img -f ./dockerfile .

运行 docker 容器

docker run --rm -e 'PORT=80' -p 8080:80 -d --name nextjs-img nextjs-img:latest

转到localhost:8080

【讨论】:

    【解决方案2】:

    您可以使用docker-compose 在 Docker 容器中运行 Nginx 和 NextJS 应用程序,然后在这些容器之间建立一个桥接网络。

    然后在 nginx 配置中:

    server {
        listen       80;
        listen       443 ssl;
    
        server_name localhost [dns].com;
    
        ssl_certificate certs/cert.pem;
        ssl_certificate_key certs/cert.key;
    
        location / {
            proxy_pass http://nextApplication; // name based on your docker-compose file
            proxy_http_version 1.1;
            proxy_read_timeout      90;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host [dns].com;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    我没有使用upstream 脚本,负载均衡器位于 nginx 之上(在云提供商级别)

    【讨论】:

    • 有没有办法让它在不使用 docker compose 的情况下工作?
    猜你喜欢
    • 2020-11-05
    • 2018-03-15
    • 2016-11-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多