0

I have two containers, one of my api in golang and the other of my mysql database... both go up correctly, but when the api connects to the container, I keep getting this try again error. I had adapted the code to try again and it works, but all the operations I perform give the same problem, so I suppose there is something wrong and I don't know what it could be. Can you help me?

As mentioned above, I adapted the code to keep trying until it works, but as it gives an error in all operations, it is kind of impracticable to adapt it to try until it works in all operations.

Here are my files:

version: '3.3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: api
    ports:
      - "8080:8080"
    env_file:
      - .env
    depends_on:
      - db
    command: ["/app/main"]
  db:
    image: mysql:5.7
    container_name: db-mysql
    restart: always
    env_file:
      - .env
    networks:
      - mysql-net
    ports:
      - "3306:3306"
    expose:
      - 3306
    volumes:
      - my-db:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d/

networks:
  mysql-net:
    driver:  bridge

volumes:
  my-db:
# Build stage
FROM golang:1.19-alpine3.16 AS builder
WORKDIR /app
COPY . .
RUN go build -o main cmd/server/main.go

# Run stage
FROM alpine:3.16
WORKDIR /app
COPY --from=builder /app/main .
COPY .env .


EXPOSE 8080
CMD [ "/app/main" ]

This is the part I get the error:

    err = db.Ping()
    if err != nil {
        panic(err)
    }
Dev Br
  • 9
  • 3

1 Answers1

0

Your containers don't have any networks: in common. Your application is on the Compose-provided default network, but the database is on a separate mysql-net network. Since they're not on the same network, they can't talk to each other.

Compose provides a network named default for you and for most application this works fine. The easiest thing to do here is to delete all of the networks: blocks from the entire file.

Once you're doing that cleanup, there are several other things you can simplify. There's a shorter form of build: if you're using the standard Dockerfile name; you don't need to manually specify container_name: or to repeat the image's command:; the obsolete expose: option does nothing and can be safely removed. This would leave you with:

version: '3.8'

services:
  app:
    build: .
    ports:
      - "8080:8080"
    env_file:
      - .env  # setting MYSQL_HOST=db
    depends_on:
      - db

  db:
    image: mysql:5.7
    restart: always
    env_file:
      - .env
    ports:
      - "3306:3306"
    volumes:
      - my-db:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d/

volumes:
  my-db:

I note one further change here. Both the container names and the Compose service names are usable as host names. Normally, though, you can do almost all operations using the Compose service name, and let Compose generate the underlying container name itself. This applies to host names for cross-container calls as well: in your .env file use the Compose service name db as a host name, rather than trying to set container_name: manually.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Hi! Thank you very much for the suggestions, I changed the docker-compose and it stopped giving that error, but now it gives the connection refused ;( – Dev Br Dec 21 '22 at 17:30
  • A Go application can start up very quickly, but it can often take the database 30-60 seconds to become usable. Do you also need [Docker Compose wait for container X before starting Y](https://stackoverflow.com/questions/31746182/docker-compose-wait-for-container-x-before-starting-y)? – David Maze Dec 21 '22 at 18:17
  • That's right, to work here I used the ```wait-for``` script. Thanks a lot for the help!!! – Dev Br Dec 21 '22 at 20:04