Primeiros passos – Criando uma imagem

Olá pessoal,

Anteriormente vimos o que era uma imagem e o que era um Dockerfile, agora vamos descobrir como criar uma imagem a partir da interação com um container. Vamos trabalhar da seguinte maneira:

Vamos criar uma imagem com apache com interação com o container.

Vamos começar criando o container com docker run -it centos /bin/bash agora que estamos dentro dele, vamos executar os seguintes comandos:

yum install wget -y
wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
rpm -ivh epel-release-7-5.noarch.rpm

yum install httpd -y,

Instalamos o apache dentro do container, mas quando iniciarmos o container novamente, o serviço do apache não irá iniciar, pois o container não possui os serviços de inicialização então vamos usar um serviço chamado Supervisord que faz com que sempre que eu reiniciar o container eu possa já iniciar alguns serviços.

sudo yum install python-setuptools
sudo easy_install pip
sudo pip install supervisor
echo_supervisord_conf > supervisord.conf
sudo cp supervisord.conf /etc/supervisord.conf
sudo mkdir /etc/supervisord.d/
sudo vi /etc/supervisord.conf

Com o arquivo de configurações do supervisord aberto vamos alterar e adicionar algumas linhas:

Altere a linha que tenha

[include]
files =
[include]
files = /etc/supervisord.d/*.conf

Agora vamos criar o arquivo: vi /etc/rc.d/init.d/supervisord

Coloque esse código dentro do arquivo:

#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/rc.d/init.d/functions

prog="supervisord"

prefix="/usr/"
exec_prefix="${prefix}"
prog_bin="${exec_prefix}/bin/supervisord"
PIDFILE="/var/run/$prog.pid"

start()
{
       echo -n $"Starting $prog: "
       daemon $prog_bin --pidfile $PIDFILE
       [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup"
       echo
}

stop()
{
       echo -n $"Shutting down $prog: "
       [ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown"
       echo
}

case "$1" in

 start)
   start
 ;;

 stop)
   stop
 ;;

 status)
       status $prog
 ;;

 restart)
   stop
   start
 ;;

 *)
   echo "Usage: $0 {start|stop|restart|status}"
 ;;

esac
sudo chmod +x /etc/rc.d/init.d/supervisord
sudo chkconfig --add supervisord
sudo chkconfig supervisord on
supervisord

Agora já podemos adicionar nosso serviço até o supervisord. Abra novamente o arquivo: /etc/supervisord.conf
Adicione ao final do arquivo as seguintes linhas.

[program:httpd]
command=/usr/sbin/httpd -D FOREGROUND -k start
environment=APACHE_LOG_DIR=/var/log/httpd
redirect_stderr=true

Após isso vamos executar supervisorctl update e supervisorctl você poderá ver que foi adicionado o serviço httpd ao supervisord.
Vamos criar o arquivo vi /run.sh e dentro dele colocar as linhas seguintes:

#!/bin/bash
supervisord &
sleep 2

/bin/bash

chmod +x /run.sh

Agora vamos criar a imagem, pressione CTRL + P + Q . Agora estamos no console do Host, para criar a imagem vamos executar docker commit id_container nome_imagem. Agora é só colocar docker run -it nome_imagem /run.sh e você estará iniciando seu Servidor Web.

Obrigado pessoal, por hoje é isso.

O que são Capabilities

Olá!

Hoje vamos ver algumas features de segurança que pertencem não apenas ao Docker, mas sim ao LXC, são as capabilities.

Em sistemas Unix like, há basicamente duas categorias de processos: processos privilegiados, que executam com ID 0 (superusuário) e os não-privilegiados, que executam com ID maior que 0.

Basicamente os processos privilegiados ignoram todas as verificações de permissões de kernel, enquanto os processos não-privilegiados estão sujeitos a algumas checagens para sua correta execução, normalmente: UID efetivo (usuário dono do arquivo/binário, etc), GID efetivos (grupo dono do arquivo/binário, etc) ou lista de grupo suplementar (mais conhecidas como ACL’s – Access Control List).

Do kernel 2.2 em diante o Linux dividiu as formas tradicionais de privilégios associados ao superusuários em unidades diferentes, conhecidas como capacidades, que podem ser habilitadas e desabilitadas independentemente umas das outras. Essas capacidades são atribuídas por thread, ou seja, threads do mesmo processos podem ter suas capacidades de execução modificadas.

 No Docker é possível modificar essas capacidades, habilitando ou desabilitando conforma sua necessidade, vale lembrar que todo container executa de forma não privilegiada, ou seja, ele tem sua execução restrita, quando é adicionada uma capacidade a execução de um container, é dado o privilegio para que o mesmo possa executar alguma ação como root, isso pode ser um problema de segurança, dependendo do seu ambiente.

Vamos ver algumas capacidades que podem ser atribuídas a um container, e que são normalmente utilizadas:

CAP_SETPCAPModifica capacidades de um processo
CAP_SYS_MODULEInsere ou remove módulos do kernel
CAP_SYS_RAWIOModifica memória do Kernel
CAP_SYS_PACCTConfigura quota de processo
CAP_SYS_NICEModifica prioridade do processo
CAP_SYS_RESOURCESobrescreve os limites de recursos
CAP_SYS_TIMEModifica a hora de sistema
CAP_SYS_TTY_CONFIGConfigura interface tty
CAP_AUDIT_WRITEEscreve logs de auditoria
CAP_AUDIT_CONTROLConfigura auditoria dos subsistema
CAP_MAC_OVERRIDEIgnora politicas de MC do Kernel
CAP_MAC_ADMINConfiguração de MAC
CAP_SYSLOGModifica o comportamento de logs
CAP_NET_ADMINConfigura funções de rede
CAP_SYS_ADMINPossibilita execução totalmente privilegiada.

Agora, para habilitar alguma capacidade (ou CAP) no Docker, pode ser utilizado o parâmetro: –cap-add=NOMEDACAP, algo parecido com isso:

docker run --cap-add=NOMEDACAP -i -t --rm centos /bin/bash

Para remover alguma CAP basta adicionar o parâmetro –drop-cap, ficaria assim:

docker run --cap-add=ALL --cap-drop=NET_ADMIN -i -t --rm centos /bin/bash

Seguindo os parâmetros acima, todas as CAPs serão habilitadas para este container, menos a CAP NET_ADMIN, com isso todas as demais operações serão permitidas ao container, menos as operações de rede, como modificação de ip, configurações de rotas, etc.

Por hoje era isso, fiquem atentos para as novidades!

Coleta de recursos

Olá pessoal,

Hoje vamos ver como mostrar os recursos sendo utilizado por cada container, como: Rede, Memória, Disco e CPU.

Vamos mostrar quatro maneiras de coletar os recursos. São elas:

– Docker stats

– API

– Cadvisor

– Cgroups

Docker stats: o comando docker stats foi adicionado nas ultimas versões do Docker, com ele agora podemos verificar as métricas de cada container em tempo real, porém não temos acesso ao histórico desses containers. Para usar este comando basta colocar docker stats id_container.

API: Em cada distribuição Linux o modo de habilitar a API é de uma maneira diferente. Vou mostrar aqui como fazer no CentOS 7. Abra o arquivo /etc/sysconfig/docker e altere a linha que tem OPTIONS= por OPTIONS=--selinux-enabled -H fd:// -H tcp://0.0.0.0:4243. Após isso reinicie o serviço do docker para que a porta da API seja aberta no host. Isso quer dizer que a porta 4243 deste servidor estará acessível de qualquer outro computador. Executando o seguinte comando podemos ver os containers que estão iniciados:

curl -X GET http://ipservidor:4243/containers/json

Esse comando retorna o JSON com as informações dos containers que estão iniciado.

Cadvisor: Fornece aos usuários a visualização de consumo por processo no host e também do container em tempo real. Com ele podemos verificar os recursos de Rede, Memória, CPU e informações do sistema. Para tudo isso basta executar o seguinte comando:
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest

Agora vá até o seu navegador coloque o seguinte endereço http://ip:8080

Cgroups: O Docker cria a limitação de seu containers através de CGROUPS (Acesse Aqui para saber mais sobre o que é CGROUPS) com ele podemos visualizar quanto de recursos aquele processo está usando. Dentro de /sys/fs/cgroup estão os recursos que podemos limitar no Docker. Podemos acessar o diretório memory/system.slice/docker-xxxxxxx.scope e dentro dele dar um cat memory.usage_in_bytes que nos mostra a quantidade de memória que o container xxxxxxx está usando. Dentro desse diretório temos outras contadores também que nos próximos posts apresentaremos.

Bom pessoal, por hoje foi isso então, em nossos próximos posts estaremos trabalhando outros tópicos avançados dentro do ambiente Docker, então fique atento, e tendo dúvidas já sabe, nos mande uma mensagem, abraço!

O que é uma imagem?

Olá pessoal,

Hoje vamos falar a sobre images, mas a final o que são images no Docker?

Images Docker são compostas por sistemas de arquivos de camadas que ficam uma sobre as outras. Ela é a nossa base para construção de uma aplicação, ela pode ser desde o base do CentOS como também um CentOS com Apache, PHP e MySQL.

Em uma Image temos o que chamamos de base que é um sistema de arquivos de inicialização bootfs, que é muito parecido com o sistema de boot do Linux / Unix. Nessa parte é onde temos toda a criação dos cgroups para fazer todo o controle e limitações de processos, namespace para blindar o container. O Docker nunca irá interagir com o sistema de arquivos de inicialização, pois quando o recipiente é iniciado ele é movido para a memória e o boot do sistema de arquivos é desmontado para liberar a memória RAM usada pela imagem de disco initrd. Isso parece muito com a pilha de virtualização típica do Linux. A próxima camada de uma imagem é a raiz na qual trabalha o rootfs, na parte superior do sistema de arquivos de inicialização, este rootfs pode ser um ou mais sistemas operacionais (Ex: Ubuntu, CentOS).

No momento do boot o sistema de arquivos raiz é montado somente leitura e depois de uma checagem de integridade é alterado para leitura e gravação. Isso no começo pode ser muito confuso, mas com a imagem abaixo vocês devem entender melhor como funciona.

docker-filesystems-busyboxrw

Como podemos ver na imagem, temos a parte dobootfs que é a parte do Kernel e a também a camada do rootfs que é a do Debian. Mais acima temos algumas adições de features na imagem que são add emacs e add apache. Todas essas camadas abaixo são somente leitura então nada será alterado nessas partes, a camada de escrita é apenas a que está acima dessas outras quatro camadas, é nessa camada que o usuário ou administrador do container irá interagir e poderá criar novas imagens, por exemplo adicionando um serviço php e dai criará uma nova imagem com mais uma camada somente leitura e assim vamos criando nossas imagens.

Por hoje é isso pessoal, em breve vamos estar mostrando como criar uma imagem, então fique ligado em nossos posts.

O que é Dockerfile

Olá!

Como mencionado neste post, o Docker possui alguns recursos que permitiram sua popularização pelo mundo a fora, além da API de integração, o Docker permite que possamos criar imagens a partir de um arquivo de definição, esse arquivo chama-se Dockerfile.

Vamos lá. Como explicado anteriormente em alguns posts, uma imagem nada mais é do que um ambiente totalmente encapsulado e pronto para ser replicado onde desejar. Podemos montar esse ambiente através de um container que esteja em execução (Exportando o mesmo), ou através da criação a partir do Dockerfile, que nada mais é do que um arquivo de definição onde é possível realizar ou preparar todo ambiente a partir de um script de execução. Em resumo, o Dockerfile é um arquivo texto com instruções, comandos e passos que você executaria manualmente, basicamente o Docker executa uma receita de bolo.

Através do comando docker build, o Docker realizar a execução desses passos e no final da execução ele encapsula cada layer gerada para dentro da imagem. Mas o Dockerfile deve seguir uma ordem ou formatação correta para que o build seja feito de forma certa, por exemplo, o formato do texto deve respeitar: INSTRUÇÃO argumento, onde INSTRUÇÃO é o comando que o build deve executar, e argumento são as instruções que deve fato serão feitas, por exemplo:

RUN yum update

Onde:

RUN: É a instrução;

yum update: Argumento que será executado.

Abaixo podemos visualizar todas as opções de instruções disponíveis:

  • FROM: Informa a partir de qual imagem será gerada a nova imagem, lembrando que em poucos casos (Veremos em posts futuros), uma imagem será gerada se um imagem base;
  • MAINTAINER: Campo opcional, que informa o nome do mantenedor da nova imagem;
  • RUN: Especifica que o argumento seguinte será executado, ou seja, realiza a execução de um comando;
  • CMD: Define um comando a ser executado quando um container baseado nessa imagem for iniciado, esse parâmetro pode ser sobrescrito caso o container seja iniciado utilizando alguma informação de comando, como: docker run -d imagem comando, neste caso o CMD da imagem será sobrescrito pelo comando informado;
  • LABEL: Adiciona metadados a uma imagem, informações adicionais que servirão para identificar versão, tipo de licença, ou host, lembrando que a cada nova instrução LABEL é criada uma nova layer, o Docker recomenda que você não use muitas LABEL. É possível realizar filtragens posteriormente utilizando essas LABEL.
  • EXPOSE: Expõem uma ou mais portas, isso quer dizer que o container quando iniciado poderá ser acessível através dessas portas;
  • ENV: Instrução que cria e atribui um valor para uma variável dentro da imagem, isso é útil para realizar a instalação de alguma aplicação ou configurar um ambiente inteiro.
  • ADD: Adiciona arquivos locais  ou que estejam em uma url, para dentro da imagem.
  • COPY: Copia arquivos ou diretórios locais para dentro da imagem.
  • ENTRYPOINT: Informa qual comando será executado quando um container for iniciado utilizando esta imagem, diferentemente do CMD, o ENTRYPOINT não é sobrescrito, isso quer dizer que este comando será sempre executado.
  • VOLUME: Mapeia um diretório do host para ser acessível pelo container;
  • USER: Define com qual usuário serão executadas as instruções durante a geração da imagem;
  • WORKDIR: Define qual será o diretório de trabalho (lugar onde serão copiados os arquivos, e criadas novas pastas);
  • ONBUILD: Define algumas instruções que podem ser realizadas quando alguma determinada ação for executada, é basicamente como uma trigger.

Veja abaixo um exemplo de Dockerfile completo:


# VERSION 0.1

FROM ubuntu
RUN echo foo > bar
# Saida parecida com ===> 907ad6c2736f

FROM ubuntu
RUN echo moo > oink
# Saida parecida com ===> 695d7793cbe4

EXPOSE 5900

# Você terá duas imagens, 907ad6c2736f com /bar, e 695d7793cbe4 com
# /oink.


Basta copiar esse código acima em um arquivo chamado Dockerfile e em seguir executar o comando: docker build -t minhaimagem . . E pronto, será criada uma imagem com o nome de minhaimagem, basta usa-la para o que precisar.

Nos próximos posts veremos como criar uma imagem mais complexa, iremos montar um ambiente completo para um site em WordPress, e aprendermos um pouco mais sobre outros recursos do docker build.

Fique atento, e tendo dúvidas já sabe, nos mande uma mensagem, abraço!

Primeiros passos – Instalação

Olá pessoal,

Hoje vamos ver como damos o pontapé inicial com Docker, vamos começar com a instalação e depois algumas informações básicas sobre alguns comandos.

Usuários que tem o seu sistema baseado em Debian podem usar o apt-get ou o aptitude:

sudo apt-get update
sudo apt-get install docker.io

Usuários que tem o seu sistema baseado em RedHat podem usar o yum:

yum install docker

A versão de Docker que estou utilizando é a versão 1.6.2 que é a versão mais nova até hoje. Na instalação default de ambiente de Docker as configurações principais de seus contêineres ficam em /var/lib/docker aqui você pode encontrar o .json de todos os seus containers com suas respectivas configurações, em nossos próximos posts estaremos mostrando o que significa cada parâmetro e como podemos melhorar a performance de nosso ambiente. Agora vou mostrar para vocês os comandos que temos no Docker:

docker attach  – Acessar dentro do container e trabalhar a partir dele.
docker build   – A partir de instruções de um arquivo Dockerfile eu possa criar uma imagem.
docker commit  – Cria uma imagem a partir de um container.
docker cp      – Copia arquivos ou diretórios do container para o host.
docker create  – Cria um novo container.
docker diff    – Exibe as alterações feitas no filesystem do container.
docker events  – Exibe os eventos do container em tempo real.
docker exec    – Executa uma instrução dentro do container que está rodando sem precisar atachar nele.
docker export  – Exporta um container para um arquivo .tar.
docker history – Exibe o histórico de comandos que foram executados dentro do container.
docker images  – Lista as imagens disponíveis no host.
docker import  – Importa uma imagem .tar para o host.
docker info    – Exibe as informações sobre o host.
docker inspect – Exibe r o json com todas as configurações do container.
docker kill    – Da Poweroff no container.
docker load    – Carrega a imagem de um arquivo .tar.
docker login   – Registra ou faz o login em um servidor de registry.
docker logout  – Faz o logout de um servidor de registry.
docker logs    – Exibe os logs de um container.
docker port    – Abre uma porta do host e do container.
docker pause   – Pausa o container.
docker ps      – Lista todos os containers.
docker pull    – Faz o pull de uma imagem a partir de um servidor de registry.
docker push    – Faz o push de uma imagem a partir de um servidor de registry.
docker rename  – Renomeia um container existente.
docker restart – Restarta um container que está rodando ou parado.
docker rm      – Remove um ou mais containeres.
docker rmi     – Remove uma ou mais imagens.
docker run     – Executa um comando em um novo container.
docker save    – Salva a imagem em um arquivo .tar.
docker search  – Procura por uma imagem no Docker Hub.
docker start   – Inicia um container que esteja parado.
docker stats   – Exibe informações de uso de CPU, memória e rede.
docker stop    – Para um container que esteja rodando.
docker tag        – Coloca tag em uma imagem para o repositorio.
docker top        – Exibe os processos rodando em um container.
docker unpause – Inicia um container que está em pause.
docker version – Exibe as versões de API, Client e Server do host.
docker wait   – Aguarda o retorno da execução de um container para iniciar esse container.

Esses são todos os comandos que possuímos na versão 1.6.2 do Docker. Nos próximos posts estaremos mostrando como utilizar todos esses comandos e em qual momento devemos escolher entre um e outro.

Ficou com dúvida? Gostaria de saber mais? Algum feedback a nos dar? Deixe sua mensagem e vamos conversando.

Abraço!

Como Funciona o Filesystem no Docker?

Olá pessoal!

Para você que está começando a ler nossos posts agora, sugiro que leia antes esseesse link que explicam o que é o Docker e como ele funciona. Hoje nós abordaremos um dos assuntos mais importantes dentro do Docker: O Filesystem.

O sistema de arquivos do Docker é chamado de layered, ou seja, é um sistema de arquivo em camadas, o que isso quer dizer?

Um sistema de arquivo comum, possui basicamente duas camadas:

bootfs: Onde ficam o sistema de Boot do sistema e o Kernel.

rootfs: Inclui o sistema de arquivo do sistema, incluindo a arquitetura de diretório, em sistemas unix-like: /dev, /proc, /bin, /etc, /lib, /usr, e /tmp assim como os arquivos de configuração e binários do sistema.

Quando o sistema é iniciado ele carrega o rootfs primeiramente em modo somente leitura, verifica sua integridade e em seguida remonta-o como leitura/escrita e assim fica disponível para o usuário/aplicação.

No Docker temos essa arquitetura também, mas com um diferencial, a camada de escrita que o processo/aplicação visualiza não é o mesmo rootfs base, e sim uma camada de abstração do rootfs, isso é o que faz com que um container torne-se portável, pois as modificações realizadas não são aplicadas ao sistema origem do container, e sim na camada a qual o sistema visualiza.

Para ficar mais claro, veja na figura abaixo como é um sistema tradicional:

    docker-filesystems-generic1

 

Agora veja como é o filesystem no docker:

 

docker-filesystems-multiroot

 

 

Como podem notar o bootfs em vez de ser único por sistema/container, é compartilhado entre eles, mas o rootfs é isolado por camadas, ou seja, o que deve ser em comum entre o host e container é compartilhado via AUFS, que monta uma camada de leitura/escrita em cima do filesystem em somente leitura, isso garante que modificações feitas dentro do container não afetem o sistema de arquivos do host.

A imagem abaixo ilustra melhor como funciona essas camadas:

docker-filesystems-busyboxrw

Um detalhe nessa arquitetura é que a cada modificação e commit do container é gerada uma nova camada, ou seja, digamos que eu inicie um container a partir de uma imagem do Debian, e instale o serviço apache dentro desse container, quando eu for transformar esse container em uma imagem, essa imagem possuirá a primeira camada que é do sistema Debian, e uma camada adicional que refere-se a instalação do serviço apache. Na imagen abaixo podemos visualizar melhor esse ambiente.

 

docker-filesystems-multilayer-update

Lembrando que uma imagem pode ser utilizada diversas vezes, ou seja, há compartilhamento da imagem entre os containers, mas os containers depois de iniciados são isolados uns dos outros, na imagem abaixo podemos visualizar essa arquitetura.docker-filesystem

Como podemos notar, há o compartilhamento das camadas inferiores, pois elas fazem parte da imagem que originou o container, e a camada de escrita, que faz parte do container rodando, é isolada para cada container.

Por hoje é isso, veremos em breve um pouco mais sobre filesystem no Docker, e algumas outras questões relacionadas a essa arquitetura. Ficou com dúvida? Gostaria de saber mais? Algum feedback a nos dar? Deixe sua mensagem e vamos conversando.

Abraço!