How to Set Up Separate Test and Development Databases in Docker
(using Node.js, PostgreSQL, Knex.js)
Part 2

How to Set Up Separate Test and Development Databases in Docker (using Node.js, PostgreSQL, Knex.js) Part 2

Part 1 | Part 2 | Part 3

docker-compose.yml

In the root directory of your project create another file called docker-compose.yml. This is a YAML file that will define how your Docker containers should behave. Below is an example of what your docker-compose.yml could look like. You can find more information on how to set up other versions of this file in the Docker Services documentation.

version: "2"

services:

  api:
    build: .
    command: npm start
    volumes:
      - .:/app
    ports:
      - 8000:8000
    depends_on:
      - postgres_dev
    environment:
      - NODE_ENV=$NODE_ENV

  postgres:
    image: postgres:9.6.2-alpine
    volumes:
      - ./.data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: db_dev
      POSTGRES_USER: username
      POSTGRES_PASSWORD: $POSTGRES_PW

  postgres_test:
    image: postgres:9.6.2-alpine
    environment:
      POSTGRES_DB: db_test
      POSTGRES_USER: username
      POSTGRES_PASSWORD: $POSTGRES_PW

Although I will go over each section of code more thoroughly, the important thing to note here is that there are 2 separate services for 2 different databases, one for the test environment and one for the development environment. Services are the actual containers for different pieces of the app. Using 2 different services for test and development databases allows us to run clean seeds and migrations each time tests are run while persisting data over runtimes for the development environment.

version

Specifying the version of the Compose file format is important for defining Docker Engine compatibility, Compose structure and permitted configuration keys, and Compose’s behavior with regard to networking. You can find more information about choosing the Compose version in the Docker docs.

services

In this section of code you will be delineating the containers you plan to run. As previously mentioned, each service corresponds to a container for a section of your app. (Individual services can actually run multiple containers which is convenient for scaling, but we won’t worry about that for now. If you’d like more information you can read more about that in the Docker docs as well.)

As shown in the above code we have defined 3 different services:

api - This is where the backend code of the api lives

postgres_dev - This container holds the database for the development environment

postgres_test - This container holds the database for the test environment

api

build

This command utilizes the Dockerfile to build a container from the specified path. In this case, we are building the container from our project’s root directory. Docker then looks for the Dockerfile and uses the image and commands specified there to build the container.

command

Technically, this instruction will override the default command specified in the CMD directive in the Dockerfile. You may see some apps that only use CMD in the Dockerfile and others that use both command in the docker-compose.yml and CMD in the Dockerfile. Either way, this instruction is telling Docker to run the command line instruction that follows.

In this case we are instructing Docker to run the npm start script.

volumes

Volumes can be used to persist data in Docker containers that would otherwise be lost when a container stops running. After the container mounts it creates the specified volumes. The contents of the host system path specified before the colon are then copied and used to populate the volume at the path inside the container specified to the right of the colon.

ports

This maps host ports to exposed container ports.

depends_on

This command alerts Docker of the order in which to start each service. The service listed here will be started before the service that depends on it. In this case the api service is explicitly saying it depends on the postgres_dev service so the postgres_dev service will be started first. This does not mean that Docker will wait until the postgres_dev service is ready to spin up the api service, it simply means postgres_dev will be initiated first.

environment

Here we are declaring relevant environment variables for this service. These environment variables will be set inside the container running for this service. In this case we are setting the NODE_ENV to the environment that is specified in the host environment during initialization.

postgres

image

This specifies the image to run the container from.

volumes

Here you will notice that one postgres container declares a volume, whereas the other one does not. This is because we want the data in the development container to persist over runtimes, but we want the test container to empty and re-populate each run.

In postgres_dev Docker creates a folder at the path ./.data and mounts that folder into the container. Docker copies the data from the local host and populates it in the file at /var/lib/postgresql/data in the container.

environment

The environment variables declared here include the name of the database this container is running as well as the username and password to access the database.


**This is part 2 of a 3-part article. You can find part 1 here and part 3 here.

To view or add a comment, sign in

More articles by Meghan Prestemon

Others also viewed

Explore content categories