MakeUseOf logo

Containerizing Go Apps With Docker

docker logo
Image credit: Rubaitul Azad/ Unsplash
URL; https://unsplash.com/photos/HSACbYjZsqQ
No attribution required
Goodness is a highly experienced technical writer and backend engineer who specializes in building scalable systems using Go and Rust. With 4 years of industry experience and 3 years of technical writing experience, Goodness has honed his skills in these languages and enjoys sharing his knowledge with the community.

Aside from his contributions to MUO, Goodness has also written over 200 technical articles for reputable companies such as DigitalOcean, LogRocket, MatterMost, and FreeCodeCamp. His writing focuses on topics related to Go, Rust, Web3, data, and backend engineering. Goodness's articles are highly regarded in the industry for their quality, depth, and relevance.

Goodness's expertise in these areas is supported by his certifications in Go and Rust, as well as his attendance at industry conferences and his efforts to stay up-to-date on the latest trends and technologies. He is a passionate and dedicated professional who is always striving to improve his skills and knowledge.
Sign in to your MakeUseOf account

Docker is the most popular containerization technology owing to its simplicity and ease of use. Docker relieves the stress of portability issues in software development and distribution. You can deploy your docker containers to most cloud service providers.

Containerizing your Go apps with Docker can help you ensure consistent and reliable deployment across different environments. You can deploy your Go apps to different environments like development, staging, and production. Docker containers are lightweight and take up less space than traditional virtual machines. This can save you money on hosting costs, and it can also make your deployments faster.

Setting Up a Simple Web Server in Go

The Go standard library contains the packages you’ll need to set up a simple web server.

First, import the http, log, and json packages. You’ll use Go's http package to set up the server and GET request endpoint. The log package for logging possible errors to your console. The json package for encoding a struct to JSON for the API endpoint.

import (
 "encoding/json"
 "log"
 "net/http"
)

You can encode a struct instance as JSON to the client as a response based on the validity of the request as thus:

type Message struct {
 Response string `json:"response"`
 Description string `json:"description"`
}

The handler function would return a successful message to the client if the request to the endpoint is a GET request.

// dockerTestEndpoint handles the API endpoint for testing Docker connectivity
func dockerTestEndpoint(writer http.ResponseWriter, request *http.Request) {
 // Set the response header to indicate JSON content
 writer.Header().Set("Content-Type," "application/json")
 // If the request method is GET
 if request.Method == "GET" {
 // Set the response status code to 200 OK
 writer.WriteHeader(http.StatusOK)
 // Create a message struct for a successful response
 message := Message{
 Response: "Successful",
 Description: "You've successfully hit the API endpoint " +
 "From your Docker Container",
 }
 // Encode the message as JSON and send it as the response
 err := json.NewEncoder(writer).Encode(&message)
 if err != nil {
 return
 }
 } else {
 // If the request method is not GET
 // Set the response status code to 400 Bad Request
 writer.WriteHeader(http.StatusBadRequest)
 // Create a message struct for a bad request response
 message := Message{
 Response: "Bad Request",
 Description: "You've successfully hit the API endpoint From your " +
 "Docker Container, But you made a bad request",
 }
 // Encode the message as JSON and send it as the response
 err := json.NewEncoder(writer).Encode(&message)
 if err != nil {
 return
 }
 }
}

You set up the handler function in the main function with the route as /api/docker/go. The dockerTestEndpoint handler function validates that the request to the handler is a GET request. If it's a GET request, it encodes an instantiated Message struct instance to the client based on the request's status.

Here’s how you can mount the handler function on a route and setup the server to run on port 8080:

func main() {
 // Register the handler function 'dockerTestEndpoint'
 // to handle requests for the "/api/docker/go" URL.
 http.HandleFunc("/api/docker/go", dockerTestEndpoint)
 // Start the HTTP server and listen for incoming requests on port 8080.
 err := http.ListenAndServe(":8080", nil)
 if err != nil {
 log.Fatalln("There's an error with the server:", err)
 }
}

The main function is the server's entry point, which listens on port 8080. The HandleFunc method mounts the routes on the handler function. The ListenAndServe method starts the server on the specified local host port 8080.

Getting Started Containerizing Your Go Apps With Docker

After installing and setting up Docker, you’ll need a Docker file named Dockerfile to create and build a Docker image for your Go app. You’ll specify commands for the base image and commands to copy the files, add the working directory, and run the app in the Dockerfile.

Run this command in the terminal of your workspace to create a Dockerfile.

touch Dockerfile

You’ll specify the commands for building your Docker image in the Dockerfile.

If there are any files you want to separate from your Docker image, you can use a .dockerignore file. The .dockerignore files work exactly like .gitignore files.

touch .dockerignore

Next, you’ll specify build commands in your Dockerfile to containerize your apps.

Defining Commands in the Dockerfile

[画像:ubuntu running as a docker container]
Image by Image by ADMC from Pixabay (No attribution required)

Dockerfiles are customizable based on your project’s specifications. You’ll define commands to build the base image for building the application.

Here’s an example of the contents of a Dockerfile that builds the web server above:

# Use a Golang base image
FROM golang:latest
# Set the working directory inside the container
WORKDIR /app
# Copies all the files in the local directory to the working directory in the container
COPY . .
# Download the Go module dependencies
RUN go mod download
# Build the Go application
RUN go build -o app
# Set the entry point for the application
ENTRYPOINT ["./app"]

The Dockerfile uses golang:latest base image, to build the app after setting the working directory to /app.

The Dockerfile copies the files with the COPY command and downloads dependencies with the RUN command.

The file specifies a build and run operation with the RUN command, then sets the command to run when the container starts with the CMD command.

Save the Dockerfile in the same directory as your go.mod and main.go files; then run this command to build a Docker image from this Dockerfile:

docker build -t GolangTutorial .

The above command will create a Docker image with the tag golangtutorial. You can run a container with this command:

docker run -p 8080:8080 golangtutorial

The command maps port 8080 from the container to port 8080 on the localhost of the host machine. You can request the server running in the Docker container from the host machine.

Here’s the result from sending the CURL request to the server, this time running on Docker:

[画像:Result from making requests to the Docker container]
image credit: Ukeje Goodness Screenshot

You Can Use Docker Compose for Container Orchestration

Docker Compose is a tool that you can use to orchestrate (work with many) Docker containers. Docker Compose allows you to define a multi-container application in a single YAML file. You can run and manage the entire application with a single command.

You can use Docker Compose for deploying and managing complex containerized applications. Docker Compose simplifies management with automated and consistent deployments.

AltStyle によって変換されたページ (->オリジナル) /