dockergodocker-composedockerfilego-gin

Why can't I access my Gin application from local with Docker?


I am creating a web application with Go and the Gin framework. The idea is to use Docker to be able to run it in a container and also be able to debug it. So my Dockerfile is as follows:

FROM golang:1.21.6

WORKDIR /go/src/gitlab.com/main/server

COPY go.mod .
COPY go.sum .

RUN go mod download

RUN go install github.com/cosmtrek/air@latest
RUN go install github.com/swaggo/swag/cmd/swag@latest
RUN go install github.com/go-delve/delve/cmd/dlv@latest

EXPOSE 2345
EXPOSE 80

My docker compose looks like this:

version: "3.2"
services:
  service-influxdb:
    image: go-time-series
    build:
      context: ..
      dockerfile: docker/Dockerfile
    command: air -c .air.toml
    volumes:
      - ../:/go/src/gitlab.com/main/server
    ports:
      - 8080:80
      - 10000:2345
    environment:
      - WEB_APP_VERSION=0.0.1
      - WEP_APP_TITLE=Thori influx-DB
      - WEP_APP_DESCRIPTION=Micro service for the manage of the influx-db services
      - ENVIRONMENT=dev
      - HOST=localhost:8080
      - INFLUX_URL=http://localhost:8086
      - INFLUX_TOKEN=1234
      - INFLUX_ORG=Abc
      - INFLUX_MINIMUN_DATE=1677-09-21 00:12:44
      - INFLUX_MAXIMUN_DATE=2100-01-01 00:00:00

    network_mode: host

I have the VS code configuration like this:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug in Docker",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "remotePath": "/go/src/gitlab.com/main/server",
            "port": 10000,
            "host": "127.0.0.1",
            "showLog": true,
            "trace": "log",
            "logOutput": "rpc"
        },
    ]
}

The .air.toml file mentioned in the docker-compose is as follows:

root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"

[build]
  args_bin = []
  bin = "./tmp/main"
  full_bin = "dlv exec --accept-multiclient --headless --listen :2345 --api-version 2 ./tmp/main"
  pre_cmd = ["swag init -g ./cmd/main.go"]
  cmd = "go build -o ./tmp/main ./cmd/main.go"
  post_cmd = []
  delay = 0
  exclude_dir = ["assets", "tmp", "vendor", "testdata", "docs"]
  exclude_file = []
  exclude_regex = ["_test.go"]
  exclude_unchanged = true
  follow_symlink = true
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "html"]
  include_file = []
  kill_delay = "0s"
  log = "build-errors.log"
  poll = false
  poll_interval = 0
  rerun = false
  rerun_delay = 500
  send_interrupt = false
  stop_on_error = false

[color]
  app = ""
  build = "yellow"
  main = "magenta"
  runner = "green"
  watcher = "cyan"

[log]
  main_only = false
  time = true

[misc]
  clean_on_exit = true

[screen]
  clear_on_rebuild = true
  keep_scroll = true

And finally, the main of my application looks like this:

func main() {
    port := flag.Int("port", 80, "Listening port")
    flag.Parse()

    if config.Cfg.Environment == "prod" {
        gin.ForceConsoleColor()
        gin.SetMode(gin.ReleaseMode)
    }

    router := gin.Default()
    loadSwagger(router)
    loadAPI(router)
    router.Run(fmt.Sprintf(":%d", *port))
}

func loadSwagger(router *gin.Engine) {
    //  @securityDefinitions.apikey ApiKeyAuth
    //  @in                         Header
    //  @name                       Authorization

    docs.SwaggerInfo.Title = config.Cfg.WebAppTitle
    docs.SwaggerInfo.Version = config.Cfg.WebAppVersion
    docs.SwaggerInfo.Description = config.Cfg.WebAppDescription
    docs.SwaggerInfo.Host = config.Cfg.Host

    router.GET("/docs/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

I hope that my application is available locally on port 8080 and 10000 for debugging. However, when I try to access it from port 8080, nothing is running, and when I try to start debugging in VS CODE I also get an error.

The logs that appear are the following:

docker-service-influxdb-1  | [21:07:26] mkdir /go/src/gitlab.com/main/server/tmp
docker-service-influxdb-1  | [21:07:26] watching .
docker-service-influxdb-1  | [21:07:26] watching app
docker-service-influxdb-1  | [21:07:26] watching app/api
docker-service-influxdb-1  | [21:07:26] watching app/api/handlers
docker-service-influxdb-1  | [21:07:26] watching app/api/handlers/healthcheck
docker-service-influxdb-1  | [21:07:26] watching app/config
docker-service-influxdb-1  | [21:07:26] watching app/domain
docker-service-influxdb-1  | [21:07:26] watching app/domain/models
docker-service-influxdb-1  | [21:07:26] watching app/domain/ports
docker-service-influxdb-1  | [21:07:26] watching app/domain/services
docker-service-influxdb-1  | [21:07:26] watching app/repositories
docker-service-influxdb-1  | [21:07:26] watching cmd
docker-service-influxdb-1  | [21:07:26] watching docker
docker-service-influxdb-1  | [21:07:26] !exclude docs
docker-service-influxdb-1  | [21:07:26] !exclude tmp
docker-service-influxdb-1  | [21:07:26] > swag init -g ./cmd/main.go
docker-service-influxdb-1  | 2024/02/07 21:07:26 Generate swagger docs....
docker-service-influxdb-1  | 2024/02/07 21:07:26 Generate general API Info, search dir:./
docker-service-influxdb-1  | 2024/02/07 21:07:26 warning: failed to get package name in dir: ./, error: execute go list command, exit status 1, stdout:, stderr:no Go files in /go/src/gitlab.com/main/server
docker-service-influxdb-1  | 2024/02/07 21:07:26 Generating models.HealthCheck
docker-service-influxdb-1  | 2024/02/07 21:07:26 create docs.go at docs/docs.go
docker-service-influxdb-1  | 2024/02/07 21:07:26 create swagger.json at docs/swagger.json
docker-service-influxdb-1  | 2024/02/07 21:07:26 create swagger.yaml at docs/swagger.yaml
docker-service-influxdb-1  | [21:07:26] building...
docker-service-influxdb-1  | [21:07:27] running...
docker-service-influxdb-1  | API server listening at: [::]:2345
docker-service-influxdb-1  | 2024-02-07T21:07:27Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)

I feel like I'm making a silly mistake, but I can't figure out what I'm doing wrong.


Solution

  • Delete the network_mode: host line.

    Your application is starting with HTTP port 80 and port 2345 for the debugger. You can see one of these ports in the console output, and the right-hand side of ports: matches these port numbers too. However, host networking generally disables all Docker networking functionality, including the ability to remap ports. You could probably reach the application on host ports 80 and 2345 and not the remapped ports, but that's not what you're intending with this setup.