Dockerizando a aplicação
Introdução: O que é Docker?
Docker é uma plataforma de virtualização leve que utiliza contêineres para empacotar e distribuir software. Os contêineres são isolados uns dos outros e contêm o software, as bibliotecas e as dependências necessárias para que ele funcione. Além disso, esses contêineres podem se comunicar uns com os outros por meio de canais bem definidos, garantindo a interoperabilidade. Todos os contêineres compartilham o mesmo kernel do sistema operacional, o que os torna mais eficientes em comparação com máquinas virtuais tradicionais.
Por que utilizei em minha aplicação?
Em minha aplicação, utilizamos o Docker para garantir a consistência do ambiente de desenvolvimento, facilitar o gerenciamento de dependências e simplificar a implantação. O Docker também possibilita que nossos serviços sejam executados de forma isolada, mas com capacidade de comunicação eficiente entre eles. Isso é fundamental para manter a modularidade e escalabilidade do sistema.
Como configurar (ambiente Linux)
Para configurar o Docker em um ambiente Linux, siga os seguintes passos:
1 - Instale o Docker:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
2 - Instale o Docker Compose:
sudo curl -L "https://github.com/docker/compose/releases/download/v2.0.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
3 - Verifique a instalação:
docker --version
docker-compose --version
4 - Inicie o Docker:
sudo systemctl start docker
sudo systemctl enable docker
Aplicação em meu projeto:
A imagem abaixo representa visualmente, por meio de uma Arquitetura, a implementação do Docker em minha aplicação. Nela, estão destacados os principais serviços e suas interconexões. A leitura atenta da legenda facilitará a compreensão de como esses serviços se relacionam.
Figura 1 - Figura arquitetura Docker
Fonte: Elaborado por Marco Rizzi
Label's
-
Imagem:
Representa uma parte da dockerização. Cada label desse tipo aponta para um serviço da nossa aplicação, que tem uma imagem gerada e gerenciada pelo Docker-Compose. -
Url Connection:
Indica que o serviço está hospedado externamente, por exemplo, em uma solução de nuvem, e que está se conectando à aplicação por meio de uma variável de ambiente configurada no Docker-Compose.
Serviços
-
Backend:
É uma imagem que aponta para o serviço backend no Docker-Compose. Essa imagem contém a API do projeto, responsável por lidar com a lógica de negócios e a comunicação com o banco de dados. -
Frontend:
É uma imagem que aponta para o serviço frontend no Docker-Compose. Essa imagem contém a interface visual do projeto, a qual será utilizada pelo cliente.
Serviços do Docker
-
Compose:
O arquivo docker-compose.yml é responsável por orquestrar todos os serviços da aplicação. Ele configura e executa os contêineres, além de possibilitar a comunicação entre os diferentes serviços em um ambiente isolado e controlado. -
Container:
O Container representa a fase final do processo de dockerização. Ele é um serviço mais abstrato e integrado, onde todos os componentes da aplicação (Backend, Frontend, etc.) se conectam. A partir desse ponto, é possível hospedar a aplicação por completo, unificando os serviços e facilitando o gerenciamento e a escalabilidade.
Trechos de código relevantes para a aplicação:
Nessa seção, exploramos as imagens que criei para cada serviço da aplicação e explico como o orquestrador Docker-Compose.yml
funciona. A seguir, estão as imagens associadas ao backend e frontend, além da configuração de serviços no Docker Compose.
Imagens
1 - Imagem do backend:
-
Baseada na imagem oficial do Python 3.10.
-
Define o diretório de trabalho (
/app
) dentro do contêiner. -
Copia o arquivo
requirements.txt
e instala as dependências necessárias compip
. -
Copia o restante do código para o contêiner.
-
Expõe a porta 3000 para acessar o serviço da API.
-
Utiliza
uvicorn
para iniciar a API no FastAPI.
FROM python:3.11-bullseye
EXPOSE 8000
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
2 - Imagem do frontend:
-
Baseada na imagem oficial do Node.js versão 20.
-
Define o diretório de trabalho (
/app
). -
Copia os arquivos
package*.json
para instalar as dependências necessárias com onpm install
. -
Copia o código do frontend para dentro do contêiner.
-
Executa o comando
npm run build
para gerar os arquivos de build da aplicação frontend. -
Expõe a porta 3000 para servir a aplicação frontend.
-
Utiliza
npm start
para iniciar o serviço.
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
Docker-Compose
O arquivo docker-compose.yml
orquestra todos os serviços da aplicação, permitindo a comunicação entre eles. Aqui, detalhei os serviços principais:
services:
frontend:
build: ./frontend
image: src/frontend
container_name: frontend
restart: unless-stopped
environment:
NEXT_PUBLIC_BACKEND_URL: "http://backend:8000"
ports:
- "3000:3000"
networks:
- app-network
depends_on:
- backend
backend:
build: ./backend
image: src/backend
restart: unless-stopped
environment:
DATABASE_URL: ${DATABASE_URL}
ports:
- "8000:8000"
container_name: backend
env_file:
- .env
volumes:
- ./backend:/app/backend
networks:
- app-network
networks:
app-network:
driver: bridge
Explicação dos Serviços no Docker Compose
-
Frontend:
- A imagem do frontend é criada e exposta na porta
3000
. - A URL do backend é passada como uma variável de ambiente
NEXT_PUBLIC_BACKEND_URL
.
- A imagem do frontend é criada e exposta na porta
-
Backend:
- O serviço de backend é responsável pela API da aplicação e está exposto na porta
8000
para comunicações internas. - O arquivo
.env
é utilizado para passar variáveis sensíveis como aDATABASE_URL
.
- O serviço de backend é responsável pela API da aplicação e está exposto na porta
Conclusão
A utilização do Docker para a aplicação proporcionou inúmeros benefícios, desde a consistência no ambiente de desenvolvimento até a facilidade na implantação e escalabilidade. Ao encapsular os diferentes serviços da aplicação em contêineres, conseguimos garantir a modularidade, o isolamento e a interoperabilidade dos componentes, tudo isso com um gerenciamento eficiente de dependências.
A estrutura criada com Docker Compose orquestra de maneira simples e eficaz os serviços de backend, frontend e armazenamento de dados, permitindo uma comunicação transparente entre eles e facilitando o monitoramento e a manutenção da aplicação. Com essa configuração, a equipe é capaz de focar mais na evolução do projeto e menos nas complexidades relacionadas ao ambiente, garantindo uma maior produtividade e qualidade no desenvolvimento.