Using Docker Containers In Jobs - GitHub Actions
Tags: github, docker, devops, beginners
Published: 2020-12-04 15:13:35

👉 Prerequisites 

If you are new to GitHub Actions, I suggest you to read these articles
* [Introduction to Github Actions - GitHub Actions (Part 1)](https://dev.to/mihinduranasinghe/introduction-to-github-actions-part-1-1d6p)

* [Working with environment variables - GitHub Actions(Part 2)](https://dev.to/mihinduranasinghe/working-with-environment-variables-github-actions-part-2-46po)

* [Working with external actions - GitHub Actions (Part 3)](https://dev.to/mihinduranasinghe/working-with-external-actions-github-actions-part-3-3895)

---

As we discussed in previous articles, we can run our workflows in virtual machines by using operating systems that GitHub Actions provides as GitHub Hosted Runners.

## **Using Docker Container**

We can use a docker container which will be installed on the the  virtual machine & then instead of running directly on virtual machine, our workflow will runs on a particular container.

<i> **This can be an image from Docker Hub.** </i>

---

### **Docker Hub**

Docker Hub is the platform which allows users to create, manage, and deliver their container applications. Docker Hub is the largest library of container images.

Link: [Docker Hub](https://hub.docker.com/)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hnsyfj4zh1y5cg4phukr.PNG)

Once you click on an image (For example Node), you can see all the dockerfile links with the respective tags.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wiior329v7okszi25woe.PNG)

---
### **How to use ?**

You have to provide the, 
**publisher-dockerhub-username : docker-image-tag** with the image tag under the "container:" 

* We can not use containers on windows and mac-os virtual machines.
* We can use containers only on ubuntu machines.

```

name: workflow-name
on: push

jobs:
  job-name:
    runs-on: ubuntu-latest
    container:
      image: dockerhub-username:docker-image-tag

```

**Example:**

```yml

name: container
on: push

jobs:
  node-docker:
    runs-on: ubuntu-latest
    container:
      image: node:14.15.0-alpine3.12
      
```

Also you can provide some other parameters like environment variables, ports & options...etc

```yml

name: container
on: push

jobs:
  node-docker:
    runs-on: ubuntu-latest
    container:
      image: node:14.15.0-alpine3.12

     #env:
     #  ENV1: Available to this container only

     #ports: To expose our container

     #options: --cpus 1 --host
      
```
So in next figure you can confirm that steps are running inside the container we initialized with dockerhub image, instead of running directly on the virtual machine.

```yml

name: container
on: push

jobs:
  node-docker:
    runs-on: ubuntu-latest
    container:
      image: node:14.15.0-alpine3.12
    steps:
         - name: Log the node version
           run: |
             node -v
             cat /etc/os-release  

      
```

Here we echo the node version of the image and some operating system information of the docker container.

**Output:**

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tnwy3fccih0i9gwtgeds.PNG)

---

## We can also specify multiple containers to run as services.

If you have an application to run multiple services, you might need multiple images to run in our virtual machine. Normally we use **Docker-Compose** to do something like that, **but in GitHub Actions we have a similar way to run this type of applications.


## **Running multiple docker containers in a job.**

Instead of having container here, we can provide "services: "
We can give the services as docker-images under the "services:" and they run as separate containers in our virtual machine.

```yml

name: workflow-name
on: push

jobs:
  job-name:
    runs-on: ubuntu-latest
    services:
      service-name-1:
        image: dockerhub-username:docker-image-1
        ports:
           - 3001:3000

      service-name-2:
        image: dockerhub-username:docker-image-2
        ports:
           - 4001:4000

    steps:
      - name: Get from service-1
        run: http://localhost:3001/api/users

      - name: Get from service-2
        run: http://localhost:4001/api/items


      - name: post a user example
        run: "curl -x POST http://localhost:3001/api/user -H 'Content-Type: application/json' -d '{\"username"\: \"hello"\, \"address"\: "sampleaddress"}' "


```

Here it creates two containers for service-1 & service-2 inside our virtual machine

In order to communicate between those two containers, we can use the service-name as the host name in the app.

---

## **Running docker containers in individual steps.**

In GitHub Actions, we can use different containers in different steps as well. 

* We can use "with:" key to provide inputs to this container in the particular step

* We can give an **entrypoint** in **with:** key and override the entrypoint of the dockerfile

* To find some entrypoints of the echo, node ...etc use this commands


Ex 1:

```
type -a  echo
```

* Output - Entrypoint of echo in ubuntu:

```
echo is  /bin/echo
```

Ex 2 :

```
type -a  node
```

* Output - Entrypoint of node in ubuntu:

```
node is  usr/local/bin/echo
```
Use this "type -a " command in ubuntu to find some Entrypoints of the installed tools & softwares.

**Example:**

```yml

name: container
on: push

jobs:
  node-docker:
    runs-on: ubuntu-latest
    container:
      image: node:14.15.0-alpine3.12
      steps:
         - name: Log the parent container node version
           run: |
             node -v 
           # Echo the node version of the parent container


         - name: Log the step container node version
           uses: docker://node:12.14.1-alpine3.10
           with:
             entrypoint: usr/local/bin/echo
             args: -v
            # Echo the node version of this step container based on this 12.14.1-alpine3.10 image


         - name: Step with docker to echo a string
           uses: docker://node:12.14.1-alpine3.10
           with:
             entrypoint: /bin/echo
             args: Hello Docker !


```

Push the workflow file into the repository & check the **Actions** window of the repository

**Outputs:**

```
v14.15.0
v12.14.1
Hello Docker !

```

👉 What's Next?

  * [Trigger workflows manually using the repository dispatch event]()


## **Thank You**

##### ***Hope you all enjoyed and learned something from this. Let me know your comments and suggestions in the discussion section.***

👉 Visit me - [https://mihinduranasinghe.com/](https://mihinduranasinghe.com/)