Halil Yıldırım
Halil Yıldırım

Reputation: 127

Why can't I connect to mongodb in docker network

My dockerfile

FROM golang:1.18

WORKDIR /usr/src/app

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

COPY . .
RUN go build -o app

CMD ["./app"]

My docker-compose file

version: "3.7"

services:
 api:
 container_name: 'api'
 build: './'
 ports:
      - '8080:8080'
 volumes:
      - './:/go/src/app'
 depends_on:
      - 'mongodb'
      - 'redis'
 networks:
      - api-network
 mongodb:
 image: mongo:latest
 ports:
      - "27017:27017"
 volumes:
      - ./data/mongo:/data/db
 networks:
      - api-network
 redis:
 image: redis:alpine
 ports:
      - "6379:6379"
 volumes:
      - ./data/redis:/data
 networks:
      - api-network
networks:
 api-network:

My go code

package main

import (
    "context"
    "fmt"
    "go-redis/handler"
    "net/http"
    "os"
    "os/signal"
    "strconv"
    "time"

    "github.com/go-redis/redis/v8"
    "github.com/go-redis/redis_rate/v9"
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
    "github.com/labstack/gommon/log"
    "gopkg.in/mgo.v2"
)

var limiter *redis_rate.Limiter

func main() {
    rdb := redis.NewClient(&redis.Options{
        Addr: "redis:6379",
    })
    limiter = redis_rate.NewLimiter(rdb)
    e := echo.New()
    e.Logger.SetLevel(log.ERROR)
    e.Use(middleware.Logger())
    e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
        Level: -1,
    }))
    e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
        SigningKey: []byte(handler.JWT_KEY),
        Skipper: func(c echo.Context) bool {
            // Skip authentication for signup and login requests
            if c.Path() == "/login" || c.Path() == "/signup" || c.Path() == "/all" || c.Path() == "" {
                return true
            }
            return false
        },
    }))
    e.Use(rateLimiting)
    db, err := mgo.Dial("mongodb://mongodb:27017")
    if err != nil {
        e.Logger.Fatal(err)
    }
    // Create indices
    if err = db.Copy().DB("twitter").C("users").EnsureIndex(mgo.Index{
        Key:    []string{"email"},
        Unique: true,
    }); err != nil {
        log.Fatal(err)
    }
    // Initialize handler
    h := &handler.Handler{DB: db, Rdb: rdb}

    // Routes
    e.POST("/signup", h.SignUp)
    e.POST("/login", h.SignIn)
    e.POST("/follow/:id", h.FollowUser)
    e.POST("/posts", h.NewPost)
    e.GET("/feed", h.FetchPosts)
    e.GET("/users", h.GetUsers)
    e.GET("/all", h.AllPosts)
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "hello world")
    })

    go func() {
        // Start server
        e.Logger.Fatal(e.Start(":1323"))
    }()
    closingChannel := make(chan os.Signal, 1)
    signal.Notify(closingChannel, os.Interrupt)
    <-closingChannel
    fmt.Println("starting to shut down the server...")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    if err := e.Shutdown(ctx); err != nil {
        fmt.Println("couldnt shut down the server...")
    }
}

func rateLimiting(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        res, err := limiter.Allow(c.Request().Context(), "project:123", redis_rate.PerMinute(10))
        if err != nil {
            return err
        }
        h := c.Response().Header()
        h.Set("RateLimit-Remaining", strconv.Itoa(res.Remaining))
        log.Printf("Remaining %d", res.Remaining)
        if res.Allowed == 0 {
            // We are rate limited.

            seconds := int(res.RetryAfter / time.Second)
            h.Set("RateLimit-RetryAfter", strconv.Itoa(seconds))

            // Stop processing and return the error.
            return c.JSON(http.StatusTooManyRequests, "Rate limit exceeded")
        }

        // Continue processing as normal.
        return next(c)
    }
}

I get no reacable servers error. When I change hostnames with localhost and run go run main.go there are no errors but when I want to run go application in docker env and I can't connect to another container from go container.

I thought it was because mongodb is not running. But the go app depend on that so it should be running before go file got executed.

Can you help me with this problem?

Update:

I know it is not related but I changed ports in docker-compose with the same as application port which is 1323.

Still getting this error

{"time":"2022-06-08T09:19:29.1670281Z","level":"FATAL","prefix":"echo","file":"main.go","line":"47","message":"no reachable servers"}

On line 47. I am logging the error when connecting to mongodb.

Upvotes: 1

Views: 341

Answers (1)

nvidot
nvidot

Reputation: 1412

What is the host OS ?

I've tested your code (commenting out what is related to go-redis/handler) and it results that the first run is succesfull but the subsequent runs fail (though in this cases, the mongodb container fails to start) giving the exact same error message you get in the go app.

The fault happens when mongodb container is stopped and database get written to disk. If the mount for mongodb container is removed (i.e. use a docker volume) then subsequent runs are ok.

So may be the solution would be to use a docker volume in your docker compose setup.

EDIT: Unless the OP add more context, this seems as a duplicate of this and the answer is indeed related to the use of mounted volume for data persistence.

Upvotes: 1

Related Questions