Docker
你可以将这个 stack 容器化,将它作为一个单独容器使用 Docker 来部署,或者作为一系列容器的部分,使用 docker-compose 来部署。参看基于本文档的示例仓库 ajcwebdev/ct3a-docker
↗。
Docker 项目配置
请注意 Next.js 会针对编译时客户端的环境变量(在客户端,名称前缀含有 NEXT_PUBLIC
) 和运行时环境的服务器端变量有不同的处理过程。在本次演示中我们将使用两个环境变量,请注意它们在 Dockerfile
文件中的位置、命令行参数以及文件 docker-compose.yml
:
DATABASE_URL
(被用于服务器端)NEXT_PUBLIC_CLIENTVAR
(被用于客户端)
1. Next 的配置
在你的 next.config.js
↗ 文件里,添加构建输出选项 standalone
,以自动借助追踪输出文件来降低镜像文件的大小↗:
export default defineNextConfig({
reactStrictMode: true,
swcMinify: true,
+ output: "standalone",
});
2. 创建 dockerignore 文件
点击这里并将下方内容添加到 .dockerignore
里:
.env
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
3. 创建 Dockerfile
因为我们并没有将服务端环境变量导入到我们的容器里,因此 环境变量的 schema 验证 肯定不会通过。为了防止这种情况发生,我们必须在构建命令中添加
SKIP_ENV_VALIDATION=1
标识,以便 env-schema 不会在编译时被验证。
点击这里并将下方内容添加到 Dockerfile
里:
##### DEPENDENCIES
FROM --platform=linux/amd64 node:16-apline3.17 AS deps
RUN apk add --no-cache libc6-compat openssl
WORKDIR /app
# 安装 Prisma 客户端 - 如果不需要 Prisma,移除下一行
COPY prisma ./
# 使用 PNPM 包管理工具安装依赖包
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \
else echo "Lockfile not found." && exit 1; \
fi
##### BUILDER
FROM --platform=linux/amd64 node:16-apline3.17 AS builder
ARG DATABASE_URL
ARG NEXT_PUBLIC_CLIENTVAR
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
##### RUNNER
FROM --platform=linux/amd64 node:16-apline3.17 AS runner
WORKDIR /app
ENV NODE_ENV production
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
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
CMD ["node", "server.js"]
注意
- 在迁移到 Node 18 后,可能就没有必要再使用
--platform=linux/amd64
了。- 参看
node:alpine
↗ 来了解为什么使用libc6-compat
- Next.js 会收集 关于使用情况的匿名观测数据↗。取消注释第一个
ENV NEXT_TELEMETRY_DISABLED 1
,以在构建过程中关闭该观测功能。取消注释第二个ENV NEXT_TELEMETRY_DISABLED 1
以关闭在运行时的观测功能。
在本地构建和运行镜像
通过下方命令在本地构建和运行该镜像:
docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
在浏览器中访问 localhost:3000↗ 来查看运行的应用。
Docker Compose
你也可以使用 Docker Compose 来创建镜像以运行容器。
遵循以上 1 - 4 的步骤,点击这里,将下方内容添加到 docker-compose.yml
里:
version: "3.9"
services:
app:
platform: "linux/amd64"
build:
context: .
dockerfile: Dockerfile
args:
NEXT_PUBLIC_CLIENTVAR: "clientvar"
working_dir: /app
ports:
- "3000:3000"
image: t3-app
environment:
- DATABASE_URL=database_url_goes_here
命令行运行 docker compose up
:
docker compose up
在浏览器中访问 localhost:3000↗ 来查看运行的应用。
部署到 Railway
你可以使用 PaaS(平台即服务)工具,例如 Railway’s↗,自动完成 Dockerfile 部署↗ 来部署你的应用。如果你已经 安装了 Railway CLI 命令行工具↗,你可以使用下方命令来部署你的应用:
railway login
railway init
railway link
railway up
railway open
前往 “Variables”,填入你的 DATABASE_URL
。然后前往 “Settings” 里,选择 “Generate Domain”。访问 ct3a-docker.up.railway.app↗ 来查看托管在 Railway 上的项目。
有用的资源
资源 | 链接 |
---|---|
Dockerfile 参考手册 | https://docs.docker.com/engine/reference/builder/↗ |
Compose file 第三版参考手册 | https://docs.docker.com/compose/compose-file/compose-file-v3/↗ |
Docker CLI 命令行工具参考手册 | https://docs.docker.com/engine/reference/commandline/docker/↗ |
Docker Compose CLI 命令行工具参考手册 | https://docs.docker.com/compose/reference/↗ |
使用 Docker 镜像 部署 Next.js | https://nextjs.org/docs/deployment#docker-image↗ |
Docker 中的 Next.js | https://benmarte.com/blog/nextjs-in-docker/↗ |
Next.js 搭配 Docker 示例 | https://github.com/vercel/next.js/tree/canary/examples/with-docker↗ |
创建一个 Next.js 应用的 Docker 镜像 | https://blog.tericcabrel.com/create-docker-image-nextjs-application/↗ |