YURKOL Ltd - Custom Software and Cloud Architectural Solutions for Modern Businesses

Containerizing Go code with Buildapcks

In this article I'm going to demonstrate how to use Buildpacks in practice - we'll build a simple Go appliacation and put it into a Docker container. This is to give the reader understanding of a whole process - from writing the application's code to run the container.

This is the continuation of the article What is Buildpacks

Install pack CLI

In order to use Buildpacks, first of all, we have to install the pack CLI tool, which is available for *nix operating systems' package managers, or can be downloaded and installed directly from Github using installation script:

yurii@localhost:~> (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.29.0/pack-v0.29.0-linux.tgz" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack)

Make sure it has been installed correctly by checking the version of pack CLI:

yurii@localhost:~/code/go-sketches> pack --version

if everything's OK, the ouput will look similar to:

0.29.0+git-95c8060.build-4209

Bash completion is also available. To use it, add this string: . $(pack completion) to your ~.bashrc. As always, do not forget to log out and log in again in order to activate it globally.


Writing the app

Our Go application is a simple http-server, that accepts requests on port 8080 and returns client's address as a response.

Let's create a directory for our app: yurii@localhost:~/code/go-sketches> mkdir simple_server && cd simple_server

Then put the following code in file main.go:

File main.go

Here info about the http client is taken from the http.Request - this is particularly useful for logging or can be utilized for some kind of a filtering/access control middleware.

Containerize the app

In order to containerize our app, simply run

pack build simple_server

The buildpack builder will analyze the current working directory content; upon detecting Go source code in main.go, it'll execute all the necessary logic to compile it into an executable and then create a Docker image.

If all went well, the command's output will contain the following:

Saving simple_server...
*** Images (567cf56ba625):
simple_server
....
Successfully built image simple_server

As simple as that! No need to write dockerfile, no need to manually build an image - isn't it cool?


Testing pack CLI

Let's check whether the image has actually been built successfuly and exists locally: yurii@localhost:~/simple_server> docker images


... the command's output should contain

simple_server latest $image_hash

Let's run the image: docker run --rm -p 8080:8080 simple_server
... the app's first message is logged into stdout: 2023/07/25 08:12:36 starting http server at 8080

Let's send a request (in another terminal): yurii@localhost:~> curl http://localhost:8080

... the response contains the client's address: 172.17.0.1:38650

on your machine this address may be different - it's assigned by containerd.