Skip to content

Commit

Permalink
Fix with-docker-compose example (#43419)
Browse files Browse the repository at this point in the history
1. Fixes example unable to build with the latest version of Next.
- Next.js 13 bumped the minimum React version to [18.2.0](https://nextjs.org/docs/upgrading), but this example seems to have gotten missed.

2. Fixes example unable to run by default on Linux. 
- Reverts #39372 
- Fixes @balazsorban44 comment #39372 (comment)
- Added a comment to the README to prevent this issue from being re-introduced. 

3. Build and start Next.js based on the preferred package manager.

4. Allow dependencies to install without lockfile present. 
- Outputs a warning instead of exiting.  
- Keeps the example faithful to the README "Develop locally without Node.js or TypeScript installed".

5. Added `next.config.js` types that got missed.

6. Updated README links now that output standalone is stable.

## Documentation / Examples

- [X] Make sure the linting passes by running `pnpm build && pnpm lint`
- [X] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
maxproske committed Nov 28, 2022
1 parent 08e6ceb commit d5c922b
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 29 deletions.
35 changes: 21 additions & 14 deletions examples/with-docker-compose/README.md
Expand Up @@ -5,10 +5,9 @@ This example contains everything needed to get a Next.js development and product
## Benefits of Docker Compose

- Develop locally without Node.js or TypeScript installed ✨
- Easy to run, consistent development environment across Mac, Windows, and Linux teams
- Easy to run, consistent development environment across macOS, 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
- Multistage builds combined with [Output Standalone](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files) outputs up to 85% smaller apps (Approximately 110 MB compared to 1 GB with create-next-app)
- Easy configuration with YAML files

## How to use
Expand All @@ -27,6 +26,12 @@ yarn create next-app --example with-docker-compose with-docker-compose-app
pnpm create next-app --example with-docker-compose with-docker-compose-app
```

Optionally, after the installation is complete:

- Run `cd next-app`, then run `npm install` or `yarn install` or `pnpm install` to generate a lockfile.

It is recommended to commit a lockfile to version control. Although the example will work without one, build errors are more likely to occur when using the latest version of all dependencies. This way, we're always using a known good configuration to develop and run in production.

## 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.
Expand All @@ -40,11 +45,13 @@ First, run the development server:
# with each other, by using their container name as a hostname
docker network create my_network

# Build dev using new BuildKit engine
docker compose -f docker-compose.dev.yml build
# Build dev
# Note: Keep v1 command until "Use Docker Compose v2" is enabled by default for Docker Desktop for Linux
# Docker aliases `docker-compose` (v1 command) to `docker compose` (v2 command), but not the other way around
docker-compose -f docker-compose.dev.yml build

# Up dev
docker compose -f docker-compose.dev.yml up
docker-compose -f docker-compose.dev.yml up
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Expand All @@ -53,7 +60,7 @@ You can start editing the page by modifying `pages/index.tsx`. The page auto-upd

## 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.
Multistage builds are highly recommended in production. Combined with the Next [Output Standalone](https://nextjs.org/docs/advanced-features/output-file-tracing#automatically-copying-traced-files) 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).

Expand All @@ -62,11 +69,11 @@ First, run the production server (Final image approximately 110 MB).
# with each other, by using their container name as a hostname
docker network create my_network

# Build prod using new BuildKit engine
docker compose -f docker-compose.prod.yml build
# Build prod
docker-compose -f docker-compose.prod.yml build

# Up prod in detached mode
docker compose -f docker-compose.prod.yml up -d
docker-compose -f docker-compose.prod.yml up -d
```

Alternatively, run the production server without without multistage builds (Final image approximately 1 GB).
Expand All @@ -76,11 +83,11 @@ Alternatively, run the production server without without multistage builds (Fina
# with each other, by using their container name as a hostname
docker network create my_network

# Build prod without multistage using new BuildKit engine
docker compose -f docker-compose.prod-without-multistage.yml build
# Build prod without multistage
docker-compose -f docker-compose.prod-without-multistage.yml build

# Up prod without multistage in detached mode
docker compose -f docker-compose.prod-without-multistage.yml up -d
docker-compose -f docker-compose.prod-without-multistage.yml up -d
```

Open [http://localhost:3000](http://localhost:3000).
Expand All @@ -89,7 +96,7 @@ Open [http://localhost:3000](http://localhost:3000).

```bash
# Stop all running containers
docker kill $(docker ps -q) && docker rm $(docker ps -a -q)
docker kill $(docker ps -aq) && docker rm $(docker ps -aq)

# Free space
docker system prune -af --volumes
Expand Down
17 changes: 15 additions & 2 deletions examples/with-docker-compose/next-app/dev.Dockerfile
Expand Up @@ -8,12 +8,25 @@ 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; \
# Allow install without lockfile, so example works even without Node.js installed locally
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi

COPY src ./src
COPY public ./public
COPY next.config.js .
COPY tsconfig.json .

CMD yarn dev
# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry at run time
# ENV NEXT_TELEMETRY_DISABLED 1

# Note: Don't expose ports here, Compose will handle that for us

# Start Next.js in development mode based on the preferred package manager
CMD \
if [ -f yarn.lock ]; then yarn dev; \
elif [ -f package-lock.json ]; then npm run dev; \
elif [ -f pnpm-lock.yaml ]; then pnpm dev; \
else yarn dev; \
fi
5 changes: 4 additions & 1 deletion examples/with-docker-compose/next-app/next.config.js
@@ -1,3 +1,6 @@
module.exports = {
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
}

module.exports = nextConfig
12 changes: 6 additions & 6 deletions examples/with-docker-compose/next-app/package.json
Expand Up @@ -7,13 +7,13 @@
},
"dependencies": {
"next": "latest",
"react": "18.1.0",
"react-dom": "18.1.0"
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "17.0.42",
"@types/react": "18.0.12",
"@types/react-dom": "18.0.5",
"typescript": "4.7.3"
"@types/node": "^18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"typescript": "^4.9.3"
}
}
Expand Up @@ -9,7 +9,8 @@ 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; \
# Allow install without lockfile, so example works even without Node.js installed locally
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi

COPY src ./src
Expand All @@ -24,9 +25,24 @@ ENV ENV_VARIABLE=${ENV_VARIABLE}
ARG NEXT_PUBLIC_ENV_VARIABLE
ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE}

# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry at build time
# ENV NEXT_TELEMETRY_DISABLED 1

RUN yarn build
# Note: Don't expose ports here, Compose will handle that for us

CMD yarn start
# Build Next.js based on the preferred package manager
RUN \
if [ -f yarn.lock ]; then yarn build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then pnpm build; \
else yarn build; \
fi

# Start Next.js based on the preferred package manager
CMD \
if [ -f yarn.lock ]; then yarn start; \
elif [ -f package-lock.json ]; then npm run start; \
elif [ -f pnpm-lock.yaml ]; then pnpm start; \
else yarn start; \
fi
17 changes: 14 additions & 3 deletions examples/with-docker-compose/next-app/prod.Dockerfile
Expand Up @@ -10,10 +10,10 @@ 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; \
# Allow install without lockfile, so example works even without Node.js installed locally
else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \
fi


COPY src ./src
COPY public ./public
COPY next.config.js .
Expand All @@ -26,10 +26,19 @@ ENV ENV_VARIABLE=${ENV_VARIABLE}
ARG NEXT_PUBLIC_ENV_VARIABLE
ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE}

# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry
# Uncomment the following line to disable telemetry at build time
# ENV NEXT_TELEMETRY_DISABLED 1

RUN yarn build
# Build Next.js based on the preferred package manager
RUN \
if [ -f yarn.lock ]; then yarn build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then pnpm build; \
else yarn build; \
fi

# Note: It is not necessary to add an intermediate step that does a full copy of `node_modules` here

# Step 2. Production image, copy all the files and run next
FROM node:18-alpine AS runner
Expand Down Expand Up @@ -57,4 +66,6 @@ ENV NEXT_PUBLIC_ENV_VARIABLE=${NEXT_PUBLIC_ENV_VARIABLE}
# Uncomment the following line to disable telemetry at run time
# ENV NEXT_TELEMETRY_DISABLED 1

# Note: Don't expose ports here, Compose will handle that for us

CMD node server.js

0 comments on commit d5c922b

Please sign in to comment.