In this article, we will create a simple golang application CI/CD process and push it to Docker hub by github action. Finally, will illustrate an example of how to use the terraform and docker-compose to deploy a local docker environment.

Create Docker hub repository

First, create a repository on Docker hub, here we create a repo name adon988/go-github-action-helloworld

Generate Github Actions workflow

Create a project folder .github/workflows/ and add github actions yaml file

Here needs plugin: Publish-Docker-Github-Action

name is the name of the image you would like to push username the login username for the registry password the authentication token [preferred] or login password for the registry.

deploy.yml

name: Build and Test
on:
  push:
    branches:
      - master
  pull_request:
jobs:
  build:
    strategy:
      matrix:
        platform: [ubuntu-latest]
    runs-on: ${{ matrix.platform }}
    steps:
      - name: Install Go
        uses: actions/setup-go@v1
        with:
          go-version: ${{ matrix.go-version }}

      - name: Check out code
        uses: actions/checkout@v1

      - name: Tesing
        run: |
          make test

      - name: Build binary
        run: |
          make build

      - name: Publish to Registry
        uses: elgohr/Publish-Docker-Github-Action@master
        with:
          name: adon988/go-github-action-helloworld
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

Create a simple go application

Here we generate a simple go application when user access will return a “Helloworld”

package main

import (
	"fmt"
	"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Helloworld")
}
func main() {

	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

Prepare a Dockerfile

Dockerfile will implement the docker build in the github action process, in the file will copy the go build file to the bin folder, and set the file path as an endpoint when docker run.

FROM plugins/base:linux-amd64

  LABEL maintainer="Adon988 <adon988@gmail.com>" \
  org.label-schema.name="go-github-action-helloworld" \
  org.label-schema.vendor="Adon988" \
  org.label-schema.schema-version="1.0.1"

  EXPOSE 8080

  COPY release/go-github-action-helloworld /bin/

  ENTRYPOINT ["/bin/go-github-action-helloworld"]

Makefile script

In github action will using the Makefile script, here have three targets in here:

build: will used to build a go application docker: will used to build a docker image test: will implement a go test

build:
  CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -a -o release/go-github-action-helloworld

docker:
  docker build -t adon988/go-github-action-helloworld .

test:
  go test -v .

Generate a Docker hub repository and set Action secrets

In Docker hub and go to Account setting > security > to create Access tokens

Next, go to Github and set access token as secrets: DOCKER_USERNAME DOCKER_PASSWORD

Publish

Publish the local go application(with github action workflow, Dockerfile, and Makefile) to github, and wait for the github action to run away, there will push a docker image to Docker hub repo.

Docker compose

Create Docker compose file docker-compose.yml

version: "3.9"
services:
  go-github-action-helloworld-services:
     image: adon988/go-github-action-helloworld
     restart: always
     ports:
       - 8000:8080

Execution the application from Docker hub repo image, and you can access the locahost:8000 to see the “Helloworld”

docker-compose up -d go-github-action-helloworld-services 

Next time, if the application has been modified, can re-pull the image by the following command:

docker-compose pull go-github-action-helloworld-services && docker-compose up -d go-github-action-helloworld-services

Terraform example

Here is a example of deploy a local docker app by terraform:

terraform {
  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 2.13.0"
    }
  }
}

provider "docker" {}

resource "docker_image" "helloworld" {
  name         = "adon988/go-github-action-helloworld:latest@sha256:31eeef8a27937131d69390b51fea09724d220c03b421210808346a02395bb0bc"
  keep_locally = false
}

resource "docker_container" "helloworld" {
  image   = docker_image.helloworld.latest
  name    = "hellowlrd-example-v3"
  restart = "always"
  ports {
    internal = 8080
    external = 8000
  }
}

Problem solting

If the following error message occurred:

WARNING! Your password will be stored unencrypted in /github/home/.docker/config.json. Login Succeeded Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store

unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /github/workspace/docker: no such file or directory

Solution

Please check your deploy.yml file format:

      - name: Publish to Registry
        uses: elgohr/Publish-Docker-Github-Action@master
        with: