Spinning service containers in GitHub action workflow
Tags: postgres, docker, devops
Published: 2021-05-29 17:03:25

Hi everyone,

This is a tutorial I am going to walk through how to run docker containers in [GitHub Action](https://docs.github.com/en/actions) workflows.
This task is often useful in testing workflows where we need a temporary database to run test cases. we will run a [PostgreSQL](https://www.postgresql.org/) database in this tutorial.  

```yml
name: Running Tests

on: [push]

jobs:
  Test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres

        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_USER: postgres
          POSTGRES_DB: postgres
        
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
        ports:
         
          - 5432:5432
```

in the above workflow snippet, we do several things. 

1. ```yml
on: [push]
``` will set when to run this workflow. here we have specified `push`,  so on every `push` event, this workflow will run. keep in mind that this is an array so we can use multiple options like `pull_request` etc.

2. ```yml
jobs:
  service-container-demo:
```
this code snippet will specify our job . `service-container-demo` is the name of our job. 

3. ```yml 
runs-on: ubuntu-latest
``` specifies, on what operating system we need to run this job. here we have specified to run it on ubuntu's latest operating system.

4.```yml
 services:
      postgres:
```
here we specify the services we need to run, and the name of the service container. name of the service container is used to access it. 

5. ```yml
image: postgres
``` this line will specify what image we need to run. these docker images are fetched from [Docker Hub](https://hub.docker.com/) . so we need to specify the respective image name from Docker Hub. 

6. ```yml
    env:
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
```
here we have specified the environment variables we need to provide to the service container. we have provided the password, username, and the default database here, so we can later access the database via those credentials. 


7.```yml
  options: >-
    --health-cmd pg_isready
    --health-interval 10s
    --health-timeout 5s
    --health-retries 5
```

we have to wait some time till the container is up and running .so to check that we have specified options to periodically check and after it is started proceed to the next steps. 

8. ```yml
 ports:
   - 5432:5432
```
here we have specified the port mapping. `5432` host port 
is mapped to `5432` container port.


next, we can define the steps of the workflow. here we can migrate to the service container database,  and run the required tests. 


```yml
# define steps of workflow
    steps:
      # run steps required in the workflow
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Set up Node.js 14.x
        uses: actions/setup-node@v1
        with:
          node-version: 14.x

      - name: Install dependencies
        run: npm install

      - name: migrate database
        run: node migrate.js
        env:
          DBURL: "postgres://postgres:postgres@localhost:5432/postgres"

      - name: Run the mock tests function
        run: node getuser.js
        env:
          DBURL: postgres://postgres:postgres@localhost:5432/postgres

```

in above snippet  `DBURL` is set to  `postgres://postgres:postgres@localhost:5432/postgres` . it is derived through the configurations we set in the service container earlier. the host is provided as `localhost` because the docker and host machine both runs on `localhost`. and here, we are passing it to the step,  through an environment variable.

#### database migration
![migration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vru2vteyentme4eraysb.png)


#### database query
![database query](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxrh4f6l8rc2jxc8evfo.png)


complete workflow file .
{% gist https://gist.github.com/RizkyRajitha/ca945c55ab09bcc2c7c150b2fed7db13 %}

example GitHub repo

{% github RizkyRajitha/gawscontainerdemo %}

### Thanks for reading till the end 🙌
### I value your opinions, and appreciate you taking the time to share your thoughts.