We will dockerize our app using Docker. You don’t have to do this in development mode, but if you are going to have multiple packages running at the same time, this step will help you a lot. You can see the full code here.
Create Dockerfile
To dockerize our app, we will initialize a Dockerfile in the server app.
Because our server code depends on packages from validation
and libs
, we need to copy them from the root folder and include the apps
folder and packages
folder, treating it as a monorepo in the image.
Update Database Connection
We will use .env
variables to set the configuration for the database. We will pass them from Docker Compose later on.
Setup Environment Variables
We will create two environment variables:
-
.env
: This is the environment for Docker Compose. When we initialize it, Docker Compose will read the variables from this file. -
.env.dev
: These are the variables for our database connection. For thePOSTGRES_HOST
, we change the value from127.0.0.1
topostgres
. Essentially, we move the host from the local environment to the Docker environment, and the value should match the name of the database service in the Docker Compose.
Add Development Script
We will add two new scripts to run development mode in Docker. The first one is in the server app; we will add the concurrently
package to run the server app and all the packages because we need to import the build result instead of the TypeScript code.
The last one is to add a script to run Docker Compose in the root package.json
.
Add Docker Compose File
In this Docker Compose, we will create two services. The first one is the server app, and the second one is the PostgreSQL database. For the server app, we will mount our local files to Docker so that we get a nice hot reload when we change our code locally. We also set up the command to run the server app in development mode. For the PostgreSQL database, we create a Docker volume to save our data in the database in Docker. So, if the container is deleted, we still have the data. We also import create_tables.sql
to create the table and insert the data during initialization.
version: "3.8"
name: my-project-dev
services:
server:
container_name: my-project-dev-server
restart: unless-stopped
build:
context: .
dockerfile: ./apps/server/dockerfile.dev
ports:
- ${SERVER_PORT}:3000
volumes:
- .:/main
- /main/node_modules/
env_file:
- ./.env.dev
depends_on:
- postgres
command: >
sh -c "
yarn workspace libs run build &&
yarn workspace validation run build &&
yarn workspace server dev:concurrently
"
postgres:
image: postgres
restart: unless-stopped
container_name: my-project-dev-postgres
env_file:
- ./.env.dev
ports:
- ${DB_PORT}:5432
volumes:
- db:/var/lib/postgresql/data
- ./apps/server/init-db/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
volumes:
db:
driver: local
To run the app, we need to execute the command yarn compose:dev up
. This command will build and create a new container for us to run.
Top comments (1)
Wonderful post!
As a web developer, Docker is too much trouble for me. I prefer using 'all-in-one' tool like this.