Smaller Next.js images! (standalone support)

Images for Next.js apps from generated Dockerfiles using fly launch will be dramatically smaller (read: ~400MB smaller) when using the standalone output option in your next.config.js

Read the full documentation here: Run a Next.js App · Fly Docs

For new Next.js apps:
Ensure that your next.config.js file contains output: "standalone"

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: "standalone"

export default nextConfig;

Then run fly launch, and the appropriate Dockerfile will be generated.

For existing Next.js apps deployed to
Inside your Dockerfile, 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:

COPY --from=build /app/.next/standalone /app
COPY --from=build /app/.next/static /app/.next/static
COPY --from=build /app/public /app/public

Lastly, update your CMD to the following:

CMD [ "node", "server.js" ]

Access Log Hack
If you are using the above with NextJS version 14.1, you can use the follow hack to create access logs:

  1. Add a file to your repository called logging.js that looks something like this:
/* eslint-disable no-console */
 * Log to console each request.
 * @param { import('http').IncomingMessage } req
 * @param { import('http').ServerResponse } res
function log(req, res, requestTime) {
  const user_agent = req.headers['user-agent'];
      request_method: req.method,
      request_uri: req.url,
      request_time_ms: Number(requestTime.toFixed(1)),
      content_type: req.headers.content_type,
      status: res.statusCode,
      reqId: req.headers['fly-request-id'],
      x_forwarded_for: req.headers['x-forwarded-for'],

module.exports = log;
  1. Add two commands to your Dockerfile, after the COPY of /app/public something like:
COPY logging.js /app/logging.js

# Inject logging into next's server code
RUN sed -i -e '/"use strict";/a\const log = require("/app/logging")' \
    -e '/await requestHandler(req, res)/s/^/    const startTime =\n/' \
    -e '/await requestHandler(req, res)/a\    const requestTime = - startTime\n    log(req,res,requestTime)\n' \

And you will have access logs with request times!