14
respostas

docker compose com mysql

Boa noite. Estou criando um projeto com spring boot e mysql. Estou tendo um problema pois o camando depends_on não está funcionando visto que os containers que eu crio no docker compose sempre startam no mesmo momento, assim quando a aplicação sobe o mysql ainda não terminou de inciar. Há alguma forma de contornar esse problema?

14 respostas

Oi Henrique, tudo bem? Você poderia disponibilizar seu compose pra gente dá uma olhada e entender melhor como ele está estruturado?

Bom dia Wanderson. Desculpe a demora. Então, esse problema eu consegui resolver. Agora estou com outro. Estou tentando fazer o load balance com uma aplicação angular + spring boot porém sem sucesso. Quando executo o docker compose os serviços iniciam corretamente, eu consigo acessar a plicação porém ele utiliza apenas o serviço node1. É como se a configuração

upstream node-upstream {
              least_conn;

              server node1:8080;
              server node2:8080;
              server node3:8080;

              keepalive 64;
        }

não funcionasse.

Seguem meus arquivos de configuração

nginx.conf

worker_processes 4;

events { worker_connections 1024; }

http {    

      proxy_cache_path          /var/cache/nginx levels=1:2 keys_zone=one:8m max_size=3000m inactive=600m;
        proxy_temp_path         /var/tmp;
        include                 mime.types;
        default_type            application/octet-stream;
        sendfile                on;
        keepalive_timeout       65;

        gzip                    on;
        gzip_comp_level         6;
        gzip_vary               on;
        gzip_min_length         1000;
        gzip_proxied            any;
        gzip_types              text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_buffers            16 8k;

        upstream node-upstream {
              least_conn;

              server node1:8080;
              server node2:8080;
              server node3:8080;

              keepalive 64;
        }

        server {
              listen 4200; 

              server_name localhost;  
              root  /var/www/public/dist;  
              index index.html index.htm; 
              # Handle static files              

              location localhost:8080/ {
                  proxy_pass            http://node-upstream;

              }

              #return  301 https://$server_name$request_uri;
        }


}

docker-compose.yml

version: '3'

networks: 
  production-network:    
    #driver: bridge
    external:
      name: minha-rede

services: 
  batistagases_bd:
    container_name: batistagases_bd
    environment:       
      MYSQL_USER: root      
      MYSQL_ROOT_PASSWORD: admin      
    image: mysql
    ports: 
      - "3307:3307"
    networks: 
      - production-network    

  nginx:
    build:
      dockerfile: nginx.dockerfile
      context: .
    image: batistagases/nginx
    container_name: nginx
    ports: 
      - "4200:4200"
    networks: 
      - production-network    
    depends_on:   
      - batistagases_bd    
      - node1
      - node2
      - node3


  node1:
    build:
      dockerfile: /api.dockerfile
      context: /projetos-java/algaworks/batistagases-api
    image: batistagases-api
    container_name: node1
    ports:
      - "8080:8080"    
    networks: 
      - production-network    
    depends_on:   
      - batistagases_bd
    command: ./wait-for-it.sh a java -jar batistagases-1.0.0.jar

  node2:
    build:
      dockerfile: /api.dockerfile
      context: /projetos-java/algaworks/batistagases-api
    image: batistagases-api
    container_name: node2
    ports:
      - "8081:8080"    
    networks: 
      - production-network    
    depends_on:   
      - batistagases_bd
      - node1
    command: ./wait-for-it.sh a java -jar batistagases-1.0.0.jar

  node3:
    build:
      dockerfile: /api.dockerfile
      context: /projetos-java/algaworks/batistagases-api
    image: batistagases-api
    container_name: node3
    ports:
      - "8082:8080"    
    networks: 
      - production-network    
    depends_on:   
      - batistagases_bd
      - node2
    command: ./wait-for-it.sh a java -jar batistagases-1.0.0.jar



Não cara, não usa nginx usa o proprio docker para fazer o load balance só declarar no docker compose a quantidade de replicadas que ele faz isso sozinho.

Usando Swarm ou docker compose

só adicionar a sessão de replicas.

 backend:
    build:
      dockerfile: /api.dockerfile
      context: /projetos-java/algaworks/batistagases-api
    image: batistagases-api
    container_name: node1
    deploy:
        replicas: 3
    ports:
      - "8080:8080"    
    networks: 
      - production-network    
    depends_on:   
      - batistagases_bd
    command: ./wait-for-it.sh a java -jar batistagases-1.0.0.jar

Usando dessa forma o load balance é feito automaticamente sem necessidade de configuração e sem o problema do nginx onde você pode ter downtime se algum container cair.

E aí Vinicis, blz? Então, fiz o que vc recomendou mas ele só criou um container (o node 1).

Eu fiz o seguinte: exclui o node2 e node3 do arquivo docker-compose.yml e adicionei o deply: replicas:3.

No arquivo do nginx.conf eu deixei apenas o node1

upstream node-upstream {
              least_conn;

              server node1:8080;
              #server node2:8080;
              #server node3:8080;

              keepalive 64;
        }

Teria alguma outra configuração a fazer?

Certo, mas você não vai mais precisar do Nginx usando dessa forma, e estranho isso de ter criado apenas um container, você está subindo como uma Stack Swarm ou com Docker-Compose up -d ?

Vinicius, então, o deploy com replicas, só funciona com swarm ou outra stack de production, a documentação mesmo comenta sobre o comando ser ignorado pelo compose up e compose run.

https://docs.docker.com/compose/compose-file/#deploy

Henrique, olha o seguinte, no seu upstream todos os serviços estão configurados com a porta 8080:

upstream node-upstream {
              least_conn;

              server node1:8080;
              server node2:8080;
              server node3:8080;

              keepalive 64;
}

Mas no seu docker-compose, os serviços nodes estão com portas diferentes abertas: 8080, 8180, 8280 no Host.

Considerando isso, apenas um dos containers vai conseguir responder a requisição, que é o primeiro container.

Faz sentido?

Bom dia Wanderson. Então, eu já tentei de várias maneiras. Essas portas abertas já foi uma outra tentativa. O que acontece: considerando o meu docker-compose que publiquei, já coloquei as portas apenas assim

ports:
      - "8080"

para todos os nodes (node1, node2, node3) e no arquivo do nginx coloquei dessa forma

          server node1:8080;
              server node2:8080;
              server node3:8080;

pois como o nginx iria redirecionar as requisições, cada container estava apontando para a sua própria porta 8080 sendo que eles estão na mesma rede. Porém não funcionou. As requisições eram enviadas apenas para o node1. O que parece é que o arquivo nginx.conf não está executando o redirecionamento das requisições. Teria alguma idéia do que pode ser?

Oi Henrique, me aprofundando melhor na documentação, entendi que você está usando uma outra estratégia de load balance que a padrão do Nginx. A Least Connected

O que acontece nesse Least Connected? Ele só vai redirecionar a requisição para uma outra instância, quando a instância atual estiver demorando pra responder ou sobrecarregando.

Essa estratégia é habilitada quando você faz uso do least_conn;.

Nesse caso, se você estiver fazendo uma requisição por vez e essa requisição é respondida rapidamente, todas as requisições irão ser atendidas pelo node1.

Se você remover a configuração do least_conn, o Nginx, volta a trabalhar no modelo round-robin e assim, para cada requisição, ele deve mandar para um node diferente.

Testa isso pra gente e confirma se está correto por favor?

Boa noite Wanderson. Obrigado pela resposta mas continua como se só houvesse um servidor. O pior, acho que a configuração do nginx.conf não está sendo respeitada, ou seja, a configuração

server node1:8080; server node2:8080; server node3:8080;

não está surtindo efeito. Digo isso porque na aplicação angular, a url do servidor está localhost:8080 e se eu modificar o mapeamento dos nods para

server node1:8081; server node2:8082; server node3:8083;

continua chamando apenas o node1 pois foi ele que ficou com a porta 8080 no mapeamento feito no arquivo docker-compose.yml . Realmente não sei mais o que tentar. Tem alguma dica? Já passou por isso?

Como você está testando isso Henrique? Acho que você não pode disponibilizar o projeto para que eu teste, estou certo? Se puder, me disponibiliza no GitHub ou coisa assim para eu ver isso de perto por favor.

Outra coisa que não entendi é a dependência do node2 pro node 1 e do node3 para o node2, se os 3 são a mesma coisa, eles não deveriam ser dependentes entre si.

Olá Wanderson. Vou tentar colocar no git para vc poder ver. As dependências foi só para teste para saber se a diretiva depends_on funcionava. Mas não funciona corretamente, não da forma que eu esperava pois era para subir toda a aplicação node1 e depois a nod2 etc... mas não funciona pois para subir a aplicação eu primeiro tenho que subir o container do mysql e para isso eu tive que criar o script ./wait-for-it.sh a java -jar batistagases-1.0.0.jar

Wanderson, segue o link do projeto. Contem o jar, o api.dockfile para gerar a imagem dos nodes (node1, node2 e node3 ) , contem o arquivo wait-for-it.sh para aguardar o mysql subir para depois subir os nodes e contem o client em angular. Qualquer dúvida é só falar.

O login e senha para acessar a aplicação. login: admin@batistagases.com senha: admin

https://www.dropbox.com/s/s4a2qdwiqah8xzv/projeto.zip?dl=0

Então Wanderson, conseguiu acessar a aplicação?

Oi Henrique, tudo bem? Estou bem confuso sobre como o projeto foi arquitetado, você adicionar esse script wait-for-it.sh, mas ele não veio com o projeto e há várias referências absolutas que dizem respeito ao seu sistema operacional e usuário, o que torna tudo mais difícil de entender do meu lado.

Aqui, do jeito que está, não vai funcionar. Aqui precisei ajustar algumas coisas e no fim das contas, o que descobri é que na sua aplicação você usa o environment para pegar a URL correta para fazer a requisição. O que está 100% correto.

O problema é que o endereço configurado no environment é localhost:8080, ou seja, depois do Angular ser carregado pelo NGINX, ele vai fazer requisições sempre para o mesmo endereço configurado no código.

Esse deve ser o problema.

Outro ponto que observei é que o location também vai redirect para o localhost:8080.

Então o que tá acontecendo é: você faz requisição para o localhost:8080 (direto no código), essa requisição nem chega a passar pelo NGINX, indo direto para o node1.

E quando você faz requisição para o NGINX, pela porta 4200, você faz um redirect com o location para o localhost:8080, que ao meu ver, também chama o node1.

No fundo, o problema não é do compose, mas sim de arquitetura e configuração mesmo. No fim, não acho que o NGINX deveria informa a porta do redirect, o código do environment não deveria apontar para um node específico e pessoalmente, se fosse para usar o NGINX como load balancer, eu não colocaria os assets lá, por que o assets são gerados por um build próprio.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software