Skip to content

TypeScript

Create TypeScript Next.js app that runs in a container

Note: This guide uses Node 18 and Yarn and is based on the documentation on the Next.js site.

Go to the location where you wish to create the new project, create a new directory and then change into that directory. Next, run the following command to initialise the project

yarn create next-app --typescript .

To run the app locally on port 3000 in development mode and have the site auto refresh on changes, run the following command:

yarn dev

Next, modify next.config.js to so module.exports looks as below:

module.exports = {
  ...nextConfig,
  output: 'standalone',
};

Now, in the root of the project, create a new file called Dockerfile and populate it with the following:

# Install dependencies only when needed
FROM node:18-alpine AS build
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock ./

RUN yarn

COPY . .

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

RUN yarn build

# Production image, copy all the files and run next
FROM node:18-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# You only need to copy next.config.js if you are NOT using the default configuration
COPY --from=build /app/next.config.js ./
COPY --from=build /app/public ./public
COPY --from=build /app/package.json ./package.json

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

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

To build the container, run the following command, adjusting that tag (-t) parameter as required:

docker build -t jabbermouth/demo-nextjs .

To run this locally on port 3100, run the following command, adjust the tag as needed:

docker run -it --rm -p 3100:3000 jabbermouth/demo-nextjs

Yarn setup for Express API with TypeScript

This article talks through the process of setting up a basic Express API using TypeScript and Yarn for package management instead of NPM.

In the folder you'd like to create your project in, type the following commands. For the purpose of this project, we'll assume the folder being used is called “api”.

mkdir api
cd api
yarn init --yes

This sets up the initial project so that additional packages including Express can be installed.

Next, we'll add the Express and DotEnv packages:

yarn add express dotenv

At this point, we could test things but we want a typescript app so next we'll add the required TypeScript files as dev dependencies using -D:

yarn add -D typescript @types/express @types/node

The next step is to generate a tsconfig.json file which is accomplished by running the following command:

yarn tsc --init

In tsconfig.json, locate the commented out line // "outDir": "./", and uncomment it and set the path to ./dist so the line now looks like the following (note the comment at the end of the line can be left in if desired):

"outDir": "./dist",

Next create a file called index.ts in the root of the project and populate it with the following example code:

import express, { Express, Request, Response } from 'express';
import dotenv from 'dotenv';

dotenv.config();

const app: Express = express();
const port = process.env.PORT;

app.get('/', (req: Request, res: Response) => {
  res.send('Express + TypeScript Server');
});

app.listen(port, () => {
  console.log(`⚡️[server]: Server is running at http://localhost:${port}`);
});

To make development easier, we'll add a few tools as dev dependencies:

yarn add -D concurrently nodemon

Next, add or replace the scripts section of package.json with the following (I suggest before the dependencies section):

  "scripts": {
    "build": "npx tsc",
    "start": "node dist/index.js",
    "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/index.js\""
  },

And update the value of main from index.js

Finally, create a .env file in the root of the project and populate it with the following (updating the port if required):

PORT=3100

Finally, start the server in dev mode by typing the following:

yarn dev

A link to the site will be showing. Using the port suggestion above, this will be http://localhost:3100/ which when accessed from the browser will show an empty screen displaying the message “Express + TypeScript Server”.