Até o momento, todos os posts que fiz sobre Docker, utilizaram imagens padrões obtidas através do comando docker pull. Depois disso, estas imagens foram utilizadas para criarmos/instanciarmos containers. Todavia, seria interessante podermos criar nossas próprias imagens, não? Essa é a ideia deste post.
Se você acompanha o site, vai se lembrar que eu fiz uma API de teste (github: dummy-api). Vou gerar uma imagem a partir deste fonte.
Na verdade, duas imagens:
- Utilizando arquivos locais;
- Clonando o repositório do Git na hora do build.
Vou dividir a criação destas imagens em 3 passos: Criação do arquivo Dockerfile, criação do docker-compose.yml e o comando para gerar a imagem (build)
Para ambas imagens, vamos precisar de um arquivo chamado Dockerfile (sem extensão, só o nome Dockerfile mesmo) e eles serão bem parecidos.
Mas afinal, o que é Dockerfile?
Este é um arquivo texto que contém todas as instruções e comandos necessários para gerar a imagem. Simples assim.
Neste post, vou explicar o que precisamos para gerar as imagens, mas existem muitas outras configurações e opções que também podem ser utilizadas. Sugiro olhar a documentação oficial do Dockerfile é uma excelente fonte de informações.
Dockerfile: Imagem com arquivos locais
A primeira coisa que vamos precisar é um sistema operacional. Vamos considerar o que será instalado nesta imagem: Uma aplicação simples feita em Python e que utiliza Flask. Sendo assim, Ubuntu me parece meio exagero. Vai aumentar o tamanho final da imagem e não trará vantagens. Sendo assim, o sistema que escolhi é o Alpine, que é uma distribuição de Linux super compacta.
FROM alpine:3.7
A linha acima define que o sistema operacional instalado será o alpine na versão 3.7. Se você não possuir esta imagem na sua maquina, o Docker irá baixa-la.
O próximo passo é opcional, mas é interessante ter: Descrição da imagem.
# A Little info LABEL Description="Dockerized my dummy-api as an example of how to create an image"
Você pode adicionar varios labels no seu Dockerfile. A sintaxe é LABEL <chave>=<valor>
No caso do código acima, adicionei um label com a chave Description (descrição) e com a descrição que criei para este imagem.
Agora precisamos colocar um comando para copiar os arquivos locais para a imagem que está sendo criada. Atenção: para que esta imagem funcione, você deve clonar o repositório da API. Na parte de geração da imagem vou passar o comando.
# Copies the dummy-api files. COPY ./dummy-api/ /dummy-api/
O comando acima segue a sintaxe: COPY <caminho local> <caminho na imagem>.
Da forma que o comando acima está elaborado, a pasta local chamada dummy-api será copiada (com todo seu conteúdo e sub-pastas) para a pasta /dummy-api dentro da imagem.
O próximo passo é instalar o Python no Alpine.
# Installs Python3 RUN apk --update --no-cache add python3 py3-pip
O comando acima vai instalar o Python3 e o pip para a versão correspondente dele.
Outro comando opcional. Se você quiser atualizar o PIP quando criar a imagem, adicione o comando abaixo:
RUN pip3 install --upgrade pip
Com o Python devidamente instalado, hora de instalar os requisitos da aplicação (que estão listados no requirements.txt)
# Installs required stuffs... RUN pip3 install -r /dummy-api/requirements.txt
O próximo comando é uma configuração importante. Nele vamos definir o diretório de trabalho (workding directory)
# Defining working directory WORKDIR /dummy-api/
O valor escolhido foi a pasta /dummy-api/, pois é lá que está o nosso fonte.
Por último, o comando que vai iniciar a aplicação:
# Starts the API CMD ["python3", "app.py"]
O comando é simples: python3 app.py. Todavia, a diretriz CMD recebe um vertor de strings, onde cada valor será separado por um espaço. Para adicionar mais argumentos, basta acrescenta-los ao vetor.
E assim completamos o arquivo Dockerfile para a imagem que utiliza arquivos locais. Agora é a hora de fazer o Dockerfile adaptado para clonar um repositório do Git.
Dockerfile: Imagem que clona um repositório do Git
Este arquivo vai ser muito parecido com o anterior, então vou colocar apenas as diferenças.
A primeira diferença é uma alteração em um dos comandos.
# Installs Python3 RUN apk --update --no-cache add python3 py3-pip git
Para clonarmos o repositório, vamos precisar do Git instalado. No código acima, além de instalar o Python3, inclui o Git na lista.
Assim que as aplicações base forem instaladas, o próximo passo é clonar o repositório…
# Cloning the files we'll need. RUN git clone https://github.com/brenordv/dummy-api.git
O comando acima é bem simples, estou apenas clonando o repositório da minha dummy-api para o ambiente da imagem. Por padrão, o git vai criar uma pasta com o nome do repositório, ou seja, o fonte vai ficar na pasta: /dummy-api/.
Pronto. O resto do arquivo é igual.
Criando o arquivo docker-compose.yml
Este arquivo vai ser exatamente igual para as duas imagens, então você deve copia-lo para as duas pastas (local_image e git_image).
version: '3' services: flask-app: build: . ports: - "5042:5000"
O docker-compose acima é bem simples.
- Primeiro defini que a versão do arquivo é a 3;
- Depois defini que ele vai ter um serviço chamado flask-app;
- Esta imagem será montada a partir do diretório local (build: .);
- E todas as requisições que chegarem na porta 5042 da maquina local serão redirecionadas para a porta 5000 do container;
Só para lembrar: O arquivo docker-compose.yml que criamos acima é o mesmo para ambas imagens.
Gerando a imagem
O último passo é gerar a imagem e/ou um container. Primeiro você deve acessar o diretório da imagem que você deseja criar (local_image ou git_image) e depois utilizar um dos comandos:
Um aviso importante: Para a imagem que copia os arquivos locais, você precisa clonar o repositório da dummy-api antes de fazer o build! Para isso, utilize o comando abaixo:
git clone https://github.com/brenordv/dummy-api.git
Agora para os comandos de build:
docker-compose up -d
Este comando vai gerar a imagem e depois subir um container com ela. (Lembrando que, devido a flag -d, este container vai rodar como serviço.)
docker build -t my_image_name:image_tag .
O comando acima vai gerar a imagem, mas não vai subir o container. A imagem vai ser criada com o nome my_image_name e com a tag image_tag. Obviamente, você pode mudar estes valores.
Se quiser, estes exemplos estão no meu Github!
Espero ter ajudado!
Latest posts by Breno RdV (see all)
- O que é Metaclass e como ela funciona. (#python #dev #metaclass) - janeiro 11, 2023
- Entenda a mágica dos Generators. (#python, #dev, #generator, #iterator) - dezembro 28, 2022
- Ordenando um DataFrame por múltiplas colunas. (#python #pandas #jupyter #dev #data) - agosto 3, 2022