Last week at INS1GHTS Days (if you didn’t attend the event, catch the replay here: https://resources.ns1.com/ins1ghts-days-containers) we learned about containers and virtualization, and how they differ. Today, let’s pick up from where we left off by dockerizing an example Go application, then exposing it to the outside world via external DNS with your NS1 free developer account.
Before we dive in this post assumes that:
- you have a server with root privileges (and hopefully a non-root user 😉)
- A Fully Qualified Domain Name (FQDN)
- A free NS1 developer account
If you don’t, please spin up a VPS from the provider of your choice and install the flavor of Linux you prefer. Going forward, we’ll assume that you’re using Ubuntu 18.04.
Installing Docker
Before we can run our app in a container, we first need to install Docker, and before we can install Docker, we need to install its dependencies and add the Docker repository.
Once you’re in your terminal, update your package index to ensure a safe and reliable environment for installing Docker.
$ sudo apt-get update
Now install Docker’s dependencies:
$ sudo apt install curl apt-transport-https ca-certificates software-properties-common gnupg
With cURL installed you can add Docker’s GPG key:
$ curl -fsSL https://download.docker.com/li... | sudo apt-key add -
For safe measure, verify the fingerprint of the GPG key:
$ sudo apt-key fingerprint 0EBFCD88
Verify that the output of the above command matches `9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88` by looking at the last 8 characters of the `pub` as seen below:
pub rsa4096 2017-02-22 [SCEA] 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid [ unknown] Docker Release (CE deb) <[email protected]> sub rsa4096 2017-02-22 [S]
Now you can add the stable Docker repository:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/li... $(lsb_release -cs) stable"
Finally, use the apt command to install Docker:
$ sudo apt install docker-ce
With Docker installed, we can verify the status of the service, with:
$ sudo systemctl status docker
Create our Go App
With Docker installed, let’s move on to our simple app. Go (golang.org) has been taking the engineering world by storm, and for good reason: It’s fast, safe, and easy to work with. Let’s start by making a directory for our application:
$ mkdir ~/go-app && cd ~/go-app
Using the text editor of your choice, create a file for our Go app:
$ vim main.go
Add the following lines:
package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path) }) http.ListenAndServe(":80", nil) }
Introducing Dockerfile
Before running our Go app, we need to compile and pack it for execution inside a Docker container. We’ll do this using a Dockerfile. Dockerfiles are like an image of the container. This image provides the same environment every time the container runs.
First, create the Dockerfile with your text editor of choice.
Next, in the root of the project folder, create a new file named `Dockerfile`:
$ touch Dockerfile && vim Dockerfile
Add the following lines:
# Base image for building the project FROM golang:alpine AS build # Update the repository and install git RUN apk --no-cache add gcc g++ make git # Switches to tmp/app as the working directory WORKDIR /go/src/web-app COPY . . # Builds the current project to a binary called web-app RUN go get ./... RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go # Now that the project has been successfully built, we will use # alpine image to run the server FROM alpine:3.9 # Add CA certificates to the image RUN apk --no-cache add ca-certificates # Switch working directory to /usr/bin WORKDIR /usr/bin # Copies the binary file from the BUILD container to /usr/bin COPY --from=build /go/src/web-app/bin /go/bin # Exposes port 80 from the container EXPOSE 80 ENTRYPOINT /go/bin/web-app --port 80
This Dockerfile installs the compilation tools for our Go app and copies the contents of the current directory, `~/go-app`, to our container. Then it copies the compiled app and exposes port `80`, setting the app as the entry point.
Exposing Your App to the World
With your NS1 free developer account in hand, let’s head over to the dashboard (https://my.nsone.net/) and set up our first zone:
Start by clicking the Zones tab in the main navigation, and then click Add Zone.

Enter the domain name (ie. example.com) you’d like to use.

Hopping back over to your server, let’s build our Docker image by running the following command:
$ docker build -t web-app .
The last line of the output should read `Successfully tagged web-app:latest`, telling us that our image was built.
To run the container, run the following:
$ docker run --name web-app --rm -p 80:80 web-app
This command sets a name for the container, tells it to remove the container from memory when it stops, exposes the internal port 80 to your port localhost:80, and tells Docker we want to use the image we just built.
Upon execution, head over to your browser and go to http://example.com/yourname to receive our `Hello, you’ve requested %PATH_NAME%` message from our app, as seen below:

You have now successfully deployed an application on Docker.