为运行 Nextjs 应用,构建 nginx+nodejs 的基础镜像

478 阅读2分钟

背景

最近公司开始了新的项目,本人负责前端,基于项目是一个门户类型的网站,需要考虑到 seo,单页应用可能不是最优选择,并且为了增加部门的前端技术多样性和促进学习,使用了nextjs 来开发前端。 nextjs 是支持 ssr 的前端框架,默认的构建产物是 nodejs 的代码,而不是静态页面,为了提高访问性能,所以我打算在这个前端服务里,加上 nginx 做静态资源和桶资源,还有请求的代理和缓存。于是我要构建出包含 nginx 和 nodejs 的基础镜像。

要构建出 amd 和 arm 两种平台架构的基础镜像,因为开发环境是 amd64,生产环境是 arm64,这里我就先构建 amd64 的 拉取 nginx 的镜像

docker pull --platform=amd64 nginx

运行镜像

docker run -d nginx

进入镜像

docker exec -it nginx /bin/bash

安装 nodejs

apt update
apt install nodejs npm
exit

导出镜像

docker commit -m 'nginx + nodejs' nginx-nodejs
docker save -o nginx-nodejs.tar nginx-nodejs

这里要注意,如果pull的是nginx:alpine,容器没有/bin/bash命令,要用/bin/sh,后续也打算转为 alpine 镜像,降低镜像的体积。

docker exec -it nginx /bin/sh
apk update
apk add nodejs npm
# 其余步骤一致

安装完成后可以在容器内使用node -v来校验 nodejs 是否安装成功

完成上面的步骤,一个 nginx+nodejs 的基础镜像就已经构建好了,接下来参考 nextjs 给出的 dockerfile 模板nextjs-with-docker,将镜像换成我们自己构建的基础镜像。

Dockerfile 模板参考。 注意 16行的基础镜像要换成构建好的 nginx-nodejs 镜像。

FROM node:18-alpine as base
FROM base as deps
WORKDIR /app
COPY package.json ./
RUN npm i

FROM base as builder

WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npm run build

# 这里换成构建好的 nginx+nodejs 镜像
FROM nginx_nodejs
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


# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
RUN chown nextjs:nodejs /usr/share/nginx

RUN chmod -R 777 /var/run/nginx.pid

# 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 80 3000

ENV PORT 3000
# set hostname to localhost
ENV HOSTNAME "0.0.0.0"

CMD node server.js && nginx -g 'daemon off;'

注意next.config.js要把 output改成standlone 接下来 build 好这个镜像,运行镜像

docker build -t nginx-nextjs .
docker run -d -p 3000:3000 -p 80:80 nginx-nextjs

就可以在本地中访问nextjs 服务和 nginx 服务了。地址分别是 http://localhost:3000http://localhost

后续准备好 nginx 的配置文件,代理好 nextjs 服务和静态资源,只放出 80 端口就行。