Deploying Node, Fastify with Typescript

Hi Everyone,

Happy New Year!

I am stuck on deploying my Fastify, Typescript app. I can get the app built with a Docker file and fly file generated, but it wont run the typescript command it keeps saying I am missing the @types/node which is strange as it installs it during the deployment successfully.

Is there any guides or templates on how to deploy with Typescript??

How about a working example?

mkdir ts-demo-43267
cd ts-demo-43267
npx --yes @flydotio/node-demo@latest --typescript
fly launch
fly deploy
fly apps open

This example does not use fastify, but does use node, typescript, and @types/node. Feel free to pick your own random number for the directory and app name.

More information on this demo app can be found here: Vanilla with Candy Sprinkles · The JavaScript Journal

1 Like

Thanks Rubys, I tried following it but i still get the below error:

2024-01-03T16:20:46.104 proxy[3287577db75498] arn [info] machine started in 543.742816ms

2024-01-03T16:20:47.062 app[3287577db75498] arn [info] > atlantic-seafood-api-prototype@1.0.0 start

2024-01-03T16:20:47.062 app[3287577db75498] arn [info] > node build/app.js

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] node:internal/modules/cjs/loader:1147

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] throw err;

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] ^

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] Error: Cannot find module ‘/app/build/app.js’

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] at Module._load (node:internal/modules/cjs/loader:985:27)

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] at node:internal/main/run_main_module:28:49 {

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] code: ‘MODULE_NOT_FOUND’,

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] requireStack:

2024-01-03T16:20:47.112 app[3287577db75498] arn [info] }

Even though the deployment seems to run fine.

This is my docker file:

syntax = docker/dockerfile:1

Adjust NODE_VERSION as desired

ARG NODE_VERSION=20.10.0

FROM node:${NODE_VERSION}-slim as base

LABEL fly_launch_runtime=“Node.js/Prisma”

Node.js/Prisma app lives here

WORKDIR /app

Set production environment

ENV NODE_ENV=“production”

Throw-away build stage to reduce size of final image

FROM base as build

Install packages needed to build node modules

RUN apt-get update -qq && \

apt-get install --no-install-recommends -y build-essential node-gyp openssl pkg-config python-is-python3

Install node modules

COPY --link package-lock.json package.json ./

RUN npm ci --include=dev

Generate Prisma Client

COPY --link prisma .

RUN npx prisma generate

Copy application code

COPY --link . .

Build application

RUN npm run build

Remove development dependencies

RUN npm prune --omit=dev

Final stage for app image

FROM base

Install packages needed for deployment

RUN apt-get update -qq && \

apt-get install --no-install-recommends -y openssl && \

rm -rf /var/lib/apt/lists /var/cache/apt/archives

Copy built application

COPY --from=build /app /app

Start the server by default, this can be overwritten at runtime

EXPOSE 3000

CMD [ “npm”, “run”, “start” ]

What this is saying is that npm run build isn’t creating a build/app.js file. This could be as simple as the file actually being named App.js (which is quite common), and you using either Windows or Mac which will match file names in a case insensitive manner. If this is the case, fix the start script in your package.json.

If this is not the case, run npm run build locally and compare the results in the build directory against running fly console and from there running ls -l /app/build.

1 Like

Thank Ruby for taking time to help me.

I finally got it working by using the fly console to review the file structure and update where the files where.

I ran into another problem with Prisma as it was not setting up the necessary files for Prisma during the deployment so could not run the Prisma Migration needed.

For anyone else running into these issues, below is my Docker file:

# syntax = docker/dockerfile:1

# Adjust NODE_VERSION as desired

ARG NODE_VERSION=20.10.0

FROM node:${NODE_VERSION}-slim as base

LABEL fly_launch_runtime="Node.js/Prisma"

# Node.js/Prisma app lives here

WORKDIR /app

# Set production environment

ENV NODE_ENV="production"

# Throw-away build stage to reduce size of final image

FROM base as build

# Install packages needed to build node modules

RUN apt-get update -qq && \

apt-get install --no-install-recommends -y build-essential node-gyp openssl pkg-config python-is-python3

# Install node modules

COPY --link package*.json ./

RUN npm ci --include=dev

# Generate Prisma Client

COPY prisma ./prisma

RUN npx prisma generate

# Copy application code

COPY . .

# Build application

RUN npm run build

# Remove development dependencies

RUN npm prune --omit=dev

# Final stage for app image

FROM base

# Install packages needed for deployment

RUN apt-get update -qq && \

apt-get install --no-install-recommends -y openssl && \

rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Copy built application and node_modules

COPY --from=build /app/build /app/build

COPY --from=build /app/node_modules /app/node_modules

COPY --from=build /app/package.json /app/package.json

COPY --from=build /app/node_modules/.prisma /app/node_modules/.prisma

# Copy the rest of the application code

COPY . .

# Start the server by default, this can be overwritten at runtime

EXPOSE 3000

CMD sh -c 'npx prisma migrate deploy && npm run start'

Here are my package.json scripts:

"scripts": {
    "preinstall": "npm install husky",
    "prisma-setup": "npx prisma migrate deploy",
    "build": "tsc -p .",
    "start": "node build/src/app.js",
    "dev": "tsnd --respawn --transpile-only --exit-child src/app.ts",
    "lint": "eslint src/**/*.ts --fix",
    "lint-staged": "lint-staged"
  },