-
Notifications
You must be signed in to change notification settings - Fork 26.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add with-docker-compose example (#32668)
`with-docker-compose` contains everything needed to get Next.js up and running with Docker Compose. This example aims to provide an easy-to-use, Next.js app development and production environment, **all without Node.js being installed** on the host machine. This ensures a consistent development environment across Windows, MacOS, and Linux teams. I was inspired to create this, because the existing [with-docker](https://github.com/vercel/next.js/tree/canary/examples/with-docker) example only uses Docker to build the final production artifacts, not provide a development environment. Docker Compose easily syncs changes with containers for Hot Reloading, parallel builds, and networking, making it a powerful and consistent development tool. Developers can **easily extend this example** by modifying the YAML files to include Nginx, Postgres, and other Docker images. This example takes advantage of Docker multistage builds combined with the Next 12.1 [Output Standalone](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files-experimental) feature, to create up to **80% smaller apps** (Approximately 110 MB compared to 1 GB with create-next-app). I also included an example without multistage builds, for developers who don't want to get into the weeds. I have been tweaking this Docker Compose setup over 3 years of real world use, but please let me know if anything can be improved.
- Loading branch information
Showing
21 changed files
with
611 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# DO NOT ADD SECRETS TO THIS FILE. This is a good place for defaults. | ||
# If you want to add secrets use `.env.production.local` instead, which is automatically detected by docker-compose. | ||
|
||
ENV_VARIABLE=production_server_only_variable | ||
NEXT_PUBLIC_ENV_VARIABLE=production_public_variable |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# vercel | ||
.vercel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# With Docker Compose | ||
|
||
This example contains everything needed to get a Next.js development and production environment up and running with Docker Compose. | ||
|
||
## Benfits of Docker Compose | ||
|
||
- Develop locally without Node.js or TypeScript installed ✨ | ||
- Easy to run, consistent development environment across Mac, Windows, and Linux teams | ||
- Run multiple Next.js apps, databases, and other microservices in a single deployment | ||
- Multistage builds combined with [Output Standalone](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files-experimental) outputs up to 85% smaller apps (Approximately 110 MB compared to 1 GB with create-next-app) | ||
- BuildKit engine builds multiple Docker images in parallel | ||
- Easy configuration with YAML files | ||
|
||
## How to use | ||
|
||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example: | ||
|
||
```bash | ||
npx create-next-app --example with-docker-compose with-docker-compose-app | ||
# or | ||
yarn create next-app --example with-docker-compose with-docker-compose-app | ||
# or | ||
pnpm create next-app --example with-docker-compose with-docker-compose-app | ||
``` | ||
|
||
## Prerequisites | ||
|
||
Install [Docker Desktop](https://docs.docker.com/get-docker) for Mac, Windows, or Linux. Docker Desktop includes Docker Compose as part of the installation. | ||
|
||
## Development | ||
|
||
First, run the development server: | ||
|
||
```bash | ||
# Create a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
docker network create my_network | ||
|
||
# Build dev using new BuildKit engine | ||
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.dev.yml build --parallel | ||
|
||
# Up dev | ||
docker-compose -f docker-compose.dev.yml up | ||
``` | ||
|
||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. | ||
|
||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. | ||
|
||
## Production | ||
|
||
Multistage builds are highly recommended in production. Combined with the Next 12 [Output Standalone](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files-experimental) feature, only `node_modules` files required for production are copied into the final Docker image. | ||
|
||
First, run the production server (Final image approximately 110 MB). | ||
|
||
```bash | ||
# Create a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
docker network create my_network | ||
|
||
# Build prod using new BuildKit engine | ||
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.prod.yml build --parallel | ||
|
||
# Up prod in detached mode | ||
docker-compose -f docker-compose.prod.yml up -d | ||
``` | ||
|
||
Alternatively, run the production server without without multistage builds (Final image approximately 1 GB). | ||
|
||
```bash | ||
# Create a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
docker network create my_network | ||
|
||
# Build prod without multistage using new BuildKit engine | ||
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose -f docker-compose.prod-without-multistage.yml build --parallel | ||
|
||
# Up prod without multistage in detached mode | ||
docker-compose -f docker-compose.prod-without-multistage.yml up -d | ||
``` | ||
|
||
Open [http://localhost:3000](http://localhost:3000). | ||
|
||
## Useful commands | ||
|
||
```bash | ||
# Stop all running containers | ||
docker kill $(docker ps -q) && docker rm $(docker ps -a -q) | ||
|
||
# Free space | ||
docker system prune -af --volumes | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
version: '3' | ||
|
||
services: | ||
next-app: | ||
container_name: next-app | ||
build: | ||
context: ./next-app | ||
dockerfile: dev.Dockerfile | ||
environment: | ||
ENV_VARIABLE: ${ENV_VARIABLE} | ||
NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE} | ||
volumes: | ||
- ./next-app/src:/app/src | ||
- ./next-app/public:/app/public | ||
restart: always | ||
ports: | ||
- 3000:3000 | ||
networks: | ||
- my_network | ||
|
||
# Add more containers below (nginx, postgres, etc.) | ||
|
||
# Define a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
networks: | ||
my_network: | ||
external: true |
24 changes: 24 additions & 0 deletions
24
examples/with-docker-compose/docker-compose.prod-without-multistage.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
version: '3' | ||
|
||
services: | ||
next-app: | ||
container_name: next-app | ||
build: | ||
context: ./next-app | ||
dockerfile: prod-without-multistage.Dockerfile | ||
args: | ||
ENV_VARIABLE: ${ENV_VARIABLE} | ||
NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE} | ||
restart: always | ||
ports: | ||
- 3000:3000 | ||
networks: | ||
- my_network | ||
|
||
# Add more containers below (nginx, postgres, etc.) | ||
|
||
# Define a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
networks: | ||
my_network: | ||
external: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
version: '3' | ||
|
||
services: | ||
next-app: | ||
container_name: next-app | ||
build: | ||
context: ./next-app | ||
dockerfile: prod.Dockerfile | ||
args: | ||
ENV_VARIABLE: ${ENV_VARIABLE} | ||
NEXT_PUBLIC_ENV_VARIABLE: ${NEXT_PUBLIC_ENV_VARIABLE} | ||
restart: always | ||
ports: | ||
- 3000:3000 | ||
networks: | ||
- my_network | ||
|
||
# Add more containers below (nginx, postgres, etc.) | ||
|
||
# Define a network, which allows containers to communicate | ||
# with each other, by using their container name as a hostname | ||
networks: | ||
my_network: | ||
external: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# vercel | ||
.vercel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
FROM node:18-alpine | ||
|
||
WORKDIR /app | ||
|
||
# Copy lock files if file exists | ||
COPY package.json yarn.lock* package-lock.json* . | ||
|
||
RUN yarn install | ||
|
||
COPY src ./src | ||
COPY public ./public | ||
COPY next.config.js . | ||
COPY tsconfig.json . | ||
|
||
CMD yarn dev |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/basic-features/typescript for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
experimental: { | ||
outputStandalone: true, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"private": true, | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start" | ||
}, | ||
"dependencies": { | ||
"next": "latest", | ||
"react": "18.1.0", | ||
"react-dom": "18.1.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "17.0.42", | ||
"@types/react": "18.0.12", | ||
"@types/react-dom": "18.0.5", | ||
"typescript": "4.7.3" | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
examples/with-docker-compose/next-app/prod-without-multistage.Dockerfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
FROM node:18-alpine | ||
|
||
WORKDIR /app | ||
|
||
# Copy lock files if file exists | ||
COPY package.json yarn.lock* package-lock.json* . | ||
|
||
# Omit --production flag for TypeScript devDependencies | ||
RUN yarn install | ||
|
||
COPY src ./src | ||
COPY public ./public | ||
COPY next.config.js . | ||
COPY tsconfig.json . | ||
|
||
# Environment variables must be present at build time | ||
# https://github.com/vercel/next.js/discussions/14030 | ||
ARG ENV_VARIABLE | ||
ENV ENV_VARIABLE=${ENV_VARIABLE} | ||
ARG NEXT_PUBLIC_ENV_VARIABLE | ||
ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE} | ||
|
||
# Uncomment the following line to disable telemetry at build time | ||
# ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
||
RUN yarn build | ||
|
||
CMD yarn start |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Step 1. Rebuild the source code only when needed | ||
FROM node:18-alpine AS builder | ||
|
||
WORKDIR /app | ||
|
||
# Copy lock files if file exists | ||
COPY package.json yarn.lock* package-lock.json* . | ||
|
||
# Omit --production flag for TypeScript devDependencies | ||
RUN yarn install | ||
|
||
COPY src ./src | ||
COPY public ./public | ||
COPY next.config.js . | ||
COPY tsconfig.json . | ||
|
||
# Environment variables must be present at build time | ||
# https://github.com/vercel/next.js/discussions/14030 | ||
ARG ENV_VARIABLE | ||
ENV ENV_VARIABLE=${ENV_VARIABLE} | ||
ARG NEXT_PUBLIC_ENV_VARIABLE | ||
ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE} | ||
|
||
# Uncomment the following line to disable telemetry at build time | ||
# ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
||
RUN yarn build | ||
|
||
# Step 2. Production image, copy all the files and run next | ||
FROM node:18-alpine AS runner | ||
|
||
WORKDIR /app | ||
|
||
# Don't run production as root | ||
RUN addgroup --system --gid 1001 nodejs | ||
RUN adduser --system --uid 1001 nextjs | ||
USER nextjs | ||
|
||
COPY --from=builder /app/public ./public | ||
COPY --from=builder /app/next.config.js . | ||
COPY --from=builder /app/package.json . | ||
|
||
# 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 | ||
|
||
# Environment variables must be redefined at run time | ||
ARG ENV_VARIABLE | ||
ENV ENV_VARIABLE=${ENV_VARIABLE} | ||
ARG NEXT_PUBLIC_ENV_VARIABLE | ||
ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE} | ||
|
||
# Uncomment the following line to disable telemetry at run time | ||
# ENV NEXT_TELEMETRY_DISABLED 1 | ||
|
||
CMD node server.js |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import '../styles/globals.css' | ||
import type { AppProps } from 'next/app' | ||
|
||
export default function MyApp({ Component, pageProps }: AppProps) { | ||
return <Component {...pageProps} /> | ||
} |
Oops, something went wrong.