In this post, I walk through creating a simple Go web app that runs in a Docker container, and lists the hostname of the container it’s running in. I chose Go as I’ve recently gotten started writing code in Go and it’s a lot of fun to work with.
The container will install Go, so there is no need to install it locally on your machine. Docker is a prerequisite, however.
First, lets take a look at the folder structure of where to keep your dockerfile
and main.go
code.
Folder Structure
~/dockerfile
~/go/src/app/main.go
Dockerfile
The dockerfile
contains the instruction of how to build our docker image and the app to run when the container is created from the image. Let’s start by creating the dockerfile:
cd ~
touch dockerfile
Here I referenced the following Docker/Golang official image documentation. Using your favourite code editor, modify the contents of the dockerfile to look as follows:
FROM golang:1.14
WORKDIR /go/src/app
COPY . .
RUN go get -d -v ./...
RUN go install -v ./...
EXPOSE 3000
CMD ["app"]
main.go
Now let’s create the main.go file and the folder structure to store it.
mkdir ~/go
mkdir ~/go/src
mkdir ~/go/src/app
touch ~/go/src/app/main.go
Here is the contents of the main.go file:
package main
import (
"fmt"
"net/http"
"os"
)
func homePage(w http.ResponseWriter, r *http.Request) {
// get the hostname of the container
hostname, err := os.Hostname()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// print the hostname of the container
fmt.Fprintf(w, "Go App running on host: %s\n", hostname)
}
func setupRoutes() {
http.HandleFunc("/", homePage)
}
func main() {
// print to terminal if container run with -it flag
fmt.Printf("Go Web App Started on Port 3000\n")
setupRoutes()
http.ListenAndServe(":3000", nil)
}
Build the Container
To build the container, ensure you are in the ~/
directory which hosts your dockerfile, then type the following.
docker build -t go-app .
Let’s take a look at the container image by running:
docker image ls
I have two docker containers in my example. The one we just created is called go-app with an IMAGE ID of 8128cf5f8047.
Run the Container
Finally, let’s run the container from the image, but ensure we automatically delete the container after it is stopped. The -d
flag will ensure it runs detached (non-interactive), the -rm
flag will remove the container when it is stopped, and the -p
flag will map local port 3000 to port 3000 in the container
docker run -d --rm -p 3000:3000 --name running-app go-app
Let’s run the curl command to see what happens
curl localhost:3000
Go App running on host: 18987a97c027
Now browse to http://localhost:3000 to see the running container in your browser
Running docker container ls
will display the running container and it’s port mapping below.
CCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
18987a97c027 go-app "app" 13 seconds ago Up 12 seconds 0.0.0.0:3000->3000/tcp running-app
I can push the container to Docker Hub using the following commands
# Login. You will need a Docker Hub account
docker login
# tag the image. We gathered the image id earlier. You will need a Docker Hub account
docker tag 8128cf5f8047 markkerry/go-app:v1
# Push the image to Docker Hub
docker push markkerry/go-app:v1
Wrapping Up
To stop the container, simply run
docker container stop running-app
If you ran the container with the -it
(interactive) flag instead of -d
(detached), press ctrl + c
to cancel out of the interactive container session.
Running docker container ls
will show the container is no longer running and was also deleted after it stopped.
If you want to delete the image, get the IMAGE ID by running docker image ls
, then running the following (8128cf5f8047 in my example is the IMAGE ID):
docker image rm 8128cf5f8047
Next I plan the create a container which does something else than simply run a web page stating the host of the container it is running in. But this does feel like a nice first step when progressing towards Docker Swarm or Kubernetes. Also, I will hopefully look to deploy to an Azure Container Instance or Azure Kubernetes Service.