Hey fellow gophers,
I'm building a full stack web application with the backend written in Go. I'm using docker-compose with machine for neat deployment. Currently my development dockerfile looks like this:
version: '2'
services:
caddy:
container_name:
image: abiosoft/caddy
volumes:
- ./Caddyfile:/etc/Caddyfile
- $HOME/.caddy:/root/.caddy
- ./build:/root/build
ports:
- "2015:2015"
- "80:80"
- "443:443"
links:
- goapp
depends_on:
- goapp
db:
image: postgres:latest
container_name: postgres
ports:
- "5432"
environment:
- POSTGRES_DB=goapp
- POSTGRES_PASSWORD=docker
- POSTGRES_USER=docker
goapp:
container_name: goapp
build: .
ports:
- "3000:3000"
links:
- db
depends_on:
- db
and my Main.go like this:
package main
import (
"flag"
"log"
"net/http"
"os"
"github.com/barthr/microservice/api/dto"
"github.com/barthr/microservice/api/routes"
"github.com/gorilla/handlers"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
)
var (
connName = flag.String("db", "host=db:5432 user=docker dbname=goapp sslmode=disable password=docker", "set the db connecction name")
)
func main() {
flag.Parse()
db, err := gorm.Open("postgres", *connName)
db.CreateTable("goapp").AutoMigrate(&dto.User{})
if err != nil {
log.Println(err)
}
defer db.Close()
r := routes.InitRoutes(db)
http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, r))
}
My problem is that I cannot access the DB from the docker-compose (tried with all different ports and usernames, I can connect with pgadmin). I don't understand how this is possible, am I missing something?
Thanks for you time, I appreciate it a lot.
p.s. English is not my first language
评论:
bubaflub:
docker-compose's "depends_on" controls the order in which containers are created but does not "wait" until any particular service inside of that container is ready or accepting incoming connections. From https://docs.docker.com/compose/compose-file/#/dependson:
Note: depends_on will not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.
They link to https://docs.docker.com/compose/startup-order/ which has an example script that waits for postgres to be ready.
Alternatively, you could put a small retry loop in your go program to attempt to connect to the database multiple times. For example, you could have it try to connect every second for 10 seconds or 15 seconds and then fail if a connection can't be dialed.