Part 1: Exploring and setting up NestJS
Part 2: Dockerizing and hosting a NestJS application
This is the second installment in my series about NestJS and becoming familiar with it.
In this part of the series, I’d like to dive further into how and why I dockerized the setup.
As with any new application, we have to make a choice of where to host the thing. I have followed fly.io on YouTube and generally heard things about them, making it a hosting provider I wanted to try out.
So I quickly set up an account and got started setting up apps via the interface. However, I quickly learned that they have a CLI and its a great way to manage apps, servers, databases and anything you’d like.
I used the CLI to initialize the app for fly.io, so it was properly containerized for their setup. It was indeed a breeze! It worked amazingly well, automatically detected that I was using NestJS and asked me a few questions, which eventually provided me with a Dockerfile, that should use to host the application.
The dockerfile was pretty neat, using multi-stage builds, automatically knowing I was using Yarn as my package manager. It was all a breeze.
Heres’ the Dockerfile it produced:
# syntax = docker/dockerfile:1
# Adjust NODE_VERSION as desired
ARG NODE_VERSION=22.12.0
FROM node:${NODE_VERSION}-slim AS base
LABEL fly_launch_runtime="NestJS"
# NestJS app lives here
WORKDIR /app
# Set production environment
ENV NODE_ENV="production"
ARG YARN_VERSION=1.22.22
RUN npm install -g yarn@$YARN_VERSION --force
# 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 pkg-config python-is-python3 ca-certificates
# Copy Prisma schema early — before yarn install triggers postinstall
COPY prisma ./prisma
# Install node modules
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile --production=false
# Copy application code
COPY . .
# Build application
RUN yarn run build
# Final stage for app image
FROM base
# Copy built application
COPY --from=build /app /app
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD [ "yarn", "run", "start:prod" ]
As you can see, it’s nothing exceptionally crazy, but it does follow some nice patterns, while using my existing package manager, yarn, and allows for extra installs should I need them.
The fly.toml file was added to my repository after running the initialization and it contains an easy-to-understand configuration for my my application, deciding how much power the server should have, etc. Essentially the file is a sort of IAC.
The fly CLI
Fly aims to be developer centric and therefore has a very convenient CLI tool. So convenient in fact, that it supports several things, that aren’t (yet?) available through the interface on their web platform.
Thats pretty neat.
Overall I enjoyed the CLI quite a bit, and it allowed me to configure everything; redis, domains, database, autoscaling and much more.
I had to revisit it several times, setting up the application for the first time, as I needed to add environment variables over several passes. Thankfully the CLI handles those very well too.
What wasn’t so great
Being a developer, I found the CLI approach awesome.
However, for some weird reason that probably says a whole lot more about me, ai couldn’t wrap my head around having a hosting provider managed through a CLI.
And thats despite having used IAC tools to manage infrastructure several times.
I dont know if there were any particular inconveniences, or something that just didn’t click for me, but ultimately I found the lack of support in the interface quite confusing.
On the note of support, when I had hiccups hosting a react app, I wanted to reach out to support for some assistance, after all I did create a business account.
Unfortunately I had to pay up another, 29$ for access to support.
I’m not sure I understand this decision as I reckon most support would be in the initial phase for customers, when they need to get their apps set up. Either way, I can respect that they value their own sanity – and probably a more self sufficient type of customer.
Render instead of fly?
Initially I had set up render.com for the backend part of the app (the NestJS application) as they boasted built in support for it, and I didnt wanna bother with more hosting setup, after having a bit of trouble with the react app.
I found the render platform and its interface excellent, their docs where a bit more mature, and to my surprise I liked their CLI even more!
Its so great. It even got a whole visual component where it takes over your entire terminal to render selectors for things. Probably some tmux going on there but I don’t even know.
Try it out, its great!
After having a pretty good experience with the initial setup, I started contemplating setting up the react app on render too, but I didnt really have much reason to do so.
I started seeing some errors with new versions not coming out properly, things being a bit weird and so ultimately, I actually decided to move off fly.io, primarily because of having to pay for support.
Spinning up the front end on render.com, was surprisingly easy and not at all the headache it had been on fly.io, which led me to think I made the right choice.
So in the end I ended up trying out Fly, had it there for a few weeks, but kept seeing errors, and ultimately migrated to render.com.
Thankfully, this change was very easy, as all I had to do was remove the fly.toml file and a few other configurations, but I could still re-use the Dockerfile and the rest of the codebase.
Easy 👌