gib's blog

This is Why You Should Dockerize

Background

Docker provides the ability to package and run an application in a loosely isolated environment called a container. https://docs.docker.com/get-started/overview/

Dockerizing your development and production environment certainly has its benefits.

  1. Predictable environment

As Docker's docs suggests, Docker helps us run our app in a container (for example, using node-16 image). This way, "Engineers get to work in a consistent and unified way instead of bouncing back and forth between servers or machines" (as this source suggests). The more predictable our development environment is, the better our development experience will be overall. Docker helps us with this.

  1. Integration with other platforms

Google Cloud Run and Railway are some of the platforms that can be used to deploy our apps. They are Docker-based, meaning their deployment relies heavily on Docker containers (Railway kind of handles the process automatically, but we can also use a custom Dockerfile). Should we need to deploy on these platforms, by Dockerizing our app, the integration process would be easier.

How to Dockerize?

We have 2 types of Dockerfiles:

// Dockerfile, used for local environment
FROM node:21-alpine3.18

WORKDIR /app

COPY package*.json ./

RUN yarn add sharp --ignore-engines

RUN yarn install

COPY . .

RUN yarn migrate

RUN yarn seed

RUN yarn build

CMD [ "yarn", "start:dev" ]
// Dockerfile.prod, used for staging and production environment
FROM node:21-alpine3.18

WORKDIR /app

COPY package*.json ./

RUN yarn add sharp --ignore-engines

RUN yarn install

COPY . .

ARG DATABASE_URL

RUN yarn migrate

RUN yarn build

CMD [ "yarn", "start" ]

These Dockerfiles will generally install dependencies, run database migrations, and run the app.

For local environment, we use Dockerfile. For staging and production environment, we use Dockerfile.prod. The difference is the way we're starting the app. Another difference is we're seeding some data to our database for the local environment so that our database is prepopulated (helps us test certain queries in our app).

The Dockerfile, used locally, is wired up with our docker-compose.yml. There are configurations to set up our local database, Redis, and PGAdmin to interact with our local database. With this, since we are a group of 6, setting up our local backend environment should be easier than manually setting up our database and Redis cache.

On the other hand, Dockerfile.prod will be used by Railway to build our app in the staging and production environment.

These Dockerfiles really help us for our local, staging, and production environment.

Conclusion

Dockerizing our application helps our team be productive in developing our backend application. Integration with Railway really helps us deploy our app in a predictable and efficient way.