Wow! You've already made your project and now it's time to deploy it with Docker. This guide will focus on creating a Dockerfile for a React and Express application using either SQLite or PostgreSQL as the database. For more information check out the Docker docs or ask in #dockerize on Slack.
A Dockerfile is the set of instructions that Docker uses to build an image for your applications. It allows you to specify a base image, something like Node or Python, and then layer on top of that with your application. This includes all the commands needed to run your app, like installing dependencies, copying files, building, and exposing ports.
The first step is to create a file named "Dockerfile" with no file extensions. This guide will give you a basic Dockerfile and explain it line by line.
FROM node:22 AS frontend
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm install
COPY frontend/ ./
RUN npm run build
FROM node:22
WORKDIR /app/backend
COPY backend/package*.json ./
RUN npm install
COPY backend/ ./
COPY --from=frontend /app/frontend/dist ./public
RUN mkdir -p /data && chown -R node:node /data
EXPOSE 3000
CMD ["node", "index.js"]
FROM node:22 AS frontend
WORKDIR /app/frontend
These first two lines set the base image to Node.js and creates a folder in the container to be used as the current directory. The "AS frontend" is used to be able to reference this stage later.
COPY frontend/package*.json ./
RUN npm install
These liens only copy the package.json files and installs the dependencies. This is to take advantage of a feature Docker has where it will cache each layer (line) of the Dockerfile. This way you only install the npm packages if you change the package.json files.
COPY frontend/ ./
RUN npm run build
This one is pretty straightforward, it copies the rest of the frontend files and builds it.
COPY --from=frontend /app/frontend/dist ./public
I skipped ahead since the last few lines were similar to the first few. This is where the "AS frontend" comes into player. It copies from frontend output and puts it into the backend's public since we are serving the frontend with Express.