背景
最近公司开始了新的项目,本人负责前端,基于项目是一个门户类型的网站,需要考虑到 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:3000 和http://localhost 。
后续准备好 nginx 的配置文件,代理好 nextjs 服务和静态资源,只放出 80 端口就行。