30 de agosto de 2017 Waldemar Dibiazi Junior Desenvolvimento de Software, Infraestrutura, Linux
A construção de imagens dentro de ambientes baseados em containers se faz necessária, pois o deploy de cada serviço baseado em container possui particularidades.
Deste modo, independente de parte do trabalho já ter sido realizado por quem criou uma determinada imagem, certamente existirão tarefas completares no container que serão realizadas para adequar o serviço/aplicação que o container proverá para os usuários.
Sendo assim, após realizadas estas tarefas complementares, nada mais justo que fazer com que estas operações persistam, situação essa que demanda a criação de uma imagem que servirá de base para inicialização de novos containers.
A construção de imagem não consistirá apenas em utilizar um container que possui as tarefas necessária executadas (atualizar o sistema, instalar pacotes, etc).
Durante a construção de uma nova imagem, podemos ter a necessidade de transferir para a mesma arquivos de configuração (atualizados), instalar novos pacotes em relação a imagem gerada anteriormente. Deste modo, recursos como Dockerfile são de grande utilidade, pois permitem parametrizar a construção de imagens, bem como, documentar estas informações.
Neste artigo estaremos vendo como:
Instalar o Docker no host que proverá a infraestrutura de execução dos containers (em um distribuição Debian);
Instalar o GIT em uma estação de trabalho Linux;
Construir um repositório local e remoto (através de chamada a API) do GIT.
Construindo Docker File para definir e documentar os parâmetros de construção de nossas imagens;
Replicar o Dockerfile do repositório local do GIT para o repositório no GIT Hub;
Construir uma imagem utilizando o Dockerfile hospedado no GIT Hub;
Criar um container a partir da nossa imagem personalizada;
Realizar o push de nossa imagem personalizada para o serviço Docker Hub.
Atualize o banco de dados de referência de pacotes do sistema:
Altere o arquivo de inicialização (baseado em SystemD) do Docker para permitir que nossa estação de trabalho consiga utilizar o Docker Client para interagir com o Docker Engine instalado neste host:
Neste arquivo deixe a linha ExecStart da seguinte maneira:
ExecStart=/usr/bin/dockerd -H fd:// -H 0.0.0.0:2376 --tlsverify=0
Deste modo, o cliente de linha de comando do Docker em nossa estação de trabalho irá conseguir interagir com o Docker Engine do servidor que hospedará os container através da porta TCP/2376.
Para este artigo não iremos utilizar a comunicação segura baseada em TLS, deste modo, estaremos utilizado a opção tlsverify desativada.
Em um próximo artigo estaremos verificando como configurar a comunicação segura entre o cliente docker e o Docker Engine.
Recarregue o arquivo de configuração alterado:
A instação do GIT é muito simples e pode ser realizado em distribuições Debian da seguinte maneira:
O processo de instalação em distribuições baseada em Red Hat, bem como em Mac OS/X e Windows é muito simples e pode ser verificado em Instalação do GIT em outros sistemas
Construindo um repositório local e remoto (através de chamadas da API) do GIT
A idéia de se construir um repositório no GIT para armazenar o arquivo de parâmetros para build de nossas imagens é interessante, pois quando estamos em ambientes com vários colaboradores em equipe, o uso do GIT auxilia não só na documentação de atualizações desse e de outros arquivos, mas permite criar versões diferentes desse arquivo e ramificações (branchs) na estrutura do projeto, permitindo que uma maior flexibilidade seja adicionada a equipe que trabalho sobre este e outros projetos base no GIT.
Antes de prosseguir, acesse o endereço para criar uma conta no GIT Hub: https://github.com/
Preencha os dados: Nome de usuário, E-mail e Senha. Após a criação da conta, logue no portal do Git Hub, pois a página inicial da sua conta já permitirá verificar que o nosso repositório foi criado.
Poderíamos criar o repositório diretamente no portal do Git Hub, entretanto, neste artigo iremos explorar o uso de algumas características básicas da API do Git Hub para que, a partir da nossa estação de trabalho, possamos tanto criar o repositório local no GIT Hub, bem como, cria-lo remotamente.
Em um terminal de nossa estação de trabalho (e não no nosso host que foi instalado o Docker), realize as tarefas a seguir:
Crie um diretório chamado git:
Abra o diretório git:
Crie o script a seguir:
#!/bin/bash echo -n "Informe o nome do novo repositorio: " read repoName userNameGitHub=PREENCHA_O_SEU_USUARIO_DO_GITHUB passGitHub=PREENCHA_A_SUA_SENHA_DA_CONTA_DO_GITHUB curl -u $userNameGitHub:$passGitHub https://api.github.com/users/$userNameGitHub/repos --silent | grep "name" | grep '"name":' |cut -f2 -d: |sed 's/"//g' |sed 's/,//g' | grep $repoName 1> /dev/null 2> null if [ $? -eq 0 ]; then echo Reposito ja existe. else echo Criando o respositorio... curl -u $userNameGitHub:$passGitHub https://api.github.com/user/repos -d "{\"name\":\"$repoName\"}" 1> /dev/null 2> null echo Verificando o repositorio remoto... curl -u $userNameGitHub:$passGitHub https://api.github.com/users/$userNameGitHub/repos --silent | grep "name" | grep '"name":' |cut -f2 -d: |sed 's/"//g' |sed 's/,//g' | grep $repoName 1> /dev/null 2> null if [ $? -eq 0 ]; then echo Reposito criando com êxito no GitHub. echo Criando diretorio do repositorio do projeto: $repoName mkdir $repoName cd $repoName echo Inicializando diretorio local para o repositorio git init echo Criando arquivo README.md echo "# $repoName" >> README.md echo "Propondo mudanças (enviando do diretorio de trabalho) para o estagio INDEX..." git add README.md echo "Confirmando as mudanças propostas (commit) - enviando para o estagio HEAD" git commit -m "Repositorio de testes Prorede Telecom - $repoName" echo Adicionando origem para enviar dados do repositorio local para remoto git remote add origin https://github.com/waldemarjr/$repoName.git git push -u origin master else echo Repositorio nao foi criado no GitHub fi fi
echo -n "Informe o nome do novo repositorio: "
userNameGitHub=PREENCHA_O_SEU_USUARIO_DO_GITHUB
passGitHub=PREENCHA_A_SUA_SENHA_DA_CONTA_DO_GITHUB
curl -u $userNameGitHub:$passGitHub https://api.github.com/users/$userNameGitHub/repos --silent | grep "name" | grep '"name":' |cut -f2 -d: |sed 's/"//g' |sed 's/,//g' | grep $repoName 1> /dev/null 2> null
echo Reposito ja existe.
echo Criando o respositorio...
curl -u $userNameGitHub:$passGitHub https://api.github.com/user/repos -d "{\"name\":\"$repoName\"}" 1> /dev/null 2> null
echo Verificando o repositorio remoto...
echo Reposito criando com êxito no GitHub.
echo Criando diretorio do repositorio do projeto: $repoName
echo Inicializando diretorio local para o repositorio
echo Criando arquivo README.md
echo "Propondo mudanças (enviando do diretorio de trabalho) para o estagio INDEX..."
echo "Confirmando as mudanças propostas (commit) - enviando para o estagio HEAD"
git commit -m "Repositorio de testes Prorede Telecom - $repoName"
echo Adicionando origem para enviar dados do repositorio local para remoto
git remote add origin https://github.com/waldemarjr/$repoName.git
echo Repositorio nao foi criado no GitHub
Concluída a edição do script, salve-o como makeGitRepo atribua a permissão de execução ao arquivo:
chmod +x makeGitRepo
Caso a ferramenta curl não esteja instalada em sua estação de trabalho, instale-a, pois será utilizada no script.
Este script realiza basicamente a consulta no portal GitHub através da sua conta criada, verificando se o repositório que desejamos criar já existe. Caso não exista, remotamente através da ferramenta CURL iremos interagir com a API do Git Hub e criaremos o repositório no Git Hub remotamente.
Caso não exista o repositório no Git Hub, o script criará dentro do atual diretório (git), um diretório com o nome desejado para o repositório.
Em seguida, através da ferramenta git será criada a estrutura do nosso repositório local, através do comando git init.
Por questões de boas práticas, o script irá criar o arquivo README.md e dentro dele inserir a string
"# nome do projeto"
Em seguida o script irá propor as mudanças no repositório (criação do arquivo README.md) enviando-o para o estágio INDEX (estágio intermediário) através do comando git add README.md, operação essa muito comum quando mudanças ocorrem dentro do repositório.
Em seguida iremos confirmar a proposta de mudanças (criação do novo arquivo) enviando-o para o estágio HEAD (último estágio antes do envio do arquivo para o respositório), através do comando:
git commit -m "Comentário", onde o comentário é importante para documentar de forma breve o que o novo arquivo traz como mudanças, incluindo, codificação de versão.
Por fim o script irá realizar adição da referência ao repositório remoto para podermos replicar as informações entre o repositório local e o repositório remoto.
Execute o script makeGitRepo:
./makeGitRepo
Informe o nome do nosso novo repositório, neste caso, apache.
Acesse o site do Git Hub com a sua conta recém criada e veja que o novo repositório já foi criado remotamente.
Clique sobre o nome do repositório apache e veja que o arquivo README.md encontra-se dentro do repositório.
Construindo Docker File para definir e documentar os parâmetros de construção de nossas imagens
Acesse o diretório apache que foi criado pelo script executado anteriormente, diretório esse que representa nosso repositório local do GIT, e em seguida crie o arquivo Dockerfile:
cd apache vi Dockerfile
Insira o conteúdo abaixo no arquivo:
FROM debian MAINTAINER Waldemar Dibiazi Junior <waldemar@proredetelecom.com.br> RUN apt-get update && apt-get install -y apache2 && apt-get clean ENV APACHE_LOCK_DIR="/var/lock" ENV APACHE_PID_FILE="/var/run/apache2.pid" ENV APACHE_RUN_USER="www-data" ENV APACHE_RUN_GROUP="www-data" ENV APACHE_LOG_DIR="/var/log/apache2" LABEL Description="Apache Webserver - Debian - v1.0" EXPOSE 80 ADD http://www.proredetelecom.com.br/docker/logo.jpg /var/www/html/ ADD http://www.proredetelecom.com.br/docker/index.html /var/www/html/ ADD http://www.proredetelecom.com.br/docker/styles.css /var/www/html/ RUN chown -R www-data: /var/www/html/. CMD /etc/init.d/apache2 start && /bin/bash
MAINTAINER Waldemar Dibiazi Junior <waldemar@proredetelecom.com.br>
LABEL Description="Apache Webserver - Debian - v1.0"
ADD http://www.proredetelecom.com.br/docker/logo.jpg /var/www/html/
ADD http://www.proredetelecom.com.br/docker/index.html /var/www/html/
ADD http://www.proredetelecom.com.br/docker/styles.css /var/www/html/
RUN chown -R www-data: /var/www/html/.
CMD /etc/init.d/apache2 start && /bin/bash
A primeira linha informa que nossa imagem será construída a partir de imagem pré existente no Docker Hub chamada debian.
A segunda linha informa o mantenedor da imagem que está sendo criada.
A próxima linha realiza a execução dos comando apt-get update, depois do comando apt-get install -y apache2 que irão basicamente atualizar o banco de dados de referências de pacotes do apt e em seguida instalar o pacote apache2.
Posteriormente a instalação serão iremos excluir todos os arquivos de cache do apt, uma ação importante, para reduzirmos a quantidade de arquivos que estará contida na imagem.
Em seguida, através do comando ENV estamos criando algumas variáveis de ambiente que serão utilizadas pelo binário do Apache no momento ele entrar em execução, dentre as variáveis de ambiente, temos APACHE_RUN_USER, que informa qual usuário do container irá iniciar o processo do Apache, e a variável APACHE_LOG_DIR que está indicando onde o Apache irá armazenar os seus logs.
Na próxima linha o parâmetro LABEL permite registrar em um dos metadatas da imagem, a descrição que documenta internamente na imagem, por exemplo, a finalidade desta imagem, softwares existentes nela, etc.
A linha posterior a LABEL é a linha EXPOSE, que tem a finalidade de fazer com que, durante a criação de uma container com base em nossa imagem, o Docker Engine irá expor a porta 80 (neste caso) para que hosts externo possam conecta-se a ela. O Docker Engine neste caso irá realizar um mapeamento, que levará na utilização de uma porta aleatória do host, onde toda conexão a esta porta sofrerá o processo de DNAT para porta 80 do serviço Apache em execução no container.
As três linhas contendo o comando ADD permitem realizar a transferência de um arquivo local ou remoto (nosso caso), onde no exemplo acima, os arquivos logo.jpg, index.html e styles.css existentes na URL acima serão copiados para o diretório /var/www/html da imagem que será construída com base nesse Dockerfile
Em seguida o comando RUN irá executar durante o build da imagem o comando chown para alterar o dono dos novos arquivos copiados para /var/www/html.
Por fim, o comando CMD irá iniciar o serviço do Apache no momento que nossa imagem for utilizada para criar um container, e em seguida o shell bash também será iniciado e já estaremos conectados ao container.
Replicando o Dockerfile do repositório local do GIT para o repositório no GIT Hub
Vamos realizar a transferência do novo arquivo existente no repositório local para o repostório no Git Hub:
git add Dockerfile git commit -m "Dockerfile - versão 0.1" git push
git commit -m "Dockerfile - versão 0.1"
Acesse o novamente o site do Git Hub com a sua conta recém criada, acesse o repositório apache, e veja que além do arquivo README.md, temos o novo arquivo Dockerfile.
Construindo uma imagem utilizando o Dockerfile hospedado no GIT Hub
Antes de realizar o processo de construção (build) da nossa imagem, iremos instalar na nossa estação de trabalho a ferramenta de linha de comando do docker:
Supondo que o servidor onde o Docker Engine está instalado possui o endereço IP 192.168.1.11, então iremos realizar a interação com o Docker Engine deste servidor através da sua API:
docker --tlsverify=0 --host tcp://192.168.1.11:2376 ps -a
Deste modo, estaremos gerenciando o host remoto, bem como, realizando o build da nossa imagem diretamente neste host remoto.
Vamos executar o build da imagem (utilizando nosso Dockerfile existente no Git Hub):
export userNameGitHub=SUA_CONTA_DE_USUARIO_DO_GIT_HUB docker --tlsverify=0 --host tcp://192.168.1.160:2376 build -t "teste/apache-debian:1.0" github.com/$userNameGitHub/apache/ docker --tlsverify=0 --host tcp://192.168.1.11:2376 images
export userNameGitHub=SUA_CONTA_DE_USUARIO_DO_GIT_HUB
docker --tlsverify=0 --host tcp://192.168.1.160:2376 build -t "teste/apache-debian:1.0" github.com/$userNameGitHub/apache/
docker --tlsverify=0 --host tcp://192.168.1.11:2376 images
O último comando mostra que a imagem foi construída, portanto, vamos criar um container a partir desta nova imagem:
docker --tlsverify=0 --host tcp://192.168.1.160:2376 run -it --rm --hostname webserver01 --name webserver -P prorede/apache-debian:1.0
Com o comando run foi criada um container chamado webserver e em seguida o container foi iniciado e definido o hostname em tempo de execução (webserver01) utilizando a imagem recém criada: prorede/apache-debian:1.0
O parâmetro -P fez com que qualquer porta disponível no host onde o Docker Engine está em execução seja mapeada para a porta exposta (EXPOSE) no container, no caso, a porta 80 do Apache.
Pressione CTRL p q para sair do container sem finalizar a execução dele.
Vamos verificar qual porta no host o container está em execução foi mapeada:
docker --tlsverify=0 --host tcp://192.168.1.11:2376 ps
Será exibida uma referência equivalente a:
CONTAINER ID IMAGE: a02afe735a2b
COMMAND : prorede/apache-debian:1.0 "/bin/sh -c '/etc/…"
CREATED: 11 minutes ago
PORTS: 0.0.0.0:32768->80/tcp
NAMES: webserver
No caso acima, a porta alocada no host do Docker Engine foi 32768, portanto, acesse o endereço http://192.168.1.11:32768
Podemos verificar que o container em execução foi criado utilizando uma imagem personalizada, e que esta imagem, além de ter o Apache instalado, recebeu três arquivos que compõem a página de exemplo exibida.
Realizando o push de nossa imagem personalizada para o serviço Docker Hub.
Para finalizar o artigo, acesse o site: https://hub.docker.com/
Crie uma conta no site, informando os dados básicos como: Docker ID, E-mail e Senha.
Para podermos realizar o push (envio) da nossa nova imagem, devemos nos autenticar no Docker Hub com a conta recém criada.
docker --tlsverify=0 --host tcp://192.168.1.11:2376 login docker --tlsverify=0 --host tcp://192.168.1.160:2376 push prorede/apache-debian:1.0