[GO] Solution for inaccessible Gin server running on Docker container

Overview

I tried to deploy and run an API server using Golang's web framework Gin on a Docker container, but I could not access the API. I was bothered for quite a long time.

As a result, I found that it was a problem of how to write the code of the Gin server, but I will write down the solution here just in case.

By the way, this error happened on Ubuntu server (t2.small) on Windows 10 and AWS (although the execution environment didn't seem to have much to do with the occurrence of this error).

Status

I was trying to set up an API server using Gin. Since it is still in the stage of building the environment, the code is a mock like the one below.

package main

import (
	"log"
	"os"
	"github.com/gin-gonic/gin"
)

func main() {
	logConfig()

	r := gin.Default()
	r.GET("/accounting-api", func(c *gin.Context) {
		log.Println("GET")
		c.JSON(200, gin.H{
			"state": "success",
		})
	})
	r.DELETE("/accounting-api", func(c *gin.Context) {
		log.Println("DELETE")
		c.JSON(200, gin.H{
			"state": "success",
		})
	})
	log.Println("Start Server")
	r.Run()
}

func logConfig() {
	logFile, _ := os.OpenFile("log/log.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	log.SetOutput(logFile)
	log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile)
	log.SetPrefix("[LOG] ")
}

It's a server that simply returns a json of {"state ":" success "} when a request for a particular path comes in with the GET or DELETE method.

And the Dockerfile to run this server is below.

FROM golang:alpine
RUN apk update && apk add --no-cache git
RUN go get -u github.com/gin-gonic/gin && mkdir /usr/src && mkdir /usr/src/api
COPY ./api /usr/src/api
WORKDIR /usr/src/api
CMD ["go","run","main.go"]

Since the above Go file etc. is in the directory ʻapi on the host, copy it to the container and start the server. I built this Dockerfile with the name ʻapi and launched it with the following command.

docker run -p 8083:8080 api

Mapping port 8083 on the host to port 8080 on the container. When you execute the above command, the following output will be output, and you can confirm that the Gin server is up.

[GIN-debug] GET    /accounting-api           --> main.main.func1 (3 handlers)
[GIN-debug] DELETE /accounting-api           --> main.main.func4 (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on localhost:8080

I didn't specify a port, so it's running on port 8080 by default. At first glance, it looks like it's working properly, but when I try to access http: localhost: 8083 with curl on the host side, I get the following error.

curl: (52) Empty reply from server

What I tried to resolve the error

1. Go inside the container and check if you can access the API

First of all, make sure that the Go program is really running on the container. Let's go inside the docker container that was launched for that purpose.

#Go inside the running container of the api server
docker exec -it api /bin/ash

Alpine, which is the base of this container, did not have / bin / bash, so use / bin / ash. Then type the following command to see if the program is working properly.

#Since curl is not included in the first place, install it
apk add --no-cache curl
#Just in case, disable the proxy and access the api server with curl
curl -x "" http://localhost:8080/accounting-api

Here is the execution result of curl.

{"state": "success"}

The results are getting good. So, it seems that the Gin server program is running properly on the container.

2. EXPOSE the port in the Dockerfile

The program seems to be running on the container, so next I suspect that the port mapping part is not working. When I looked it up, it seems that the command ʻEXPOSE` can be written in the Dockerfile, so I will add it.

EXPOSE 8080

Doing this didn't help.

In the first place, according to the official docs, the ʻEXPOSE command doesn't really do anything and tells the developer to open a specific port. It seems that it only has a document-like role for. So, just adding the ʻEXPOSE command couldn't solve the problem.

3. Check Windows firewall settings

Since development was basically done with Docker on Windows, I reviewed the Windows firewall settings, but this also didn't make sense.

In the first place, when I built this Dockerfile on Ubuntu and launched it, I could not access the API server as well, so I knew from the beginning that it was not due to the Windows firewall.

4. (This is the solution) Specify the port on the Gin server side

In the Go program, I tried to specify the port in the part that starts the GIn server, and now I can access it well. Specifically, it is the following part.

r := gin.Default()
r.Run(":8080")

I didn't care because it starts up with 8080 by default even if I don't specify anything, but it seems to be useless if I don't specify it properly.

I'm not sure why the port is bad by default and must be explicitly stated. I will add it when I understand it.

Recommended Posts

Solution for inaccessible Gin server running on Docker container
Build CGI Server running on Python 3 on Docker
Try running tensorflow on Docker + anaconda
Tips for running Go with docker
Start Docker container when running Pytest
Run Matplotlib on a Docker container
Dockerfile: Install Docker on your Linux server
Run matplotlib on a Windows Docker container
Enter into stdin of the running Docker container