I have a Go app that does basic CRUD operations and uses MongoDB for data persistence.
I am using Mongo Atlas connection string to connect the app to MongoDB and things work fine when I run the application on my local dev machine. But when I push everything to a docker container, in a docker-compose workflow, I start getting this error:
server selection error: server selection timeout, current topology: { Type: ReplicaSetNoPrimary, Servers: [{ Addr: app-test-shard-00-00-zfzs6.mongodb.net:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : x509: certificate signed by unknown authority }, { Addr: app-test-shard-00-01-zfzs6.mongodb.net:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : x509: certificate signed by unknown authority }, { Addr: app-test-shard-00-02-zfzs6.mongodb.net:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : x509: certificate signed by unknown authority }, ] }
This is how my docker-compose.yml looks:
services:
redis:
image: redis
restart: always
app:
image: docker.pkg.github.com/<user>/<project>/<image>:latest
ports:
- 80:8080
environment:
- APP_ENV=docker
- GIN_MODE=release
depends_on:
- redis
restart: on-failure
This is how my connection string looks:
mongodb://user:[email protected]:27017,app-test-shard-00-01-zfzs6.mongodb.net:27017,app-test-shard-00-02-zfzs6.mongodb.net:27017/test?ssl=true&replicaSet=app-test-shard-0&authSource=admin&retryWrites=true&w=majority
I have checked this question and a couple of others, but none seem to fix this.
I also checked docker’s networking config, I am using a bridge driver, which should allow access to outside apps (i.e. Mongo Atlas)
Go Version: 1.13
Mongo Driver: mongodb/mongo-go-driver v1.2.0
Dockerfile:
FROM golang:alpine as builder
WORKDIR /build
COPY . .
RUN apk add git openssh build-base
RUN git config --global url."[email protected]:".insteadOf "https://github.com/"
COPY keys/id_rsa /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa
RUN ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts
ENV GOPRIVATE=github.com/contributor-org
RUN go build
FROM alpine
WORKDIR /org
COPY --from=builder /build/app .
COPY config/*.yml config/
RUN mkdir -p /var/log
CMD ["./app"]
DB Connection code:
type databaseClient struct { // Implements the Database interface
collection *mongo.Collection
}
func GetNewClient(cfg *config.Config, log *logger.Logger) (Database, error) {
clientOptions := options.Client().ApplyURI(cfg.Database.ConnectionString)
client, err := mongo.NewClient(clientOptions)
if err != nil {
log.Errorln(err)
}
err = client.Connect(context.Background())
if err != nil {
log.Fatalln("Failed to connect to Mongo!", err)
return nil, err
}
log.Info("Connected to Mongo!")
db := client.Database(cfg.Database.Database)
if db == nil {
err := fmt.Errorf("DB (%s) not found", cfg.Database)
log.Error(err)
return nil, err
}
collection := db.Collection(cfg.Database.Collection)
if collection == nil {
err := fmt.Errorf("Collection (%s) not found on DB (%s)", cfg.Database.Collection, cfg.Database.Database)
log.Error(err)
return nil, err
}
return &databaseClient{collection: collection}, nil
}
DB Interface:
type Database interface {
GetByBookname(context.Context, string) (*model.Book, error)
GetOneByFilter(context.Context, map[string]interface{}) (*model.Book, error)
GetAll(context.Context) ([]*model.Book, error)
GetAllByFilters(context.Context, map[string]interface{}) ([]*model.Book, error)
AddBook(context.Context, *model.Book) (string, error)
UpdateBook(context.Context, string, map[string]interface{}) (*model.Book, error)
DeactivateBook(context.Context, string) error
OverwriteBook(context.Context, string, *model.Book) (*model.Book, error)
OnboardBook(*model.Book, string, bool) (string, error)
}
2
Answers
The problem seems related to the certificate validation.
You have two options:
– add the self signed certificate to the CA.
– skip the validation.
If you want to skip the self signed certificate validation, you have to modify the
ClientOptions
struct setting totrue
theClientOptions.SSLInsecure
variable.I quick-fixed this by adding
&tlsInsecure=true
to the MongoDB URI. Still looking for the correct way to fix it though.Edit:
Solved it too adding
ca-certificates
to the Docker image:Another option for a smaller image: