Docker Tutorial – Introdução ao Docker (Parte 2)

, Author

P>Agora ao artigo anterior, agora já sabe o que é o Docker. Agora, venha aprender a utilizá-lo com os principais comandos e interacções básicas! Tudo sobre a baleia!

Introdução

Este artigo faz parte de uma série de posts sobre Docker e o seu ambiente:

  • Tutorial Docker: compreender Docker (parte 1)
  • Tutorial Docker: começar com Docker (parte 2)
  • Tutorial Docker: Os comandos Docker (parte 3)

Docker é um sistema de gestão de contentores (como já sabe pelo artigo Discovering Docker), e onde Docker é muito forte é que é capaz de tornar até as peças mais obscuras mais fáceis de usar.

Sobre a nossa baleia (Moby Dock para os seus amigos). Docker conta com uma API RESTFul API, sobre a qual falarei num futuro post. A isto, a empresa combinou um “docker-cli” que nos permite executar facilmente comandos do nosso terminal.

De um terminal, se executar o comando docker, obterá uma lista de comandos executáveis, que são:

$ docker…Commands: attach Attach to a running container build Build an image from a Dockerfile commit Create a new image from a container's changes cp Copy files/folders from a container's filesystem to the host path create Create a new container diff Inspect changes on a container's filesystem events Get real time events from the server exec Run a command in an existing container export Stream the contents of a container as a tar archive history Show the history of an image images List images import Create a new filesystem image from the contents of a tarball info Display system-wide information inspect Return low-level information on a container kill Kill a running container load Load an image from a tar archive login Register or log in to a Docker registry server logout Log out from a Docker registry server logs Fetch the logs of a container port Lookup the public-facing port that is NAT-ed to PRIVATE_PORT pause Pause all processes within a container ps List containers pull Pull an image or a repository from a Docker registry server push Push an image or a repository to a Docker registry server restart Restart a running container rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save an image to a tar archive search Search for an image on the Docker Hub start Start a stopped container stop Stop a running container tag Tag an image into a repository top Lookup the running processes of a container unpause Unpause a paused container version Show the Docker version information wait Block until a container stops, then print its exit code…

E aí tem, com esta lista, tem tudo em mãos para gerir os seus contentores e imagens. Fácil, não é?

(Para aqueles que usariam o boot2docker, recomendo que sigam a documentação e abram um terminal no qual possam conversar com o vosso Moby Docker),

Docker e as suas imagens

Até agora, nunca vos falei de imagens. Só vos falei de contentores. E no entanto, as imagens Docker são de importância crítica. Aqui está um pouco mais sobre estas imagens, tão essenciais no funcionamento do Docker.

Uma imagem é um recipiente estático. Pode comparar uma imagem com uma fotografia de um recipiente num determinado momento, uma espécie de fotografia de um dos seus recipientes. Quando se quer trabalhar com um recipiente, declara-se necessariamente um recipiente de uma imagem.

Também, as imagens Docker funcionam por herança a partir de outras imagens. A sua própria imagem Tomcat herda da imagem Java. Essa mesma imagem Java que pode ter sido construída a partir de um Debian. Assim, a herança pode ir muito longe! O recipiente criado a partir de uma imagem contém o delta entre a imagem de base a partir da qual o recipiente foi instanciado e o estado actual. Graças a este sistema, a duplicação de dados é baixa.

O ponto técnico!

Uma imagem pode ter sido construída a partir de outra imagem que ela própria pode ter sido construída a partir de outra imagem. Este sistema funciona perfeitamente através de um sistema de empilhamento de contentores. Portanto, quando constrói uma imagem a partir de outra imagem, está na realidade a armazenar todos os contentores que lhe permitiram obter desde a sua imagem base até à sua imagem final. Pode visualizar do que estou a falar executando o comando “docker history .

Pode ver a sua “biblioteca” de imagens em qualquer altura com o comando “docker images”. Verá que, à medida que vai passando pelos seus projectos, terá cada vez mais imagens. Utilizável como “moldes” para iniciar os seus projectos ou, no mínimo, os seus novos contentores.

Para ver a sua biblioteca de imagens:

$ docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

Aí está, acabou de interagir com Docker pela primeira vez. Não espere ver nada, por defeito não tem imagens. Lógica. Felizmente, outros já têm bases de imagens prontas a usar!

Como recuperar (puxar) uma imagem Docker?

Existe uma plataforma mantida pela Docker na qual qualquer pessoa pode empurrar e puxar imagens. É como as imagens do GitHub of Docker! A partir de agora, vamos tentar obter uma imagem. Há imagens oficiais para tudo e mais alguma coisa! Esta biblioteca partilhada gigante é o Registo do Docker Hub!

P>Pode procurar uma imagem de uma distribuição ou produto já instalado. Comecemos por encontrar uma imagem do Docker que possamos utilizar. Tem duas maneiras de procurar uma imagem: através da interface web, ou através do comando “docker search”.

I’m going to use the “docker search” command (because I’m a bearded man) to find Debian distributions, which have enough stars (trust of the platform users). O comando é o seguinte.

$ docker search --stars=10 debianNAME DESCRIPTION STARS OFFICIAL AUTOMATEDdebian (Semi) Official Debian base image. 248 google/debian 25 tianon/debian use "debian" instead - https://index.docke... 13

E aqui estão os resultados disponíveis com os meus critérios. Comecemos por ser simples: o que me interessa é um Debian oficial. Existe de facto uma, denominada debian, com 248 estrelas (!!) e assinalada no atributo OFFICIAL. Em frente, Moby Dock, puxa esta imagem!

$ docker pull debian…

Aqui está, após alguns segundos de descarregamento, tem uma imagem no seu anfitrião. Pode realmente vê-lo executando “imagens de doca”. Um comando que lista as imagens presentes na sua máquina.

Há outra forma que é menos útil numa base diária (mas ainda pode ser usada), que é importar uma imagem com o comando “docker load” de um ficheiro .tar.gz, inicialmente exportado por um Docker (de um colega, por exemplo).

Como criar uma imagem:

Agora queremos aprender a trabalhar de forma independente e a construir as nossas imagens à nossa vontade. Há vários métodos:

  1. o Dockerfile: já visto no primeiro artigo, permite, entre outras coisas, partir de uma imagem inicial, lançar acções e construir uma nova imagem.
  2. para lançar um contentor, executar acções por si próprio e submeter (com o comando “docker commit”) as alterações numa nova imagem.

Hoje não vou detalhar o segundo método, que para mim é menos útil no início. Numa nota pessoal, utilizo este método para historiar as minhas personalizações. Isto permite-me manter estados passo a passo da personalização do meu contentor, de modo a poder começar a partir de um passo específico, por exemplo (daí o uso do termo snapshot usado acima).

As diferenças entre um contentor e a sua imagem podem ser vistas graças ao comando “docker diff”.

Criar uma imagem com um ficheiro Docker

Este ficheiro tem uma mistura de instruções e metadados. Com este ficheiro, dá a receita de Docker para construir a sua imagem. O website oficial descreve obviamente o conjunto completo de instruções que podem ser feitas.

P>Deixemos começar por criar um ficheiro chamado Dockerfile (sem extensão! O nome deste ficheiro não é negociável) na pasta da nossa escolha, e digamos-lhe quais são as prerrogativas para a criação de uma nova imagem. Para o nosso exemplo, queremos partir de um Wheezy Debian (ou Debian 7), no qual adicionamos Nginx.

Linha por linha, vamos detalhar o nosso futuro Dockerfile:

1 – Indico a distribuição inicial com a linha

FROM debian:wheezy

2 – Indico a pessoa que escreveu este Dockerfile, neste caso sou eu. Graças à linha

MAINTAINER Baptiste Donaux <[email protected]>

3 – procuro os pacotes disponíveis e instalo o Nginx.

RUN apt-get update \ && apt-get install -y \ nginx

4 – Copio sucessivamente as configurações e scripts do meu sistema anfitrião para a minha imagem

COPY nginx.conf /etc/nginx/nginx.conf
COPY service_start.sh /home/docker/script/service_start.sh

5 – Aplico permissões para executar o meu script

RUN chmod 744 /home/docker/script/service_start.sh

6 – Eu defino um ponto de entrada: O primeiro script que será executado quando o contentor for iniciado

ENTRYPOINT /home/docker/script/service_start.sh

7 – A pasta onde estarei quando executar um novo contentor será WORKDIR

WORKDIR /home/docker

Temos todas as linhas para fazer o nosso Dockerfile. Aqui está na íntegra:

FROM debian:wheezyMAINTAINER Baptiste Donaux <[email protected]>RUN apt-get update \ && apt-get install -y \ nginxCOPY nginx.conf /etc/nginx/nginx.confCOPY service_start.sh /home/docker/script/service_start.shRUN chmod 744 /home/docker/script/service_start.shENTRYPOINT /home/docker/script/service_start.shWORKDIR /home/docker

Construindo uma imagem de um Dockerfile

Agora que temos um Dockerfile, queremos criar a nossa imagem. E o comando mágico é… “docker build”!

$ docker build .

Quando executa “docker build”, precisa de especificar o caminho para o Dockerfile (daí o ponto no fim do comando se executar o comando a partir do mesmo local).

Durante a construção verá todos os passos a correr um após o outro. A primeira corrida leva muito tempo, porque nenhuma das etapas já foi chamada. Numa segunda construção, verá as etapas a serem despachadas a alta velocidade! (Experimente, para ver!). Tudo isto desde que os passos anteriores não tenham sido modificados no seu Dockerfile, é claro!

Of course, Docker historiza todas as acções que executa (cada declaração executada num Dockerfile é armazenada num contentor intermediário). Este é também o princípio que é utilizado para realizar a herança entre imagens. Se as instruções não forem alteradas e a sua ordem for idêntica à anterior, NÃO são regeneradas porque o Docker sabe como utilizar a sua cache e reutilizar as acções já realizadas. Fortiche, a baleia!

Explicação: como funciona a cache do Docker?

A cache que o “construtor de docas” utiliza não é mágica (mesmo que pareça), mas é fácil de compreender.

Acima, falei-lhe vagamente do comando Docker-commit que lhe permite gerir estados das suas imagens guardando as alterações de um contentor numa nova imagem. Por defeito, quando se faz uma construção portuária, cada passo (cada declaração no seu ficheiro portuário) é armazenado num contentor intermédio (pode ver todos os passos de construção de uma imagem usando o comando de construção portuária-história). O Docker tem um violino interno para gerir os seus recipientes internos de modo a proporcionar o melhor desempenho na construção de uma imagem. Herança, historização, lembrar 😉 ?

Tagging an image or taking your images out of anonymity

Any image or container has a unique identifier. Poderíamos utilizar estes identificadores únicos, mas a Docker Inc forneceu uma funcionalidade para marcar as nossas imagens, bem como os nossos contentores para os reutilizar mais facilmente.

Aqui está como nomear as suas imagens:

  1. Dê um nome à construção da imagem com a opção –tag
  2. Utiliza o comando docker-tag
  3. Nomeia a tua imagem quando usares docker-commit

Mais exemplo concreto: criando uma imagem usando o comando docker-build e a sua opção –tag

$ docker build --tag="myImage"

Aqui está, agora faça uma imagem docker-build e a sua imagem correctamente etiquetada aparecerá na sua lista!

O ponto técnico!

Imagens podem ter tantos nomes e tantas etiquetas quantas quiser. A propósito, a imagem oficial do Debian Wheezy pode ser encontrada sob o nome debian:7, debian:latest ou mesmo debian:wheezy. Neste caso, aplicámos várias etiquetas no mesmo nome de imagem, mas talvez queira chamar a esta imagem outro nome.

default debian c90d655b99b2debian 7.8 c90d655b99b2debian latest c90d655b99b2debian wheezy c90d655b99b2debian 7 c90d655b99b2

Aqui verá que a imagem identificada por c90d655b99b2 também é identificada por defeito:debian.

Gestão de contentores

Agora essa gestão de imagens já não é um problema para si, falemos de contentores por um pouco.

Definir como funciona um contentor

Já falamos sobre isso acima, um contentor encarna a noção de um ambiente. Em Docker, mesmo as imagens são recipientes, mas a diferença entre uma imagem e um recipiente deve-se a comportamentos.

Imagens são estáticas; não se escreve directamente para uma imagem. Declaramos um recipiente DE uma imagem. Este recipiente viverá e conterá as diferenças feitas a partir da imagem de base. Segue?

Um contentor também contém outros elementos, armazena parâmetros de execução, tais como mapeamento de portas, pastas a serem partilhadas.

O ponto técnico !

Atualmente aplicamos parâmetros a um contentor como o reencaminhamento de portas, partilha de pastas… Mas não é possível alterar os seus parâmetros em tempo real. A Docker Inc. está também a trabalhar na possibilidade de alterar a quente as suas variáveis. Actualmente, a única forma de alterarmos as definições é:

  1. Guardar o seu contentor como imagem (docker commit)
  2. Launch um contentor da nova imagem com as definições completas que pretende utilizar.

Vamos fazer um exercício em conjunto.

Declarar um recipiente

Temos normalmente uma imagem debian com várias etiquetas na nossa máquina graças à imagem criada acima. Vamos declarar um contentor.

$ docker run debian:wheezy

Aí está, já correu um contentor a partir de uma imagem Docker! Com isto, não esperem fazer nenhuma loucura, mas é um começo. Se sentir que este comando não fez nada, pode ver com o comando “docker ps -l” que as coisas aconteceram:

$ docker ps -lCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES9b4841d73b6e debian:7 "/bin/bash" 3 seconds ago Exited (0) 3 seconds ago furious_hopper

Este retorno indica que um contentor chamado “furious_hopper” identificado pelo ID 9b4841d73b6e, correu o comando /bin/bash a partir de uma imagem debian:7 e terminou com o código de retorno 0. (Note que Docker sabe como nomear os seus contentores de uma forma original! Aqui furious_hopper!)

p>Even se o seu contentor estiver desligado (estado exilado), não é apagado, é armazenado (isto é importante para o seguinte). A propósito, pode exibir todos os contentores (tanto em funcionamento como parados) usando o comando “docker ps -a”.p>Agora queremos interagir com o nosso contentor. Para o fazer, teremos de usar algumas opções no comando “docker run”, que são:

$ docker run --tty --interactive debian:7

Você deve estar num belo contentor com uma batida pronta a responder. Verá que o tempo de lançamento é bastante baixo. Mas o que é que fizemos? Vamos detalhar o que significa:

  • A opção –tty permite-nos ligar a consola à nossa consola actual e não perder o foco. É por causa desta opção que o seu contentor não terminará.
  • li>A opção –interactiva permite-lhe falar com o seu contentor. Sem esta opção, qualquer coisa que escreva na sua consola não será passada para a bash.

No nosso caso, o comando foi /bin/bash mas isto não é uma coincidência. Ao declarar uma imagem (no seu Dockerfile), pode especificar alguns metadados como CMD que lhe permitem dar um comando padrão se nenhum for especificado.

Se quisesse executar um comando diferente de /bin/bash, poderia ter feito assim ao declarar o seu contentor:

$ docker run debian:7 echo Docker is fun

E voila, o seu contentor foi criado e executou o comando que deu (“echo Docker is fun”), e depois terminou porque nenhum comando executado levou o foco da consola.

Utilizar um recipiente

Agora que sabe como executar comandos num recipiente, vamos um pouco mais longe com um exemplo simples.

Um recipiente é o equivalente a um Sistema de Ficheiros. Além disso, o meu projecto Symfony utiliza uma base de dados. Uma vez que a minha base de dados vai mudar, não queremos perder os nossos dados (bem, suponho ;)!)! Este seria o caso se fizesse uma “corrida às docas” sempre que quisesse iniciar o seu serviço de base de dados. Porque faria isto? Porque, como se viu acima, o cais inicia um novo contentor. Uma nova! Não usa o que já foi criado antes! Vejamos como evitar este problema.

Vejamos o detalhe de como “correr a doca”

No início, era o comando (!) que eu usava o tempo todo. Agora nem por isso. O que é que o “estivador corre” realmente? Este comando executa sucessivamente dois outros comandos a que tem acesso: “criar doca” e “iniciar doca”. Vamos detalhá-los juntos.

docker-create

“docker create” é um comando indispensável! Se fizer um homem, notará que este contém as mesmas opções que “corrida às docas”. Com este comando, irá criar um contentor a partir de uma imagem, dando-lhe parâmetros de execução.

  • cartografia de portas
  • partilha de pastas

entre os dados parametrizáveis, poderá dar um nome ao seu contentor. Docker dará sempre um nome ao seu contentor (furious_hopper, lembre-se?), mas será mais fácil para si encontrar o seu contentor de projecto com um nome próprio do que “condescendente_wozniak”! XD

Aqui está o comando completo para criar um contentor, aquele que irá utilizar a partir de agora!

$ docker create --tty --interactive --name="wonderful_mobidock" debian:7

O regresso deste comando deve ser uma cadeia de caracteres lenta (indicando o ID dado ao seu contentor).

docker-start

O nosso contentor é agora criado graças ao comando “docker create”. A propósito, ao fazer um “docker ps -a” deverá encontrá-lo.

Agora que criou o seu contentor e o configurou, pode iniciá-lo com o comando “docker start”.

$ docker start wonderful_mobidock

Por predefinição, “início da doca” não lhe liga a consola, mas pode especificá-la com a opção –attach.

$ docker start --attach wonderful_mobido

Aqui é simples, certo?

Reutilizar um contentor

O nosso contentor é lançado e nomeado. A nossa base de dados vive no nosso contentor, e de uma vez para a outra não queremos perder os nossos dados (o que seria uma vergonha, sejamos francos). O comando “docker stop” permite-lhe fechar limpos um contentor (o uso de “docker kill” deve ser limitado).

Se mais tarde quiser reiniciar este maravilhoso_mobydock e recuperar os seus dados, corra “docker start”!!

Conclusion

Agora é capaz de criar uma imagem e gerir os seus contentores apenas nomeando, criando e parando-os. Nem todos os comandos e opções foram aqui detalhados, mas deverá agora ter as melhores práticas para começar a utilizar o Docker. O manual é seu amigo, e o Docker está a crescer rapidamente, por isso fique atento!

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *