{"id":22468086,"url":"https://github.com/isaacalves7/scaling-services","last_synced_at":"2026-04-07T23:32:09.406Z","repository":{"id":157185019,"uuid":"625928214","full_name":"IsaacAlves7/scaling-services","owner":"IsaacAlves7","description":"⚖️📦➕ It's a repository of scaling services.","archived":false,"fork":false,"pushed_at":"2023-05-18T04:03:30.000Z","size":330,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T15:52:57.311Z","etag":null,"topics":["cluster","docke-swarm","docker","docker-compose","express","kubernetes","load-balancing","marko","mongodb","mongoose","monolith","mvc-architecture","nginx","nodejs","services"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IsaacAlves7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-10T12:25:37.000Z","updated_at":"2024-05-28T16:49:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"50245941-fef0-4c6b-9733-2186ed58fcfd","html_url":"https://github.com/IsaacAlves7/scaling-services","commit_stats":null,"previous_names":["isaacalves7/scaling-services"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/IsaacAlves7/scaling-services","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsaacAlves7%2Fscaling-services","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsaacAlves7%2Fscaling-services/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsaacAlves7%2Fscaling-services/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsaacAlves7%2Fscaling-services/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IsaacAlves7","download_url":"https://codeload.github.com/IsaacAlves7/scaling-services/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IsaacAlves7%2Fscaling-services/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31533823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cluster","docke-swarm","docker","docker-compose","express","kubernetes","load-balancing","marko","mongodb","mongoose","monolith","mvc-architecture","nginx","nodejs","services"],"created_at":"2024-12-06T11:15:00.714Z","updated_at":"2026-04-07T23:32:09.401Z","avatar_url":"https://github.com/IsaacAlves7.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\u003ca href=\"https://github.com/IsaacAlves7/scaling-and-load-balancing-webapp\"\u003e\n\n![1679593818556](https://user-images.githubusercontent.com/61624336/230903035-222d7763-61d5-4d90-bf41-5a741d016d21.jpg)\n\n\u003c/a\u003e\u003c/div\u003e\n\n# ⚖️ [Docker] Scaling services\n\u003e ⚖️📦➕ **Arquitetura da aplicação**: Essa é uma aplicação criada para o modelo cliente-servidor usando o Marko para front-end e Node.js para o back-end, e possui uma estrutura monolítica atuando com a arquitetura MVC (Model View Controller) e ODM (Object Document Model) com Mongoose e MongoDB como banco de dados NoSQL.\n\nNa vida real, sabemos que a aplicação é maior que somente dois containers, geralmente temos dois, três ou mais containers para segurar o tráfego da aplicação, distribuindo a carga. Além disso, temos que colocar todos esses containers para se comunicar com o banco de dados em um outro container, mas quanto maior a aplicação, devemos ter mais de um container para o banco também.\n\nE claro, se temos três aplicações rodando, não podemos ter três endereços diferentes, então nesses casos utilizamos um Load Balancer em um outro container, para fazer a distribuição de carga quando tivermos muitos acessos. Ele recebe as requisições e distribui para uma das aplicações, e ele também é muito utilizado para servir os arquivos estáticos, como imagens, arquivos CSS e JavaScript.\n\nAssim, a nossa aplicação controla somente a lógica, as regras de negócio, com os arquivos estáticos ficando a cargo do Load Balancer.\n\n[![docker-compose.yaml](https://img.shields.io/badge/-docker--compose.yaml-pink?style=social\u0026logo=docker\u0026logoColor=magenta)](#)\n\n```yaml\nversion: '3'\nservices:\n    nginx:\n        build:\n            dockerfile: ./docker/nginx.dockerfile\n            context: .\n        image: douglasq/nginx\n        container_name: nginx\n        ports:\n            - \"80:80\"\n        networks: \n            - production-network\n        depends_on: \n            - \"node1\"\n            - \"node2\"\n            - \"node3\"\n\n    mongodb:\n        image: mongo\n        container_name: mongodb\n        networks: \n            - production-network\n\n    node1:\n        build:\n            dockerfile: ./docker/alura-books.dockerfile\n            context: .\n        image: douglasq/alura-books\n        container_name: alura-books-1\n        ports:\n            - \"3000\"\n        networks: \n            - production-network\n        depends_on:\n            - \"mongodb\"\n\n    node2:\n        build:\n            dockerfile: ./docker/alura-books.dockerfile\n            context: .\n        image: douglasq/alura-books\n        container_name: alura-books-2\n        ports:\n            - \"3000\"\n        networks: \n            - production-network\n        depends_on:\n            - \"mongodb\"\n\n    node3:\n        build:\n            dockerfile: ./docker/alura-books.dockerfile\n            context: .\n        image: douglasq/alura-books\n        container_name: alura-books-3\n        ports:\n            - \"3000\"\n        networks: \n            - production-network\n        depends_on:\n            - \"mongodb\"\n\nnetworks:\n    production-network:\n        driver: bridge\n```\n\n\nEntão, para isso foi criada uma ferramenta no Docker chamada **Docker Compose**, que ele executa e auxilia na build ou criação de vários (múltiplos) containers simultaneamente. Ele funciona seguindo um arquivo de texto, chamado `docker-compose.yaml`.\n\nEsse arquivo serve para dar um conjunto de passos ao Docker e com ele podemos controlar quais containers sobem primeiro, ou seja, funciona como um processo de BIOS ou um automatizador de containers. O **Docker Compose** cria uma rede padrão, também é possível criar uma nova rede usando o comando `docker network`.\n\nEssa aplicação possui servidor, rotas e banco de dados. De novidade, é que agora precisamos criar o **NGINX**, que é mais um container que devemos subir.\n\nEntão, ao utilizarmos a **imagem nginx**, ou criamos a nossa própria. Como vamos configurar o NGINX para algumas coisas específicas, como lidar com os **arquivos estáticos**, vamos criar a nossa própria imagem, por isso que na aplicação há o `nginx.dockerfile`:\n\n[![dockerfile](https://img.shields.io/badge/-nginx.dockerfile-blue?style=social\u0026logo=docker\u0026logoColor=blue)](#)\n\n```dockerfile\nFROM nginx:latest\nMAINTAINER isaacalves7\nCOPY /public /var/www/public\nCOPY /docker/config/nginx.conf /etc/nginx/nginx.conf\nEXPOSE 80 443\nENTRYPOINT [\"nginx\"]\n# Parametros extras para o entrypoint\nCMD [\"-g\", \"daemon off;\"]\n```\n\nNesse arquivo, nós utilizamos a última versão disponível da imagem do nginx como base, e copiamos o conteúdo da pasta `public`, que contém os arquivos estáticos, e um arquivo de configuração do NGINX para dentro do container. Além disso, abrimos as portas `80` e `443` e executa o NGINX através do comando nginx, passando os parâmetros extras `-g` e `daemon off`.\n\nPor fim, vamos ver um pouco sobre o *arquivo de configuração do NGINX*, para entendermos um pouco como o **load balancer** está funcionando.\n\n[![NGINX](https://img.shields.io/badge/-nginx.conf-000000?style=social\u0026logo=Nginx\u0026logoColor=#009639)](#)\n\nNo arquivo `nginx.conf`, dentro server, está a parte que trata de servir os *arquivos estáticos*. Na `porta 80`, no localhost, em `/var/www/public`, ele será responsável por servir as pastas `css`, `img` e `js`. E todo resto, que não for esses três locais, ele irá jogar para o `node_upstream`.\n\nNo **node_upstream**, é onde ficam as configurações para o NGINX redirecionar as conexões que ele receber para um dos três containers da nossa aplicação. O redirecionamento acontecerá de forma circular (fila circular - estrutura de dados), ou seja: \n\n1. A primeira conexão irá para o primeiro container;\n2. A segunda irá para o segundo container; \n3. A terceira irá para o terceiro container; \n4. Na quarta, começa tudo de novo, e ela vai para o primeiro container e assim por diante.\n\nAgora, começamos a descrever os nossos **serviços** (services):\n\n\u003e Um serviço é uma parte da nossa aplicação dockerizada, lembrando do diagrama acima.\n\nTemos um nó com NGINX, três nós com Node.js, e um nó com MongoDB como serviços. Logo, se queremos construir cinco containers, vamos construir cinco serviços, cada um deles com um nome específico.\n\nEntão, vamos começar construindo o NGINX, que terá o nome `nginx`. Em cada serviço, devemos dizer como devemos construí-lo, como devemos fazer o seu build.\n\nO serviço será construído através de um `Dockerfile`, então devemos passá-lo onde ele está. E também devemos passar um contexto, para dizermos a partir de onde o `Dockerfile` deve ser buscado. Como ele será buscado a partir da pasta atual, vamos utilizar o ponto:\n\nConstruída a imagem, devemos dar um nome para ela, por exemplo `douglasq/nginx`. E quando o Docker Compose criar um container a partir dessa imagem, vamos dizer que o seu nome será `nginx`.\n\nSabemos também que o NGINX trabalha com duas portas, a `80` (HTTP) e a `443`(HTTPS). Como não estamos trabalhando com HTTPS, vamos utilizar somente a porta `80`, e no próprio arquivo, podemos dizer para qual porta da nossa máquina queremos mapear a porta `80` do container. Vamos mapear para a porta de mesmo número da nossa máquina.\n\nNo YAML, toda vez que colocamos um traço, significa que a propriedade pode receber mais de um item. Agora, para os containers conseguirem se comunicar, eles devem estar na mesma rede, então vamos configurar isso também. Primeiramente, devemos criar a rede, que não é um serviço, então vamos escrever do começo do arquivo, sem as tabulações:\n\nO nome da rede será `production-network` e utilizará o driver `bridge`: Com a rede criada, vamos utilizá-la no serviço.\n\nIsso é para construir o **serviço do NGINX**, agora vamos construir o **serviço do MongoDB**, com o nome `mongodb`. Como ele será construído a partir da imagem `mongo`, não vamos utilizar nenhum Dockerfile, logo não utilizamos a propriedade `build`. Além disso, não podemos nos esquecer de colocá-lo na rede que criamos.\n\nFalta agora criarmos os três serviços em que ficará a nossa aplicação: `node1`, `node2` e `node3`. Para eles, será semelhante ao NGINX, com Dockerfile `alura-books.dockerfile`, contexto da rede `production-network` e porta `3000`: Com isso, a construção dos nossos serviços está finalizada.\n\nPor último, quando subimos os containers na mão, temos uma ordem, primeiro devemos subir o `mongodb`, depois a nossa aplicação, ou seja, `node1`, `node2` e `node3` e após tudo isso subimos o `nginx`. Mas como que fazemos isso no `docker-compose.yml`? Nós podemos dizer que os serviços da nossa aplicação dependem que um serviço suba antes deles, o serviço do `mongodb`. Da mesma forma, dizemos que o serviço do `nginx` depende dos serviços `node1`, `node2` e `node3`.\n\n## Subindo os serviços\nCom o `docker-compose.yml` pronto, podemos subir os serviços, mas antes devemos garantir que temos todas as imagens envolvidas neste arquivo na nossa máquina. Para isso, dentro da pasta do nosso projeto, executamos o seguinte comando:\n\nInicio/Build do Docker Compose\n```sh\ndocker-compose build\n```\n\nDepois de buildar os serviços, eles podem ser vistos em:\n\n```sh\ndocker images\n```\n\nApós isso, podemos inserir o comando:\n\n```sh\ndocker-compose up # ou docker-compose up -d\n```\n\nListando e verificando o docker-compose\n\n```sh\ndocker-compose ps\n```\n\nPara e remove todos os containers do docker-compose\n\n```sh\ndocker-compose down\n```\n\nVerificando que os containers estão se comunicando\n\n```sh\ndocker exec -it alura-books-1 ping alura-books-2\ndocker exec -it alura-books-1 ping node2\n```\n\nReinicializando containers\n\n```sh\ndocker-compose restart\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisaacalves7%2Fscaling-services","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisaacalves7%2Fscaling-services","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisaacalves7%2Fscaling-services/lists"}