04 – DEVelopment OPerationS – 02 – Tutorial Docker – Dockerizando uma aplicação
04 – DEVelopment OPerationS – 02 – Tutorial Docker – Dockerizando uma aplicação
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Link do código fluente no Pinterest
Meus links de afiliados:
Hostinger
Digital Ocean
One.com
Voltar para página principal do blog
Todas as aulas desse curso
Aula 03
DEVelopment OPerationS – DevOps
Vamos ao exemplo do site oficial do docker.
Dockerizando um aplicativo Flask / Redis / Python
Flask
Flask é uma estrutura de aplicativo web WSGI leve.
O Web Server Gateway Interface (WSGI), é uma convenção de chamada simples para servidores Web encaminhar solicitações para aplicativos Web ou estruturas escritas na linguagem de programação Python.
Ou seja, funciona como servidor web e de aplicações Python, e é o padrão para a linguagem.
O WSGI foi originalmente especificado como PEP-333 em 2003.
O PEP-3333, publicado em 2010, atualiza a especificação para o Python 3.
Voltando ao Flask, ele foi projetado para facilitar e acelerar o início de uma aplicação web, com capacidade de expandir para aplicativos complexos.
Começou como um pacote simples em torno de Werkzeug e Jinja e se tornou uma das estruturas de aplicativos Web Python mais populares.
Redis
O Redis é uma estrutura de armazenamento de dados em memória, de código aberto, licenciado pela BSD, usado como banco de dados em cache e intermediário de mensagens (message broker).
Python
Python é uma linguagem de programação interpretada, de alto nível e de uso geral.
Suporta múltiplos paradigmas de programação, incluindo programação procedural, orientada a objeto e funcional.
Dockerizando uma aplicação web
Contextualizando
É hora de começar a criar uma aplicação da maneira Docker.
Começaremos na parte inferior da hierarquia de um aplicativo, o contêiner.
Acima desse nível, tem os serviços, que definem como os contêineres se comportam em produção.
E no nível superior está a pilha que define as interações de todos os serviços.
- Pilha
- Serviços
- Contêiner (estamos aqui)
Seu novo ambiente de desenvolvimento
No passado, se você começasse a escrever um aplicativo Python, a primeira coisa a fazer era instalar o Python em sua máquina.
Porém, isso cria uma situação em que o ambiente da sua máquina precisa ser exatamente assim para que seu aplicativo seja executado conforme o esperado, a mesma coisa para o servidor que vai servir seu aplicativo em produção.
Com o Docker, você pode simplesmente pegar uma versão portátil do Python como uma imagem, sem necessidade de instalação.
Em seguida, sua compilação pode incluir a imagem básica do Python ao lado do código do aplicativo, garantindo que a aplicação e suas dependências sempre viajem juntas.
Essas imagens portáteis são definidas no Dockerfile.
Definindo um contêiner com o Dockerfile
O Dockerfile definirá o que acontece no ambiente dentro do seu contêiner.
O acesso a recursos como interfaces de rede e unidades de disco é virtualizado dentro deste ambiente, que é isolado do resto do seu sistema, para que você tenha que mapear portas para o mundo externo e ser específico sobre quais arquivos deseja copiar para esse ambiente.
No entanto, depois de fazer isso, você pode esperar que a compilação do seu aplicativo definida neste Dockerfile se comporte exatamente do mesmo modo onde quer que seja executada.
Local de armazenamento de imagens e contêineres do Docker
Um contêiner do Docker consiste em configurações de rede, volumes e imagens.
A localização dos arquivos do Docker depende do seu sistema operacional.
Essa localização não interessa muito na prática, mas, de qualquer forma, ela fica em:
- Ubuntu: /var/lib/docker/
- Fedora: /var/lib/docker/
- Debian: /var/lib/docker/
- Windows: C:\ProgramData\DockerDesktop
- MacOS: ~/Library/Containers/com.docker.docker/Data/vms/0/
Vamos ao exemplo
O exemplo que seguiremos usa 4 arquivos:
- Dockerfile
- docker-compose.yml
- requirements.txt
- app.py
Dockerfile
Crie uma pasta para o projeto e dentro crie esses arquivos.
Dockerfile
#Cria uma imagem Python 3.8.
FROM python:3.8-alpine
#Define o diretório de trabalho como /code
WORKDIR /code
#Define variáveis de ambiente usadas pelo comando flask
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
#Instala o gcc para que pacotes Python, como
#MarkupSafe e SQLAlchemy, possam compilar mais rápido
RUN apk add --no-cache gcc musl-dev linux-headers
#Copia o requirements.txt para dentro do contêiner
#COPY <src> <dest>
COPY requirements.txt requirements.txt
#Instala as dependências do Python
RUN pip install -r requirements.txt
#Copia o diretório atual . no projeto, para a workdir . na imagem
COPY . .
#Define o comando padrão para o contêiner executar.
CMD ["flask", "run"]
docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
requirements.txt (Dependências)
Flask
Redis
E por último, a aplicação em si.
app.py (Aplicação)
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
Mesmo em uma máquina que não tenha python, flask e redis instalados, você conseguirá rodar a sua app empacotada no contêiner sem problemas.
O docker-compose.yml define dois serviços: web e redis.
Web service
O Web service usa uma imagem criada a partir do Dockerfile no diretório atual.
Em seguida, vincula o contêiner e a máquina host à porta exposta, 5000.
Este serviço de exemplo usa a porta padrão para o servidor web Flask: 5000.
Redis service
O serviço redis usa uma imagem pública Redis extraída do registro do Docker Hub.
Dockerfile
O Dockerfile define as imagens que queremos criar.
É a partir delas que o docker faz os builds para podermos criar os contêineres.
docker-compose.yml
O docker-compose.yml é uma ferramenta para definir e executar aplicativos Docker com vários contêineres.
Com o Compose, você usa um arquivo .yml para configurar os serviços do seu aplicativo.
Em seguida, com um único comando, você cria e inicia todos os serviços com a configuração definida.
Por exemplo, em uma situação onde você necessita de alguns contêineres trabalhando juntos, um para servidor http, outro para o servidor de banco de dados, etc. Você pode usar o docker-compose.yml para definir de todas as imagens que gerarão esses contêineres que funcionarão juntos.
Resumindo, o Dockerfile configura as imagens para um contêiner e o Docker-compose configura as imagens para contêineres e define a conexão entre eles.
Crie e execute seu aplicativo com o Compose
No diretório do projeto, inicie o aplicativo executando:
docker-compose up
O docker-compose.yml vai baixar uma imagem do Redis, vai cria uma imagem para o seu código e iniciar os serviços do Redis.
Nesse caso, o código é copiado estaticamente na imagem no momento da criação.
Acesse:
http://0.0.0.0:5000/
E veja a aplicação rodando.
Dê um refresh(F5) na página e veja que o contador vai aumentando.
Limpando os contêineres e as imagens
Lista os processos do Docker, inclusive os parados.
docker ps -a -q
Remove todos os contêineres parados.
docker rm $(docker ps -a -q)
Remove uma imagem
docker image rmi <image ID>
Limpa todos os recursos – imagens, contêineres, volumes e redes
docker system prune
Remove todos os contêineres parados e todas as imagens não utilizadas (não apenas imagens pendentes):
docker system prune -a
No diretório do projeto, inicie o compose novamente:
docker-compose up
Acesse de novo:
http://0.0.0.0:5000/
Veja que o contador começou do 1(um) de novo, poruqe a gente matou o contêiner.