Como executar um script Python ao iniciar um container Docker

DockerBeginner
Pratique Agora

Introdução

Docker é uma ferramenta poderosa para a conteinerização de aplicações, facilitando o desenvolvimento, a implantação e o gerenciamento de software. Neste tutorial, exploraremos como executar um script Python quando um container Docker é iniciado. Essa abordagem permite automatizar a implantação da sua aplicação e otimizar o seu fluxo de trabalho de desenvolvimento. Ao final deste laboratório, você será capaz de criar um container Docker que executa automaticamente seu script Python na inicialização.

Criando um Script Python Simples

Neste primeiro passo, criaremos um script Python simples que será executado quando nosso container Docker for iniciado. Este script imprimirá uma mensagem e a data e hora atuais.

Vamos começar criando um novo diretório para nosso projeto:

mkdir -p ~/project/python-docker
cd ~/project/python-docker

Agora, vamos criar um script Python simples chamado app.py usando o editor de texto nano:

nano app.py

No editor nano, adicione o seguinte código Python:

import datetime
import time

print("Olá do container Docker!")
print(f"Data e hora atuais: {datetime.datetime.now()}")

## Mantém o container em execução para demonstrar que está funcionando
print("Container está em execução...")
while True:
    print("Container ainda em execução... Pressione Ctrl+C para parar.")
    time.sleep(10)

Salve o arquivo pressionando Ctrl+O, depois Enter e saia do nano pressionando Ctrl+X.

Este script irá:

  1. Imprimir uma mensagem de boas-vindas
  2. Exibir a data e hora atuais
  3. Manter o container em execução com uma mensagem a cada 10 segundos

Vamos testar nosso script Python para garantir que ele funcione corretamente:

python3 app.py

Você deve ver uma saída semelhante a:

Olá do container Docker!
Data e hora atuais: 2023-10-12 14:30:45.123456
Container está em execução...
Container ainda em execução... Pressione Ctrl+C para parar.

Pressione Ctrl+C para parar o script.

Agora que temos um script Python funcionando, podemos prosseguir para criar um container Docker que executará este script quando for iniciado.

Criando um Dockerfile

Agora que temos nosso script Python pronto, vamos criar um Dockerfile para definir como nosso container Docker deve ser construído.

Um Dockerfile é um arquivo de texto que contém todos os comandos necessários para construir uma imagem Docker. Esta imagem conterá nosso script Python e todas as dependências necessárias.

No mesmo diretório (~/project/python-docker), crie um novo arquivo chamado Dockerfile:

nano Dockerfile

Adicione o seguinte conteúdo ao Dockerfile:

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

Salve e saia do nano pressionando Ctrl+O, depois Enter e, em seguida, Ctrl+X.

Vamos entender o que cada linha no Dockerfile faz:

  1. FROM python:3.9-slim: Isso especifica a imagem base a ser usada. Estamos usando a imagem oficial do Python 3.9 com uma variante slim para manter o tamanho pequeno.

  2. WORKDIR /app: Isso define o diretório de trabalho dentro do container como /app.

  3. COPY app.py .: Isso copia nosso script Python da máquina host para o diretório de trabalho atual no container (que é /app).

  4. CMD ["python", "app.py"]: Isso especifica o comando a ser executado quando o container é iniciado. Neste caso, ele executará nosso script Python.

Agora, vamos construir nossa imagem Docker usando este Dockerfile:

docker build -t python-app .

Este comando constrói uma imagem Docker a partir do Dockerfile no diretório atual (.) e a marca com o nome python-app (-t significa tag).

Você deve ver uma saída semelhante a:

Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM python:3.9-slim
 ---> 1bc6a8a2a52f
Step 2/4 : WORKDIR /app
 ---> Using cache
 ---> 2a3b7a28c9e5
Step 3/4 : COPY app.py .
 ---> Using cache
 ---> 9a0b7a1c8c2d
Step 4/4 : CMD ["python", "app.py"]
 ---> Using cache
 ---> 3b0c7a2d9f1e
Successfully built 3b0c7a2d9f1e
Successfully tagged python-app:latest

A saída pode variar, mas você deve ver as mensagens "Successfully built" e "Successfully tagged" se tudo correu bem.

Você agora criou com sucesso uma imagem Docker que contém seu script Python e o executará quando um container for iniciado a partir desta imagem.

Executando o Container Docker

Agora que construímos nossa imagem Docker, podemos executar um container baseado nesta imagem. O container executará automaticamente nosso script Python quando for iniciado.

Para executar um container a partir de nossa imagem, use o seguinte comando:

docker run --name python-container python-app

Este comando inicia um novo container chamado python-container a partir da imagem python-app que criamos no passo anterior.

Você deve ver uma saída semelhante a:

Olá do container Docker!
Data e hora atuais: 2023-10-12 15:45:30.123456
Container está em execução...
Container ainda em execução... Pressione Ctrl+C para parar.
Container ainda em execução... Pressione Ctrl+C para parar.

O container agora está em execução e executando nosso script Python. O script foi projetado para continuar em execução indefinidamente, imprimindo uma mensagem a cada 10 segundos.

Pressione Ctrl+C para parar de visualizar os logs, mas observe que o container ainda está em execução em segundo plano.

Para verificar se o container está em execução, use o seguinte comando:

docker ps

Você deve ver seu container na lista de containers em execução:

CONTAINER ID   IMAGE        COMMAND           CREATED         STATUS         PORTS     NAMES
1a2b3c4d5e6f   python-app   "python app.py"   1 minute ago    Up 1 minute              python-container

Para parar o container, use o seguinte comando:

docker stop python-container

Para iniciar o container novamente, use:

docker start python-container

E para visualizar os logs do container em execução:

docker logs python-container

Isso mostrará a saída do nosso script Python. Você pode pressionar Ctrl+C para sair da visualização dos logs.

Para remover o container quando terminar, primeiro pare-o se estiver em execução e, em seguida, remova-o:

docker stop python-container
docker rm python-container

Você agora criou e executou com sucesso um container Docker que executa um script Python na inicialização.

Usando Variáveis de Ambiente com Python no Docker

Variáveis de ambiente são uma ótima maneira de configurar sua aplicação sem alterar o código. Nesta etapa, vamos modificar nosso script Python para usar variáveis de ambiente e atualizar nosso Dockerfile para fornecer essas variáveis.

Primeiro, vamos atualizar nosso script Python para ler uma variável de ambiente:

nano app.py

Modifique o script para incluir suporte a variáveis de ambiente:

import datetime
import time
import os

## Get the environment variable with a default value if not set
user_name = os.environ.get('USER_NAME', 'Guest')

print(f"Hello, {user_name}, from the Docker container!")
print(f"Current date and time: {datetime.datetime.now()}")

## Keep the container running to demonstrate it's working
print("Container is running...")
while True:
    print("Container still running... Press Ctrl+C to stop.")
    time.sleep(10)

Salve e saia do nano pressionando Ctrl+O, depois Enter e, em seguida, Ctrl+X.

Agora, vamos atualizar nosso Dockerfile para incluir uma variável de ambiente:

nano Dockerfile

Atualize o Dockerfile para incluir a variável de ambiente:

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Set environment variable
ENV USER_NAME="Docker User"

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

Salve e saia do nano e, em seguida, reconstrua a imagem Docker:

docker build -t python-app-env .

Agora, execute um container com a variável de ambiente padrão:

docker run --name python-env-container python-app-env

Você deve ver uma saudação com "Docker User" na saída:

Hello, Docker User, from the Docker container!
Current date and time: 2023-10-12 16:30:45.123456
Container is running...

Pressione Ctrl+C para parar de visualizar os logs.

Pare e remova o container:

docker stop python-env-container
docker rm python-env-container

Você também pode substituir a variável de ambiente ao executar o container:

docker run --name python-env-container -e USER_NAME="LabEx Student" python-app-env

Desta vez, você deve ver seu nome personalizado na saudação:

Hello, LabEx Student, from the Docker container!
Current date and time: 2023-10-12 16:35:15.789012
Container is running...

Pressione Ctrl+C para parar de visualizar os logs.

Pare e remova o container:

docker stop python-env-container
docker rm python-env-container

Usar variáveis de ambiente é uma prática comum no Docker para tornar seus containers mais configuráveis sem ter que reconstruir a imagem para pequenas alterações.

Usando ENTRYPOINT vs CMD no Dockerfile

No Docker, existem duas instruções para especificar qual comando deve ser executado quando um container é iniciado: CMD e ENTRYPOINT. Elas têm propósitos e comportamentos diferentes, e entender a diferença é importante para o gerenciamento de containers.

Entendendo ENTRYPOINT e CMD

  • ENTRYPOINT: Define o executável que será executado quando o container for iniciado. É mais difícil de substituir em tempo de execução.
  • CMD: Fornece argumentos padrão para o ENTRYPOINT ou pode especificar todo o comando se o ENTRYPOINT não for usado. É fácil de substituir em tempo de execução.

Vamos explorar a diferença criando dois Dockerfiles diferentes.

Primeiro, crie um novo script Python que aceite argumentos de linha de comando:

nano greeting.py

Adicione o seguinte código:

import sys

print("Script started!")

if len(sys.argv) > 1:
    print(f"Arguments provided: {sys.argv[1:]}")
    for arg in sys.argv[1:]:
        print(f"- {arg}")
else:
    print("No arguments provided.")

print("Script finished!")

Salve e saia do nano.

Agora, vamos criar um Dockerfile que usa CMD:

nano Dockerfile.cmd

Adicione o seguinte conteúdo:

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

CMD ["python", "greeting.py", "default", "arguments"]

Salve e saia do nano.

Construa a imagem:

docker build -t python-cmd -f Dockerfile.cmd .

Agora, crie outro Dockerfile que usa ENTRYPOINT:

nano Dockerfile.entrypoint

Adicione o seguinte conteúdo:

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

ENTRYPOINT ["python", "greeting.py"]
CMD ["default", "arguments"]

Salve e saia do nano.

Construa a imagem:

docker build -t python-entrypoint -f Dockerfile.entrypoint .

Testando CMD vs ENTRYPOINT

Vamos executar containers de ambas as imagens e observar as diferenças.

Primeiro, execute um container usando a imagem CMD sem argumentos adicionais:

docker run --name cmd-container python-cmd

A saída deve ser semelhante a:

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

Agora, execute um container com a imagem CMD, mas forneça argumentos personalizados:

docker run --name cmd-container-custom python-cmd hello world

Saída:

Script started!
No arguments provided.
Script finished!

Observe que todo o comando foi substituído por hello world, que não são passados como argumentos para o nosso script.

Agora, vamos executar um container usando a imagem ENTRYPOINT sem argumentos adicionais:

docker run --name entrypoint-container python-entrypoint

Saída:

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

Finalmente, execute um container com a imagem ENTRYPOINT e forneça argumentos personalizados:

docker run --name entrypoint-container-custom python-entrypoint hello world

Saída:

Script started!
Arguments provided: ['hello', 'world']
- hello
- world
Script finished!

Desta vez, nossos argumentos são passados corretamente para o script Python porque ENTRYPOINT define o executável, e quaisquer argumentos adicionais fornecidos para docker run são passados para esse executável.

Melhores Práticas

  • Use ENTRYPOINT para containers que sempre devem executar um comando específico (como nosso script Python)
  • Use CMD para fornecer argumentos padrão que podem ser facilmente substituídos
  • Combine ambos usando ENTRYPOINT para o comando e CMD para argumentos padrão

Limpe os containers:

docker rm cmd-container cmd-container-custom entrypoint-container entrypoint-container-custom

Você agora aprendeu a diferença entre CMD e ENTRYPOINT no Docker, o que é essencial para controlar como seus scripts Python são executados quando um container é iniciado.

Resumo

Neste laboratório, você aprendeu como executar scripts Python quando um container Docker é iniciado. Aqui está o que você realizou:

  1. Criou um script Python simples que é executado em um container Docker
  2. Construiu uma imagem Docker com um Dockerfile
  3. Executou um container Docker que executa automaticamente o script Python
  4. Usou variáveis de ambiente para configurar sua aplicação Python no Docker
  5. Entendeu a diferença entre CMD e ENTRYPOINT em Dockerfiles

Essas habilidades são fundamentais para conteinerizar aplicações Python e automatizar sua implantação. Agora você pode:

  • Empacotar suas aplicações Python com todas as suas dependências
  • Configurar suas aplicações usando variáveis de ambiente
  • Controlar como suas aplicações iniciam dentro de containers Docker
  • Escolher o mecanismo de inicialização apropriado (CMD ou ENTRYPOINT) para seu caso de uso específico

Com este conhecimento, você pode construir aplicações Docker mais complexas que executam scripts Python automaticamente na inicialização, tornando seu processo de implantação mais eficiente e confiável.