Intro

Docker is such a fantastic tool for software development and I can’t think of a reason not to use it when applicable. In this quick blog post, I’ll show you how to use Docker and the official Docker Hub image to spin up a simple "Hello World!" program in Go. These steps can be applied to virtually any language available on Docker Hub. Hopefully, it’s a straightforward example and highlights just how versatile and efficient Docker can be.

I’ve been learning an incredible amount from Brett Fisher’s Docker Mastery course and this is only scratching the surface of what I’ve learned so far! 🤯 But a couple of quick prereqs to clear up first.

Docker Desktop

You will need this installed and running before proceeding below. Docker Desktop is the preferred tool (or bundle) for getting started with Docker. It comes with the Docker Engine and Docker CLI which are the two tools we need for this. Also, it’s totally free to create an account for personal use! So go install it and get it running, it’s worth it.

Container vs. Image

All you need to really know until you dive deeper into Docker is that containers run images. An image is essentially a snapshot of an application, including its source code, dependencies, and any necessary system libraries, often based on a lightweight Linux distribution. A container is an isolated runtime environment that executes the image, providing everything the app needs to run independently from the host system.


Let’s Go(lang)!

So with some of the basics out of the way, let’s dive right in. Let’s use Go for this exercise, but definitely check out Docker Hub and look around to see what other images are available! The first task is to check and make sure that Docker is installed and running.

Pulling the image

Let’s check to see if Docker is running with docker ps. Since you haven’t run any containers yet, it should just return the table headers. If you see an error about the Docker daemon connection, check your install and make sure Docker Desktop is running.

bash
docker ps

Now that Docker is running, let’s pull the official Golang image from Docker Hub.

bash
docker image pull golang

Expected Output:

You should see it loading in the various image layers with the default tag latest.

Using default tag: latest
latest: Pulling from library/golang
ba1dd0e85e0b: Pull complete
92b12b0dccf2: Pull complete
fd63102cac36: Pull complete
47f0760d52ed: Pull complete
39f8f326b044: Pull complete
df3aad8f12f6: Pull complete
4f4fb700ef54: Pull complete
Digest: sha256:7ea4c9dcb2b97ff8ee80a67db3d44f98c8ffa0d191399197007d8459c1453041
Status: Downloaded newer image for golang:latest
docker.io/library/golang:latest

To verify, you can check the images on your machine.

bash
docker image ls

Expected Output:

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
golang       latest    e3b811b0aa52   3 weeks ago   844MB

Running the Container

Now we can run a container with the Golang image! This command includes a couple of interesting flags. I encourage you to take a look at all of them with the docker container --help command (which you can append to almost any Docker CLI command! WOW!).

bash
docker container run -it --rm --name go-say-hello-world golang bash

Let’s break down some interesting parts of the command:

  • container
    • This specifies that you want to interact with Docker containers. While the container part is optional (you could just use the oldskool command docker run), it’s now conventional to use the management command container followed by the sub-command.
  • run
    • This is the sub-command that tells Docker to create a new container from the specified image and immediately run it.
  • —-it
    • Together, —it allows you to interact with the container's terminal as if you're working on a normal Linux machine.
      • i (interactive): Keeps the stdin (standard input) open, allowing you to provide input to the container.
      • t (tty): Allocates a pseudo-TTY, providing an interactive terminal session (like you’re using a shell).
  • --rm
    • This flag will remove the container once you exit which is fine for this lightweight exercise
  • golang
    • This specifies the image we pulled from Docker Hub. No need to append :latest
  • bash
    • This specifies the command to run inside the container. Here, it's the bash shell, which gives us access to an interactive Linux shell environment.

What Happens When You Run This Command:

  1. Docker checks if the Golang image is available locally. We already did that so we are good to go!
  2. Docker creates a new container from the Golang image.
  3. The container runs the specified command (bash).
  4. You’re dropped into an interactive Bash shell inside the container, where we can interact with the container's filesystem and environment.

Example Output:

This indicates you're now inside the container's terminal, ready to get buildin’.

root@<container_id>:/go#

Write your “Hello World!”

Almost there, feel free to poke around in the container. You are in a fully interactive bash session after all. You can type in go to get a nice list of Golang CLI commands to test. But we are here to write a quick “Hello World” so let’s do that!

Using cat we can write out basic Hello World! function.

go
cat <<EOF > main.go
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
EOF

Then you can compile and run.

bash
go run main.go

Expected Output:

Hello, World!

Wrapping up

That’s it. Now you can exit the container with exit. You’ve just created and run a containerized "Hello World!" in Go using Docker! I hope this process not only introduced you to the fundamentals of Docker but also gave you some hands-on experience with the workflow of pulling an image, running a container, and cleaning up after use.

This is a really sleek way to get around having to install dependencies and go through the hassle of installs when you’d like to try a new language or program!

If you’re excited about Docker now, definitely check out the Docker Mastery course I mentioned earlier. There’s much more to explore!

And the last thing you can do if you really want is to remove the Go image we pulled. You can start by checking out the system disk usage

bash
docker system df

And then remove the Go image with the <name>:<tag>

bash
docker image rm golang:latest

Thanks for reading, remember to commit early and often! 🎵