NextJS
This guide explains how to wrap your Next.js application into a Docker image and configure environment variables effectively. Whether you're managing client-side or server-side variables, this document covers the key concepts and provides practical examples to streamline your setup.
Key concepts
Build-time variables (client-side)
- Prefix: Variables prefixed with
NEXT_PUBLIC_
(e.g.,NEXT_PUBLIC_API_URL
). - Behavior: These variables are embedded into the client-side JavaScript bundle during the
next build
process. - Availability: They are accessible in client-side code (e.g., React components) via
process.env
. - Limitation: They cannot be provided at runtime—they must be defined at build time. If set only during the next start, they won’t be available in the client bundle.
- Best Practice: Store these variables in your GitHub repository’s environment variables or define them in your GitHub Actions workflow to ensure they’re injected during the build.
Run-time variables (server-side)
- Prefix: Variables without the
NEXT_PUBLIC_
prefix (e.g.,DATABASE_URL
). - Behavior: These are only available in server-side contexts (e.g., API routes,
getServerSideProps
, or Server Components in the App Router). - Availability: They can be injected at runtime and accessed via
process.env
in server-side code.
info
For more information on the environment variables, you can check NextJS official documentation here.
Setting up environment variables
For server-side variables
- Define your server-side variables (e.g.,
DATABASE_URL
,API_SECRET
) using the Kapstan UI. - Kapstan will securely inject these variables into your application at runtime.
- Access them in your server-side code like this
// Example: API route
export default function handler(req, res) {
const dbUrl = process.env.DATABASE_URL; // Injected by Kapstan
res.status(200).json({ message: `Connected to ${dbUrl}` });
}
For client-side variables
- Define
NEXT_PUBLIC_
variables in your build environment (e.g., GitHub repository variables or GitHub Actions workflow). - These variables will be embedded into the client-side bundle during next build.
- Example usage in a React component:
// pages/index.js
export default function Home() {
return (
<div>
<h1>{process.env.NEXT_PUBLIC_APP_NAME}</h1>
<p>API: {process.env.NEXT_PUBLIC_API_URL}</p>
</div>
);
}
Script to trigger this docker build in the GitHub action
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: |
docker build \
--build-arg NEXT_PUBLIC_APP_NAME=${{ vars.NEXT_PUBLIC_APP_NAME }} \
--build-arg NEXT_PUBLIC_API_URL=${{ vars.NEXT_PUBLIC_API_URL }} \
-t my-next-app .
Building a docker image
Below is a sample Dockerfile to containerize your Next.js application with environment variable support.
Sample Dockerfile
# Build stage
FROM node:18-alpine AS builder
# Set working directory
WORKDIR /app
# Copy package.json and lock the file
COPY package.json package-lock.json* ./
# Install dependencies
RUN npm ci
# Copy application code
COPY . .
# Define build-time arguments for NEXT_PUBLIC_ variables
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_APP_NAME
# Set environment variables for the build
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_APP_NAME=$NEXT_PUBLIC_APP_NAME
# Build the Next.js app
RUN npm run build
# Production stage
FROM node:18-alpine AS runner
WORKDIR /app
# Copy only necessary files from the builder stage
COPY --from=builder /app/package.json ./
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/node_modules ./node_modules
# The below file can also be `next.config.mjs` depending on the project
COPY --from=builder /app/next.config.js ./
# Expose port
EXPOSE 3000
# Start the app
CMD ["npm", "start"]
Building the docker image
Run the following command to build your Docker image, passing NEXT_PUBLIC_
variables as build arguments:
docker build \
--build-arg NEXT_PUBLIC_API_URL=https://api.example.com \
--build-arg NEXT_PUBLIC_APP_NAME=MyApp \
-t my-next-app .
Summary
- Client-Side (
NEXT_PUBLIC_
): Define at build time using GitHub variables or build arguments. Embedded in the client bundle. - Server-Side: Inject at runtime using Kapstan. Available only server-side.
- Docker: Use the provided Dockerfile and build/run commands to containerize your app with variables.
This setup ensures a secure, scalable, and maintainable approach to managing environment variables in your Next.js application.