Little http go server inside docker container
Tags: go, docker, microservices, rest
Published: 2021-11-03 13:01:56

---
title: Little http go server inside docker container
published: true
description: a step by step guide to create the simplest http server in the world!
tags: go, docker, microservices, rest
series: go
---

## Before starting

We are going to create a new project with go. First time to do is to create a folder with our project name. My personal suggestion is to create a `development` folder in our home. And inside dev folder all our projects such this:

 - ~/development/github.com/sensorario/go-docker.

## On Github

This project is made following [this project](https://github.com/sensorario/go-docker). In main branch you can find same code you can see here. The project went on since a wrote this article as draft. You are free to check [first release](https://github.com/sensorario/go-docker/releases/tag/v1.0.0) ([v1.0.0](https://github.com/sensorario/go-docker/releases/tag/v1.0.0)) here.

## Go Http server

What we need for this trivial example is the code of the simplest http server. Obviously written using go. Because the focus is not to write a complete go example but only its integration inside a docker container the example will be nothing more a simple hello world http server.

```go
package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", HelloServer);
    http.ListenAndServe(":5000", nil);
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, world!");
}
```

This content must be saved in file `main.go` inside the root folder of our project. We will not build the file in our machine but we will do it inside the container and specifically inside the Dockerfile.

## Dockerfile

Let's go on the creation of this exercise creating the Dockerfile. First of all we must specify the go image we want to start from.

```go
FROM golang
```

Because of we are not specifying the go version, it will be the latest. Second command we need is the creation of the app folder. This folder will contains sources of our program.

```go
RUN mkdir /app
```

Once created, folder designed to contain sources of our application, we will copy all the content of our project in the app folder.

```go
ADD . /app
```

And then, we will specify the desire to execute every next command like we are placed inside `app/` folder. In other words, we now will set `app/` folder as working folder.

```go
WORKDIR /app
```

After the copy of all the code here, we need to build our go application. The command tu run is very very simple and it means that our go project will generate an executable called main in current folder (`-o main .`).

```go
RUN go build -o main .
```

We are close to finish Dockerfile. As the most attentive readers will have noticed the go program listen port 5000. The port exposed by the container is 5000. Value is arbitrary. Expose a port is necessary to the container to be reached from our host. Host is our machine.

```go
EXPOSE 5000
```

Last but not least, the command that run the just created executable.

```go
CMD ["/app/main"]
```

The following is the final result.

```go
FROM golang
RUN mkdir /app
ADD . /app
WORKDIR /app
RUN go build -o main .
EXPOSE 5000
CMD ["/app/main"]
```

Easy! Isn't it?

## docker-compose.yaml

To make our life easier, we create a docker-compose file in which configuring and managing docker in general becomes easier. In this file it says where the Dockerfile is, which ports are exposed and then it says that you want to share the volume. What is the folder of our project corresponds to the folder `/opt/app/api`.

```yaml
version: "3.9"
services:
    app:
        build:
            dockerfile: Dockerfile
            context: .
        volumes:
            - .:/opt/app/api
        ports:
            - "5000:5000"
```

## Makefile

> If you are not familiar with Makefile please [read this article](https://dev.to/sensorario/a-brief-introduction-to-what-makefiles-are-3fb1).

Sometimes learning so many commands becomes difficult, at least for me. That's why in every project I add a makefile that makes my life easier. In our Makefile we then add a command that allows us to pull up this container.

> generally my Dockerfile contains up, down, build, bash_mysql and so on

```make
up:
	docker-compose up -d --build
```

Then we run the `make` command. The result should be approximately the following.

```bash
​​docker-compose up -d --build
Building app
[+] Building 3.5s (11/11) FINISHED
 => [internal] load build definition from Dockerfile
 => => transferring dockerfile: 146B
 => [internal] load .dockerignore
 => => transferring context: 2B
 => [internal] load metadata for docker.io/library/golang:latest
 => [auth] library/golang:pull token for registry-1.docker.io
 => [1/5] FROM docker.io/library/golang@sha256:124966f5d54a41317ee81ccfe5f849d4f...
 => [internal] load build context
 => => transferring context: 465B
 => CACHED [2/5] RUN mkdir /app
 => [3/5] ADD . /app
 => [4/5] WORKDIR /app
 => [5/5] RUN go build -o main .
 => exporting to image
 => => exporting layers
 => => writing image sha256:940d9cb837f6f0ccc21178699ee336ca5195b89d648df3b3...
 => => naming to docker.io/library/go-docker_app
```

## Call the server

We said that our container exposes port 5000 and that we have built a small server to listen in that port. And make is called, ... Now we just have to test it with a simple command like curl.

```bash
curl http://localhost:5000
Hello, world!
```

It works! Thank you!