首页 前端知识 Docker Nginx部署Next.js实践

Docker Nginx部署Next.js实践

2025-03-19 11:03:38 前端知识 前端哥 928 174 我要收藏

背景

Next.js有很多种部署方式,在最近的项目中,我选择了如下部署方案:

第一步使用Docker通过Node server部署Next.js应用,第二步使用Docker部署Nginx作为反向代理,转发请求并安装SSL证书支持https访问。

部署步骤

1. 环境准备

我这套部署方案基于CentOS7,需要的软件和前期准备工作如下:

  • docker:容器化部署。1. 安装方式
  • git:每次部署前先从github拉取最新代码。1. 安装方式
  • acme.sh:签发和部署SSL证书以支持HTTPS访问。1. 安装方式,2. SSL证书签发

2. 制作镜像

需要制作两份镜像,一个是Next.js应用的镜像,另一个是Nginx镜像。涉及到的Dockerfile如下:

Next.js Dockerfile:

# syntax=docker.io/docker/dockerfile:1

FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json pnpm-lock.yaml* ./
RUN corepack enable pnpm && pnpm i --frozen-lockfile

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED=1

RUN corepack enable pnpm && pnpm run build; 

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED=1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000

# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
复制

Nginx Dockerfile:

FROM nginx:1.27.3

EXPOSE 80
EXPOSE 443
复制

3. Nginx配置

Nginx.conf:

events {
}

http {
    upstream nextjs {
        #  in Docker Compose, services run in separate containers and need to reference each other by their service names
        server nextjs:3000;
    }

    server {
        listen       80;
        listen  [::]:80;
        server_name  easynomad.cn www.easynomad.cn;

        #80跳转到443
        rewrite ^(.*)$ https://${server_name}$1 permanent;
    }

    server {
        listen 443 ssl;
        server_name  easynomad.cn www.easynomad.cn;

        ssl_certificate          /etc/nginx/ssl/easynomad.cn/full.pem;
        ssl_certificate_key      /etc/nginx/ssl/easynomad.cn/key.pem;

        ssl_session_timeout  5m;
        ssl_session_cache shared:SSL:10m;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
        ssl_protocols TLSv1.3 TLSv1.2;
        ssl_prefer_server_ciphers on;
        
        #开启HSTS
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

        location /api/ {
            proxy_pass 后端接口地址;
        }

        location / {
            proxy_pass http://nextjs;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
复制

4. Docker Compose配置

services:
nextjs:
image: nextjs:latest
container_name: nextjs
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- "3000:3000"
restart: always
nginx:
image: nginx:latest
container_name: nginx
labels:
- sh.acme.autoload.domain=easynomad.cn
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
ports:
- "80:80"
- "443:443"
restart: always
复制

5. 完整的部署脚本

部署脚本的整体流程如下,每次只需要在服务器直接运行脚本就可以完成部署:

  1. 从github获取最新代码
  2. 分别打包Next.js和Nginx镜像
  3. 通过docker compose运行容器
  4. 更新Nginx配置
  5. 安装SSL证书
#!/bin/sh
# step 1: download code from github
rm -rf easynomad-frontend
echo ">>>> original code dir deleted"
git clone https://${GIT_TOKEN}@github.com/xx/xxxx.git
cd easynomad-frontend
# step 2: build images
docker build --tag nextjs:latest -f Dockerfile .
echo ">>>> build nextjs image finished"
docker build --tag nginx:latest -f ./src/nginx/Dockerfile .
echo ">>>> build nginx image finished"
# step 3: 运行容器
docker compose down
docker compose up -d
# step 4: 更新nginx配置,使其覆盖原有配置
sleep 6s
# /etc/nginx/nginx.conf是主要配置文件,/etc/nginx/conf.d/nginx.conf是副配置文件
docker cp ./src/nginx/nginx.conf nginx:/etc/nginx/nginx.conf
echo ">>>> nginx.conf updated!"
# step 5:安装SSL证书
# The label value to find the container
export DEPLOY_DOCKER_CONTAINER_LABEL=sh.acme.autoload.domain=easynomad.cn
# The target file path in the container.
# The files will be copied to the position in the container.
export DEPLOY_DOCKER_CONTAINER_KEY_FILE="/etc/nginx/ssl/easynomad.cn/key.pem"
export DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/ssl/easynomad.cn/cert.pem"
export DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/ssl/easynomad.cn/ca.pem"
export DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/ssl/easynomad.cn/full.pem"
# The command to reload the service in the container.
export DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
sleep 2s
/root/.acme.sh/acme.sh --deploy --deploy-hook docker -d easynomad.cn
echo ">>>> SSL cert deployed!"
复制

最后,这个项目是我独立开发的一个远程工作聚合网站,对远程工作感兴趣的小伙伴可以进来看看:轻松游牧

转载请注明出处或者链接地址:https://www.qianduange.cn//article/24047.html
标签
评论
发布的文章

动态规划感悟1

2025-03-20 12:03:52

华为NAS真实测评!

2025-03-20 12:03:52

Java设计模式之代理模式

2025-03-20 12:03:51

Linux 锁、线程同步

2025-03-20 12:03:48

大家推荐的文章
会员中心 联系我 留言建议 回顶部
娴忚鍣ㄥ崌绾ф彁绀猴細鎮ㄧ殑娴忚鍣ㄧ増鏈緝浣庯紝寤鸿鎮ㄧ珛鍗冲崌绾т负鐭ヤ簡鏋侀€熸祻瑙堝櫒锛屾瀬閫熴€佸畨鍏ㄣ€佺畝绾︼紝涓婄綉閫熷害鏇村揩锛�绔嬪嵆涓嬭浇
复制成功!