fbpx
Docker Images – Dicas e Truques
Publicado em: domingo, 28 de fev de 2016
Tags: DevOps | Docker

Você já criou suas primeiras imagens, mas algo não ficou bom e teve muito trabalho? Periódicas atualizações fizeram com que gastasse um tempo não previsto para atualizar imagens?! Deseja criar imagens mas não sabe como criar imagens de forma eficiente e de acordo com as melhores práticas. Esse post é para você.

Você pode encontrar imagens para os mais variados tipos de serviços e produtos, desde load balancers até blogs, bancos de dados SQL e NoSQL até Log. A maioria delas preza por alguns aspectos que são considerados boas práticas na criação de imagens, entenda como nesse post.

Imagens

A criação de imagens é feita com o comando Docker Build. O build necessita de um DockerFile. Se você ainda não viu um DockerFile, siga esse exemplo abaixo:

FROM debian:jessie

MAINTAINER NGINX Docker Maintainers "[email protected]"

ENV NGINX_VERSION 1.9.11-1~jessie

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
    && echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y ca-certificates nginx=${NGINX_VERSION} gettext-base \
    && rm -rf /var/lib/apt/lists/*

# forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx", "-g", "daemon off;"]

Vamos tentar traduzir:

A imagem que estamos compilando deve ser feita sob a imagem existente "debian:jessie". Baixe-a, caso não tenha baixado, e vamos executar os comandos abaixo sob essa imagem.

Armazene um nome para determinar que essa imagem foi criada por mim, e assim facilitar a indexação e o diálogo, caso alguém queira debater sobre algo.

Defina a variável de ambiente "NGINX_VERSION" com o valor "1.9.11-1~jessie"

Execute esses comandos: 1) Adicione a chave hkp://pgp.mit.edu:80 às chaves conhecidas. 
    && 2) Adicione o repositório "http://nginx.org/packages/mainline/debian/ jessie nginx" ao arquivo  "/etc/apt/sources.list" 
    && 3) Faça update da lista de pacotes disponíveis
    && 4) Instale ca-certificates, nginx=(na versão que especifiquei na variável de ambiente NGINX_VERSION) e gettext-base
    && 4) Remova a lista de referências para APT-GET, para que não seja possível fazer update após a instalação.

Execute esses comandos: Crie um link de /dev/stdout para /var/log/nginx/access.log
    && Crie um link de /dev/stderr para /var/log/nginx/error.log

Exponha as portas 80 e 443

Ao executar esse container, execute o comando "nginx" com os parâmetros "-g" e "daemon off;"

Nas minhas buscas pelo google, hub e github, não me recordo de sequer um DockerFile que não seguisse a seguinte estrutura:

  1. Definir imagem base (obrigatório).
  2. Instalar dependências.
  3. Instalar software ou ferramenta (via ap-get, via download ou via download e build).
  4. Executar algum tipo de limpeza para garantir que a imagem será o mais enxuta possível.
  5. Expor as portas em que o serviço ou app opera.
  6. Definir o comando de inicialização.

Embora haja esse padrãozinho, ainda há algumas coisas que você precisa saber sobre imagens.

Build X Image Layers

Ao realizar um build de DockerFile, cada instrução do DockerFile gerará, imediatamente após sua execução, uma nova image layer. Uma imagem, nada mais é que um conjunto de image layers sobrepostos. Esse design facilita a construção de novas imagens a partir de outras, reduzindo e otimizando a indexação, tráfego de rede, economizando o tempo de build e processamento durante a criação de imagens. Esse desenho simples, mas não simplista, é extremamente robusto e é a base da arquitetura de imagens do Docker.

Segregação de Comandos afins

Um DockerFile contém diversas instruções a serem executadas durante o build, vimos isso no tópico acima, mas você pode ter considerado meramente ilustrativo, se enganou. O isolamento de cada uma das image layers pode afetar seu build, principalmente se separar as execuções comandos que manipulem memória ou cache, como no caso do APT do debian e suas variações.

Nunca separe APT-GET UPDATE de APT-GET INSTALL, pois em uma recompilação da sua imagem, provavelmente a layer em que você executou o APT-GET UPDATE será carregada do cache, assim, a layer subsequente, gerada com o comando APT-GET INSTALL,  usaria dados indexados com resultado do APT-GET UPDATE do momento em que a layer foi criada. Isso pode significar alguns minutos, horas, dias, semanas, meses ou anos. O resultado é instalação de pacotes velhos.

Errado

...
RUN apt-get update
RUN apt-get install -y ca-certificates gettext-base \   
...

Correto

...
RUN     apt-get update \
    && apt-get install -y ca-certificates gettext-base \
...

A diferença está na garantia de que o apt-get update será executado sempre que o apt-get install for. Se você adicionar ou remover 1 pacote da lista, ambos serão executados. No exemplo errado, caso você adicione adicione ou remova pacotes, o apt-get update só será executado caso não haja cache dessa layer. E isso pode ter sido semanas, meses ou anos atrás.

EntryPoint.sh

EntryPoint.sh é um padrão super simples de ser implementado, ele consiste em ter um arquivo de inicialização que determina quais steps são necessários para a inicialização do seu container. O DockerFile pode criar esse arquivo, caso ele seja bem simples, ou você adiciona-o usando o comando COPY ou ADD no seu DockerFile. No arquivo EntryPoint.sh geralmente vemos comandos de preparação de ambiente, como cópias de arquivos, aplicação de configurações baseadas nas variáveis de ambiente, e etc. Geralmente colocamos o script de inicialização na imagem, já que utilizar infraestrutura de inicialização de serviços não é comum. Uma das coisas que mais me chamaram a atenção, são cópias de arquivos-padrão para Data Volumes, tema que vou abordar em Data Volumes e Default Volume Content, tópicos a seguir. Antes que me esqueça, o EntryPoint.sh é corriqueiramente utilizado no parâmetro EntryPoint do DockerFile.

Nos repositórios do Docker no github, vemos alguns DockerFiles bem interessantes, e podemos ver as diferenças entre o EntryPoint.sh do WordPress e do Redis. Ainda não entendi o motivo deles usarem o nome docker-entrypoint.sh enquanto a maioria dos DockerFiles não produzidos por eles possui o nome de EntryPoint.sh.

Imutabilidade

Imagens devem gerar containers imutáveis, isso significa que para fazer atualizações, ou modificações, é aconselhável que faça modificações no DockerFile para gerar uma nova versão da imagem. Você sempre terá acesso ao container para executar comandos após sua criação, mas essa não é uma boa prática. Executar comandos no container diretamente, é o mesmo que modificar arquivos em produção, sem versionamento.

Data Volumes (User Data)

Enquanto a imutabilidade diz para não realizar modificações no container, criando containers stateless, em algum momento você se deparará com cenários que a evolução da utilização da aplicação ou serviço gerará arquivos que não podem ser perdidos com um update de container. Podem ser dados do usuário, ou atualizações automáticas das aplicações, novos plugins, arquivos de configurações, novos temas, ou simplesmente um novo dado em um banco de dados (sql ou nosql) containerizado. São dados que representam a utilização ou evolução da aplicação em questão. Para esses cenários, devemos ter uma estratégia bem definida para que possamos realizar modificações duradouras. Os DATA VOLUMES, para o Docker são pontos de montagem que estão no host e são compartilhados entre host e containers. Cada container pode ter um ou vários desses pontos de montagem, e é bem interessante usá-los para o tipo de conteúdo que não pode ser perdido.

É uma boa prática criar containers sem estado, que pois sua portabilidade não dependerá do estado adicional, apenas do container.

Default Volume Content

Supondo que um Data Volume deva conter configurações, é interessante que você forneça uma configuração padrão, ou um arcabouço de configuração, para facilitar o trabalho de quem utiliza seu container, além de reduzir o atrito na implantação. No tópico EntryPoint.sh falamos do que um EntryPoint.sh pode fazer, umas das atividades extremamente relevantes em imagens profissionais, é analisar um determinado diretório, para tomar a decisão de copiar arquivos-padrão para lá. Isso é muito útil quando esses diretórios fazem parte de um Data Volume, um ponto de montagem para o seu container.

Lightweight Containers

No post DockerFile – Ubuntu + SSH + WebMin como criar uma imagem que fere praticamente todas as boas práticas. Mas qual o motivo?

  1. Imagens devem atender a uma única necessidade, pois assim facilita a manutenção, evolução, gestão e distribuição.
  2. Containers destinados a uma única finalidade podem depender de outros containers, que por sua vez podem ser trocados, por containers criados com imagens diferentes do mesmo produto ou serviço, seja por evolução, ou por configurações mais completas, ou por produtos similares de outras comunidades ou mesmo fabricantes. É o que acontece caso queira migrar do Memcached para o Redis. Bastaria criar um novo container Redis, dropar o Container Mamecached, e reapontar seus consumidores.

Então para que eu criaria um container “gordo”?

A resposta é simples, para fazer testes, das mais variadas naturezas:

  • Desde compreender como o Docker interfere no seu ambiente.
  • Compreender diferenças entre containers SO’s completos e containers.
  • Analisar os impactos de instalações em detalhes.

Does not expose mystique port

Os containers por padrão, recebem IP’s virtuais, isso significa que seu container pode utilizar todas1 as portas possíveis, sem entrar em conflito com nenhum outro container. A preocupação com alocação de portas é responsabilidade de quem vai criar um container, não de quem cria imagens. Cada imagem deve utilizar a porta padrão da ferramenta ou produto. Não complique! HTTP utiliza porta 80 e 443, Redis, RabbitMQ, MySQL/MariaDB, entre outros, utilizam portas específicas, não invente.

Agradecimentos

Obrigado a você que leu até aqui, se gostou, curta o post, assine, compartilhe com os amigos e colegas de trabalho. Essa semana será dedicada ao Docker, portanto teremos muito a falar nesse tema.

Observações

1) Somente portas do sistema são excepcionais.

 

hangout-docker-2016-03-04

Save The Date

Nessa sexta-feira, dia 4/Mar/2016!

Nessa semana vamos bater um papo no Canal.Net do Youtube, vamos falar sobre Docker, Containers, mostrar alguns exemplos e falar muito sobre tudo o que você quer saber sobre Docker. Se já tiver perguntas, podem mandar!

O Cloud Native .NET é meu principal projeto.

Onde empenho energia para ajudar, acompanhar, direcionar Desenvolvedores, Líderes Técnicos e jovens Arquitetos na jornada Cloud Native.

Conduzo entregando a maior e mais completa stack de tecnologias do mercado.

Ao trabalhar com desenvolvedores experientes, eu consigo usar seu aprendizado com .NET, banco de dados, e arquitetura para encurtar a jornada.

Ao restringir à desenvolvedores .NET eu consigo usar do contexto de tecnologias e problemas do seu dia-a-dia, coisas que você conhece hoje, como WCF, WebForms, IIS e MVC, por exemplo, para mostrar a comparação entre o que você conhece e o que está sendo apresentado.

É assim que construímos fundamentos sólidos, digerindo a complexidade com didática, tornando o complexo, simples.

É assim que conseguimos tornar uma jornada densa, em um pacote de ~4 meses.

Eu não acredito que um desenvolvedor possa entender uma tecnologia sem compreender seus fundamentos. Ele no máximo consegue ser produtivo, mas isso não faz desse desenvolvedor um bom tomador de decisões técnicas.

É preciso entender os fundamentos para conseguir tomar boas decisões.

0 comentários

Enviar um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Luiz Carlos Faria

Mensagem do Autor

Espero que goste desse post. Não deixe de comentar e falar o que achou.

Se acha que esse post pode ajudar alguém que você conheça, compartilhe!

 

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.