As a software engineer, one of your goals is to ensure that your product can be accessed globally by your customers. It’s not enough that an app is bug-free and works flawlessly if it only works on localhost. Docker was introduced to solve the “it works on my machine” problem. For example, the particular version of a programming language a developer is using on Windows or MacOS may not be working on the hosting server. This explains why most applications fail to run once deployed to production.

In this tutorial, I will show you how to Dockerize your Golang API. Using an already built Golang API project, you will build a container image out of it, and then push the container image to the Azure container registry. I will then show you how to create an Azure web service as an application and connect the container image to it.

To wrap things up, I will guide you through creating a continuous integration and continuous deployment pipeline to run automated tests and deployment using CircleCI.

Prerequisite

To follow along with this tutorial, you will need the following:

Setting up the demo project

To get started quickly, clone the Golang API project from GitHub. Review this tutorial to learn how this demo was built. Run this command to download the project using Git:

git clone https://github.com/yemiwebby/go-docker-demo.git

This will clone the project into a go-docker-demo folder within your development directory.

Running and testing the application

Next, move into the project folder and run the application:

// Move into the project
cd go-docker-demo

// run the application
go run main.go

The application will run on the default port 8080. Go to http://localhost:8080 to review it.

App running on local This endpoint only returns a simple message as shown above. You can proceed to further test the remaining endpoints and run the unit tests just to be sure that everything works as expected.

Creating a new company

Test this out using Postman or your preferred API testing tool. Send an HTTP POST request to http://localhost:8080/company. Use the data below as the request payload:

{
  "name":"Shrima Pizza",
  "ceo": "Demo CEO",
  "revenue":"300 million"
}

Create company on Postman

Retrieving the list of companies

To retrieve the list of companies, set an HTTP GET request to http://localhost:8080/companies.

Retrieve company on Postman

Running the unit test

Now, open a new terminal window and run the test by issuing this command:

GIN_MODE=release go test -v

Unit test result from the terminal

At this point, the application work as expected, and the unit test are certainly passing. Stop the application from running using CTRL + C.

Deployment strategy

As mentioned, the objective of this tutorial is to Dockerize and deploy the Golang project to the Azure container instance. There is no need to modify the codebase other than the configuration file, so let’s go over the deployment strategy.

You will:

  • Create a registry to host your container image on Azure container registry (ACR) and obtain the Access key. ACR is a private registry owned by Microsoft for hosting Docker images just like DockerHub.
  • Create a container image for the project, then build and run the container locally.
  • Publish the Docker image to the Azure container registry.
  • Create an Azure web app and link it with the published container image.
  • Enable continuous deployment and create a configuration file to build and deploy your container image on CircleCI.
  • Push the project to GitHub and connect with CircleCI.
  • Deploy the container image to the Azure container registry.

Creating an Azure Container Registry

Next, you will create an Azure container registry that will store the image for this project. Go to the Azure portal homepage and click Create a resource.

Create resource

Then select Containers > Container Registry to create a new registry.

Create container resource

On the registry creation page, add the details for the registry, similar to what you have below. I have named mine godemo:

Create registry

Click Review + Create. You will be redirected to a page where you can review the registry information. Click Create to set up a new registry instance.

Getting the access key from the Registry

In this section, you will enable Docker access in the Azure container registry, which is crucial to the deployment process. It lets you remotely log in to the Azure container registry through the CLI and push images to it.

After the registry resources have been created, open it and locate the Access Keys link in the Settings section.

Enable admin user

This will show you the registry name and login server. Use the toggle button to change Admin user to enabled. Copy the username and any of the passwords, preferably the first one. Keep this handy; it will be used later in the tutorial.

Copy access key

Containerizing the application locally

Next, you will write a custom Docker file that will build a container image. From the root of the application, open the Dockerfile and ensure that its content matches this:

FROM golang:1.18.3-alpine3.16

RUN mkdir /app

ADD . /app

WORKDIR /app

RUN go build -o main .

CMD ["/app/main"]

This file uses golang:1.18.3-alpine3.16 as its base image. It then creates a new folder named app and adds all the content of the Golang project into it. Next, it sets the working directory in the container to th app folder and includes the command to run the project.

Building the Docker image

To build a Docker image for the project, run:

docker build -t godemo.azurecr.io/go-demo:latest .

This command looks in the project for the Dockerfile and builds the container image based on the content of the Golang application. Notice that the command uses the registry name and login server from the registry you created earlier. The benefit of this approach is that you can easily map the container image with the Azure container registry.

You will receive output when the container image has been built successfully.

Build container image

Running the Docker image

Now that you have built the local version of the container image, run it with this command:

docker run -d -p 8080:8080 godemo.azurecr.io/go-demo

This will run the app on the same port as earlier. Visit http://localhost:8080.

Pushing the Docker image to Azure Registry

Now, log in to the Azure container registry you created earlier and push the container image to it. Issue this command from the terminal:

docker login -u DOCKER_USER -p DOCKER_PASS godemo.azurecr.io

Replace these placeholders with your values:

  • Replace DOCKER_USER with the username for the container registry.
  • Replace DOCKER_PASS with the password from the container registry.

Once you are logged in, use this command to push the image to the Azure registry:

docker push godemo.azurecr.io/go-demo:latest

This deploys the image to the Azure registry.

View latest image

Creating an Azure web app for the container

Next, you will create an Azure web app and connect it with the container image. Go to the Azure portal homepage and click Create a resource. Select Containers > Web App for Containers to create a new web app service instance.

Create web app for image

You will be redirected to the Create Web App page. Select an Azure subscription and a resource group. Docker container should be selected by default.

Create web app Now, click on the Docker tab. Select the image source and its Docker image.

Link web app to container

Click Review + Create. You will be redirected to a page where you can review the web app details. Click Create to set up a new Azure web app.

Once the process is completed, you can visit the URL, where you will be able to review the app as deployed to Azure.

App running on Azure

Enable continuous deployment

To ensure that each time your Docker image is updated, the app will receive the update, you need to enable continuous deployment for the web app service. To do that, click the app name. Then click Deployment Center under the Deployment section and scroll down. Below the settings tab, turn on continuous deployment by selecting the radio button. Click Save.

Enable continuous deployment

With continuous deployment selected, the web app will trigger a new deployment of the Golang application each time the Docker image is rebuilt on Azure Container Registry.

Automating the deployment

Next, you need to add the pipeline configuration. This configuration instructs CircleCI to automate testing and run the commands to build and push the image to the Azure container registry.

At the root of your project, open the .circleci/config.yml file. Make sure the content matches this:

version: 2.1
orbs:
  go: circleci/go@1.7.1
jobs:
  build-and-run-test:
    executor:
      name: go/default
      tag: "1.16"
    steps:
      - checkout
      - go/load-cache
      - go/mod-download
      - go/save-cache
      - run:
          name: Run tests
          command: go test -v
  build-docker-image:
    docker:
      - image: cimg/go:1.18.3
    steps:
      - checkout
      - setup_remote_docker:
          docker_layer_caching: true
      -run:
        name: Build and push Docker image
        command: |
          docker build -t godemo.azurecr.io/go-demo:latest .
          docker login -u $DOCKER_USER -p $DOCKER_PASS godemo.azurecr.io
          docker push godemo.azurecr.io/go-demo:latest
workflows:
  test-and-deploy:
    jobs:
      - build-and-run-test
      - build-docker-image:
          requires:
            - build-and-run-test

These scripts contain two jobs:

  • The build-and-run-test job pulls in the Go orb for CircleCI, which allows common Go-related tasks such as installing Go, downloading modules, and caching to be carried out. It then checks out of the remote repository and issues the command to run the test.
  • The build-docker-image job builds the Docker container image for the project on CircleCI and pushes it to the Azure container registry.

The workflow ensures that the test is run successfully before building the container image and deploying it to Azure.

Next, you will need to set up a repository on GitHub and link the project to CircleCI. Review pushing your project to GitHub for instructions.

Connecting with CircleCI

Log into your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard. Search for the go-docker-demo project:

Select project

Click Set Up Project. You will be prompted about whether you have already defined the configuration file for CircleCI within your project. Enter the branch name (for the tutorial, you are using main). Click the Set Up Project button to complete the process.

Select configuration file

The first job will run successfully while the second will fail. This is because it requires the Azure container registry credentials.

Build failed

Fixing the credential issue

To fix the credential issue, click the Project Settings button, then click Environment Variables. Go ahead and add these two new variables:

  • DOCKER_USER is the username for the container registry.
  • DOCKER_PASS is the password from the container registry.

Environment variables

Click Rerun Workflow from Start.

Successful build

Your workflow will run successfully. You can make some changes to the codebase locally and push it to GitHub to be sure that continuous deployment has been implemented.

Conclusion

As you learned in this tutorial, each time you update the project and push it to GitHub, CircleCI will use the configuration details to build a new container image and update the Azure container registry with it. And with continuous deployment enabled on the Azure web app, a webhook resource will be fired to push a new version of the container image to the web app.

I hope that you found this tutorial helpful. Check here for the complete source code of the project.


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Read more posts by Olususi Oluyemi