The source code for this project can be found here.
Getting Started
Building a Golang program is pretty easy. The simplest program can be merely 3 lines of code.
package main
import "fmt"
func main() {fmt.Println("Howdy!")}
“Hi”, “howdy”, and “hello” are all greetings you might use with a stranger, or an acquaintance whose name escapes you. It’s less personal, no matter how friendly, because you’ve omitted the recipient’s name. To make this program more personal, let’s ask the user for their name.
package main
import "fmt"
func main() {
var name string
fmt.Println("Howdy! What's your name?")
fmt.Scan(&name)
fmt.Printf("Hi, %s! Nice to meet you!\n", name)
}
Now that’s a bit more personal!
Containerization
There’s just one more catch: your organization only lets you deploy containerized workloads. You cannot run this simple script on any servers or VMs as-is. Let’s containerize it.
Docker Hub must have secure container images that we can build off of, right? Let’s assume that for now and use the Docker Official Image for Golang. At the time of this blog’s creation (July 15th, 2025), 1.24 is the latest stable version. 1.25 is available, but it’s offered as an unstable version. Although I couldn’t find an official definition for “unstable”, I interpret it to mean that “not all features and methods in Go 1.25 today are guaranteed to be present in the stable release of Go 1.25”. With that interpretation in mind, it’s almost certainly a best practice to use the latest stable version.
Let’s use the following Dockerfile for our app.
#1
FROM golang:1.24
#2
WORKDIR /app
#3
COPY main.go /app
#4
CMD ["go", "run", "/app/main.go"]
Although I’ve numbered the 4 lines in the Dockerfile, you would never do this in production. I’ve just done this to illustrate:
- Line 1 instructs the Docker CLI to pull the golang:1.24 image from Docker Hub to use as a base image.
- Line 2 instructs the Docker CLI to set /app as the working directory in our container image.
- This is a critical instruction. /app does not exist in the Golang base image by default. According to the Docker docs, “If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.”
- Line 3 instructs the Docker CLI to copy our main.go file to /app.
- Line 4 instructs the Docker CLI to run main.go within the running container.
- An interesting call-out from the Docker docs: “CMD doesn’t execute anything at build time, but specifies the intended command for the image.”
And finally, let’s try building the container and running it with the following commands.
docker build . -t go-app
docker run -it go-app

Although your users would never need to initiate the container themselves manually with a docker command, this dips our toes into the sea of containers. We’ll continue to get our ankles and shins wet in the next few posts.
Interesting Takeaways
Here are some things I personally learned by writing this:
- Golang’s Println function does not support string formatting. Printf is the function you’ll need to use.
- It’s almost certainly a best practice to use the latest stable version of Golang. For the vast majority of developers, you’ll never need to toy around with unstable versions.
- The CMD instruction requires expects you to each word in a command into its own spot in an array. CMD [“go”, “run”, “/app/main.go”] will work. CMD [“go run /app/main.go”] will not work.
What did you learn?
#containers #docker #golang
Leave a comment