How to use docker init command to containerize a go application

DockerDockerBeginner
Practice Now

Introduction

In this lab, you will learn how to containerize a Go application using the docker init command. The lab begins by verifying the correct installation of Docker Desktop on the LabEx VM, including checking the Docker version and running the hello-world container to ensure Docker is functioning as expected.

The subsequent steps involve initializing a Go project with docker init, customizing the generated Dockerfile and Compose file specifically for a Go application, and finally, building and running the Go application using Docker Compose. This hands-on experience will provide you with the skills to effectively containerize Go applications using modern Docker tools.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/SystemManagementGroup(["System Management"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/logs("View Container Logs") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/SystemManagementGroup -.-> docker/version("Show Docker Version") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/run -.-> lab-555164{{"How to use docker init command to containerize a go application"}} docker/logs -.-> lab-555164{{"How to use docker init command to containerize a go application"}} docker/create -.-> lab-555164{{"How to use docker init command to containerize a go application"}} docker/pull -.-> lab-555164{{"How to use docker init command to containerize a go application"}} docker/version -.-> lab-555164{{"How to use docker init command to containerize a go application"}} docker/build -.-> lab-555164{{"How to use docker init command to containerize a go application"}} end

Install Docker Desktop and Verify Docker Init

In this step, we will verify that Docker is installed correctly on the LabEx VM. The LabEx VM comes pre-installed with Docker Engine, so we will check the Docker version and run a simple "hello-world" container to ensure everything is working as expected.

First, let's check the Docker version. Open a terminal in the LabEx VM. You can find the terminal icon on the desktop or in the applications menu.

Execute the following command in the terminal:

docker --version

This command will display the Docker version installed on the system. You should see output similar to:

Docker version 20.10.21, build xxxxxxx

If you see the Docker version, it means Docker is installed correctly. If you encounter an error, please contact support.

Next, let's run the "hello-world" container. This is a simple container that prints a message to the console and then exits.

Execute the following command in the terminal:

docker run hello-world

Before running the command, you need to pull the hello-world image from Docker Hub. Docker Hub is a public registry for Docker images.

Execute the following command to pull the image:

docker pull hello-world

This command downloads the hello-world image from Docker Hub to your local machine. You should see output similar to:

Using default tag: latest
latest: Pulling from library/hello-world
...
Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest

Now, execute the docker run hello-world command again:

docker run hello-world

This command will run the hello-world container. You should see output similar to:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

This message indicates that Docker is working correctly and you have successfully run your first container!

Initialize a Go Project with Docker Init

In this step, we will initialize a new Go project and use docker init to generate the necessary Dockerfile and docker-compose.yml files. This will provide a starting point for containerizing our Go application.

First, let's create a new directory for our Go project. Open a terminal in the LabEx VM and execute the following commands:

mkdir my-go-app
cd my-go-app

These commands create a new directory named my-go-app in the ~/project directory and then change the current directory to my-go-app.

Next, we need to initialize a Go module. This will create a go.mod file that tracks the dependencies of our project.

Execute the following command in the terminal:

go mod init my-go-app

This command initializes a new Go module named my-go-app. You should see output similar to:

go: creating new go.mod: module my-go-app
go: to add module requirements and sums:
        go mod tidy

Now, let's create a simple Go application. Create a new file named main.go in the my-go-app directory using the nano editor:

nano main.go

Add the following code to the main.go file:

package main

import "fmt"

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

This is a simple Go program that prints "Hello, Docker!" to the console.

Save the file and exit the nano editor by pressing Ctrl+X, then Y, and then Enter.

Now, we will use docker init to generate the Dockerfile and docker-compose.yml files. However, the LabEx VM does not have Docker Compose installed by default. We need to install it first.

Download the latest version of Docker Compose using curl:

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Make the Docker Compose binary executable:

sudo chmod +x /usr/local/bin/docker-compose

Verify the installation by checking the Docker Compose version:

docker-compose --version

You should see output similar to:

docker-compose version 1.29.2, build xxxxxxx

Now that Docker Compose is installed, we can proceed with docker init.

Execute the following command in the terminal:

docker init

docker init will ask a series of questions to configure the Dockerfile and docker-compose.yml files. Here are the recommended answers for this lab:

  • What do you want to call this application? my-go-app
  • What port is this app listening on? 3000 (This is a placeholder, we won't actually use a port in this simple example)
  • What is the main file to execute? main.go
  • Would you like to include the Docker Compose configuration? Yes
  • Please choose a Docker Compose version: 2.0

After answering these questions, docker init will generate a Dockerfile and a docker-compose.yml file in the my-go-app directory.

You can view the contents of the generated files using the cat command:

cat Dockerfile
cat docker-compose.yml

These files provide a basic configuration for building and running our Go application in a Docker container. In the next step, we will customize these files to better suit our needs.

Customize the Generated Dockerfile and Compose File for Go

In this step, we will customize the Dockerfile and docker-compose.yml files generated in the previous step. We will optimize the Dockerfile for building our Go application and configure the docker-compose.yml file to run our application.

First, let's examine the generated Dockerfile. Open the Dockerfile in the my-go-app directory using the nano editor:

nano Dockerfile

The generated Dockerfile might look something like this:

## syntax=docker/dockerfile:1

FROM golang:latest AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . .

RUN go build -o my-go-app

FROM alpine:latest

WORKDIR /app

COPY --from=builder /app/my-go-app .

EXPOSE 3000

CMD ["./my-go-app"]

This Dockerfile uses a multi-stage build. The first stage (builder) uses the golang:latest image to build the Go application. The second stage uses the alpine:latest image to run the application.

Let's modify the Dockerfile to use a specific Go version and optimize the build process. Replace the contents of the Dockerfile with the following:

## syntax=docker/dockerfile:1

FROM golang:1.17 AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . .

RUN go build -o my-go-app

FROM alpine:latest

WORKDIR /app

COPY --from=builder /app/my-go-app .

CMD ["./my-go-app"]

We have changed the base image for the builder stage to golang:1.17. This ensures that we are using a specific Go version for building our application.

Save the file and exit the nano editor.

Now, let's examine the generated docker-compose.yml file. Open the docker-compose.yml file in the my-go-app directory using the nano editor:

nano docker-compose.yml

The generated docker-compose.yml file might look something like this:

version: "3.9"
services:
  my-go-app:
    build: .
    ports:
      - "3000:3000"

This docker-compose.yml file defines a single service named my-go-app. It specifies that the service should be built from the current directory (.) and that port 3000 should be exposed.

Since our application doesn't actually listen on a port, we can remove the ports section. Modify the docker-compose.yml file to the following:

version: "3.9"
services:
  my-go-app:
    build: .

Save the file and exit the nano editor.

In this step, we have customized the Dockerfile and docker-compose.yml files to better suit our needs. In the next step, we will build and run our Go application using Docker Compose.

Build and Run the Go Application with Docker Compose

In this step, we will build and run our Go application using Docker Compose. Docker Compose simplifies the process of building and running multi-container applications. In our case, we only have one container, but Docker Compose still provides a convenient way to manage the build and run process.

First, navigate to the my-go-app directory in the terminal:

cd ~/project/my-go-app

To build the Docker image for our application, execute the following command:

docker-compose build

This command will build the Docker image based on the Dockerfile in the current directory. You should see output similar to:

Building my-go-app
Sending build context to Docker daemon  3.072kB
Step 1/6 : FROM golang:1.17 AS builder
 ---> xxxxxxxxxxxxxxxx
Step 2/6 : WORKDIR /app
 ---> Using cache
 ---> xxxxxxxxxxxxxxxx
Step 3/6 : COPY go.mod go.sum ./
 ---> Using cache
 ---> xxxxxxxxxxxxxxxx
Step 4/6 : RUN go mod download && go mod verify
 ---> Using cache
 ---> xxxxxxxxxxxxxxxx
Step 5/6 : COPY . .
 ---> xxxxxxxxxxxxxxxx
Step 6/6 : RUN go build -o my-go-app
 ---> Running in xxxxxxxxxx
Removing intermediate container xxxxxxxxxx
 ---> xxxxxxxxxxxxxxxx
Successfully built xxxxxxxxxxxxxxxx
Successfully tagged my-go-app_my-go-app:latest

This output indicates that the Docker image has been built successfully.

Now, to run the application, execute the following command:

docker-compose up

This command will start the container defined in the docker-compose.yml file. You should see output similar to:

Starting my-go-app_my-go-app_1 ... done
Attaching to my-go-app_my-go-app_1
my-go-app_1  | Hello, Docker!
my-go-app_my-go-app_1 exited with code 0

This output shows that our Go application has been executed and printed "Hello, Docker!" to the console. The container then exited with code 0, indicating successful execution.

To stop the container, press Ctrl+C in the terminal.

You can also run the container in detached mode by adding the -d flag to the docker-compose up command:

docker-compose up -d

This will start the container in the background. To view the logs of the container, execute the following command:

docker logs my-go-app_my-go-app_1

To stop the container running in detached mode, execute the following command:

docker-compose down

This command will stop and remove the container.

In this step, we have successfully built and run our Go application using Docker Compose. This demonstrates how Docker Compose can simplify the process of managing containerized applications.

Summary

In this lab, we began by verifying the successful installation of Docker Desktop on the LabEx VM. This involved checking the Docker version using the docker --version command and confirming its proper installation. We then proceeded to pull the hello-world image from Docker Hub using docker pull hello-world and subsequently ran the container with docker run hello-world to ensure Docker was functioning as expected, printing a confirmation message to the console.

This initial step established a working Docker environment, laying the groundwork for subsequent steps involving the use of docker init to containerize a Go application.