create-next-app CLI tool provided by Next.js.
Generate the Next.js app
We’ll assume you have NodeJS installed already and can runnpx. Refer to the documentation if you would like to use yarn, pnpm or bun.
Now let’s create a new project by running the create-next-app. This will scaffold a new project asking you if you’d like to set up some basic tooling such as TypeScript.
cd hello-nextjs && npm run dev and access it at http://localhost:3000.
Deploy to Fly.io
First, install flyctl, the Fly.io CLI, and sign up to Fly.io if you haven’t already. Now let’s launch your Next.js app from the root of your application.fly apps open to see your deployed app in action.
Try a few other commands:
fly logs- Tail your application logsfly status- View your app’s current deployment statusfly ssh console- Open a terminal on your VMfly deploy- Deploy the application after making changes
fly.toml and Dockerfile in the root of the project. Change them if you need to customize your deployment.
The following sections cover further steps you can apply for your Next.js app deployment.
Standalone builds (recommended)
To reduce the size of the final image deployed to Fly.io, we recommend using the standalone output in yournext.config.js (or next.config.mjs) file:
fly launch or using the Dockerfile generator, if this "standalone" value is set in your Next config, your Dockerfile will be updated such that only the files necessary for a production environment will be used in the final image. Using the standalone setting and updating your Dockerfile can reduce your total image size by ~400mb, so we highly recommend this approach!
You can also manually update your Dockerfile to accommodate a standalone Next.js app. After running the build script (npm run build), there should typically be a final COPY instruction towards the end of one’s Dockerfile. Replace that with the following:
CMD to the following:
Generating your Next.js Dockerfile
While you’re welcome to write your own Dockerfile, the easiest way to get started with this is to use the Dockerfile generator. Once installed, it can be run usingnpx @flydotio/dockerfile for Node applications or bunx @flydotio/dockerfile for Bun applications. You’ll see it referenced throughout this article for various use cases.
Connecting to databases
Unlike some other frameworks, Next.js does not bundle a database adapter. Instead, you are free to choose the ORM or node module you wish. Fly.io will provide aDATABASE_URL that you can use at runtime to
connect to your database. How you will use this will depend on the
database module you choose. Prisma is
a popular choice, and connecting to your database using Prisma is done
through your prisma/schema.prisma file. An example:
Build time secrets
This approach allows you to inject secrets (such as database URLs) that are only available at build time.This approach will not work for SQLite3, as the build Machine still won’t have access to your volume. However, it can be used with PostgreSQL, MySQL and other such databases.
DATABASE_URL. If you don’t know the value of this
secret, fly console and printenv DATABASE_URL can obtain this value
for you.
Next, you need to modify your Dockerfile to mount a secret. The easiest way to do this is using the Dockerfile generator, like so:
Deferring static site generation
An alternate approach, one that works with SQLite3 too, is to defer the running of the build step to just after deployment before your web server is started. The upside is that your build has full access to all of your deployment secrets and environment variables. This involves replacing the entry point in your Dockerfile (typically yourCMD) with a script
and having that script run npm build (or equivalent) prior to starting
your server.
You can let the Dockerfile generator take care of these
changes for you:
- Your deployment Machines will need enough memory to run a build. See:
fly scale memoryandswap_size_mbfor two options. - You may need to adjust the grace_period for any HTTP service checks.
- If you are only running one Machine there will be a period of time where your server is inaccessible while the site is being statically generated.
- If you run multiple Machines, the static site generation will be run on each increasing the total time before any changes are fully deployed.
Exposing environment variables to the browser
If you’re a Next.js user you might know that it supports exposing environment variables to the browser using variables with names starting withNEXT_PUBLIC_. These variables are fixed at build time, and unlike runtime environment variables (which are only available on the server), they can’t be changed unless the application is built again.
In order to make these NEXT_PUBLIC_ variables available, you can add them as ARG variables in your Dockerfile, as seen in the example below. This should come after any actual build steps (if you’ve used the Dockerfile generator or the Dockerfile created from fly launch, this would be after the line FROM base as build).
Disabling telemetry in production
During server startup, the following messages may appear in your log:Common pitfalls
Out of memory: Killed process
If you should happen to see lines like the following in your logs:Fetch failure when optimizing images
If your application uses the<Image> element and your images aren’t showing and you are seeing the following in your logs:
Cannot find module
Your app doesn’t start and you see an error like the following in your logs:package.json’s dependencies, not just devDependencies. If you’re using a Dockerfile generated by dockerfile-node, your image will be optimized for production and omit development dependencies by default.
If the module is missing, add it to dependencies and re-deploy.