Docker: Tutorial mão na massa – Parte II/III

docker

Houve centenas de notícias sobre Docker nos últimos meses. É fato que estamos prestes a ver uma grande mudança na maneira de pensar sobre a virtualização.

Já pensou na possibilidade de não ser obrigado a usar softwares tradicionais de virtualização para obter isolamento e controle de recursos?

Provavelmente ainda teremos por muito tempo ambos os sistemas em funcionamento, mas já imaginou uma migração para containers?

O Docker é uma tecnologia disruptiva. Tem o potencial para transformar a indústria de virtualização de cabeça para baixo. Todos os cloud providers percebem como a utilização dos recursos fica melhor, gerando maior desempenho uma vez que não se faz necessário um hypervisor. As empresas privadas não precisariam mais pagar por um hypervisor caro.

O Docker é mais do que mais um software. É um padrão de container, que pode ser usado em todas as distribuições Linux. É interessante ter essa idéia e pensar sobre como estará a indústria de virtualização daqui a 5 anos e exatamente por isso, é bom que ficar do olho no Docker cada vez mais. Acredito que quem dominar bem a ferramenta hoje, daqui a 5 anos estará muito bem no mercado.

O Docker nasceu em uma empresa de hospedagem chamada dotCloud. Basicamente, a dotCloud usava containers internamente para executar códigos de clientes, e com o tempo, eles construíram uma monte de ferramentas úteis capazes de gerenciar muitos containers. Em 2013, dotCloud percebeu que suas ferramentas poderiam ser úteis para outras pessoas e então lançaram como opensource, chamando de Docker. Desde então, o projeto tornou vida própria, e tem crescido exponencialmente, além de diversas parcerias com grandes empresas como Google, RedHat, Rackspace e Canonical.

Neste post (http://www.ricardomartins.com.br/docker-um-engine-linux-container/) fiz uma introdução sobre o Docker. O docker é um projeto opensource que torna a criação e gerenciamento de containers Linux muito fácil.

De grosso modo, containers podem ser comparados com pequenas VMs. E eles permitem códigos e aplicações rodarem isoladamente de outros containers de forma muito rápida, compartilhando os mesmos recursos de hardware de forma segura e sem um hypervisor.

Comparação entre virtualização tradicional e containers:

difference

A base do sistema que envolve o hardware e o sistema operacional é a mesma. O que muda é que no caso de um container, eles fazem uso de funcionalidades do kernel chamadas namespaces, cgroups e chroots que permitem a criação de pequenas áreas operacionais, que podem ser comparadas às máquinas virtuais, porém sem o hypervisor.

A parte mais legal dos containers é que eles não precisam de um sistema operacional completo rodando, mas apenas do que você estiver executando e suas dependências relacionadas.

Desta forma, podemos resumir containers como um método de isolamento de ambientes através de namespaces e controle de recursos via cgroups, da mesma forma que na virtualização tradicional, diferenciando-se pela inexistência de um hypervisor e um sistema operacional.

Vamos lembrar apenas que o conceito de linux containers não é algo novo. Ele já existe há pelo menos 30 anos,e é muito similar aos que já é feito nas jails do FreeBSD, containers do Solaris e outras formas de virtualização à nível de sistema operacional como OpenVZ e Linux VServer. Por definição, como utiliza as funcionalidades do kernel do Linux, não preciso dizer que só funciona em Linux 😀

Então vamos lá. Recapitulando…

Uma vez que você tem um daemon do docker rodando em sua máquina, ele aceita comandos de um cliente docker. O cliente docker pode ser um utilitário de linha de comando ou uma chamada de API. Em seguinda, o daemon do docker conversa com o kernel do linux através de uma biblioteca chamada libcontainer, integrante do projeto do Docker.

Então o cliente do docker faz uma chamada ao Docker server para criar um container usando uma imagem específica. O servidor do docker, através da libcontainer como proxy, trabalha em conjunto com o kernel do linux para criar o container, usando esta imagem.

O container é construído usando namepspaces, cgroups, chroot entre outras funcionalidades do kernel para construir uma área isolada para sua aplicação. E você deve estar se perguntando: “- De onde vêm a aplicação e as suas bibliotecas?”. Elas vem do Registro (Registry – https://registry.hub.docker.com/). O registro é um repositório provido pelo Docker. Ele está na nuvem, e disponibiliza uma área para envio, download e compartilhamento de imagens (snapshots) de containers.

E como inserir uma imagem dentro de um container?

De forma geral e resumida, funciona assim: O cliente informa ao servidor qual imagem deseja usar, e pede para que seja definido no container. Em seguida o servidor vai até o registro a faz o download da imagem do container caso não possua no cache local. Em seguida, pega a imagem e aplica no container.

Instalando

Neste teste, estou rodando a partir de um CentOS 7, 64 bits. Então você verá algumas diferenças por ele usar o SystemD, ao invés do tradicional SysVInit. Aproveitando, aqui tem uma tabela comparativa de comandos e aqui também tem um artigo interessante à respeito desse assunto.

[root@localhost ~]# yum install docker docker-registry

Iniciando o docker, e garantindo a inicialização dele no boot

Habilitando no boot:

[root@localhost ~]# systemctl enable docker.service

ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service'

Iniciando o docker:

[root@localhost ~]# systemctl start docker.service

Verificando o status:

[root@localhost ~]# systemctl status docker.service

docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Tue 2014-09-09 13:55:47 BRT; 5s ago
Docs: http://docs.docker.io
Main PID: 2367 (docker)
CGroup: /system.slice/docker.service
??2367 /usr/bin/docker -d --selinux-enabled

Sep 09 13:55:46 localhost.localdomain docker[2367]: [0ab6a91d.init_networkdriver()] creating new bridge for...ker0
Sep 09 13:55:46 localhost.localdomain docker[2367]: [0ab6a91d.init_networkdriver()] getting iface addr
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d] -job init_networkdriver() = OK (0)
Sep 09 13:55:47 localhost.localdomain docker[2367]: Loading containers: : done.
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d.initserver()] Creating pidfile
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d.initserver()] Setting up signal traps
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d] -job initserver() = OK (0)
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d] +job acceptconnections()
Sep 09 13:55:47 localhost.localdomain docker[2367]: [0ab6a91d] -job acceptconnections() = OK (0)
Sep 09 13:55:47 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
Hint: Some lines were ellipsized, use -l to show in full.

Depois de instalado, podemos começar a brincadeira com o Docker. Primeiro vamos rodar o comando sem argumentos, apenas para ver as opções disponíveis:

[root@localhost ~]# docker

Usage: docker [OPTIONS] COMMAND [arg...]
-H=[unix:///var/run/docker.sock]: tcp://host:port to bind/connect to or unix://path/to/socket to use

A self-sufficient runtime for linux containers.

Commands:
attach Attach to a running container
build Build a container from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders from the containers filesystem to the host path
diff Inspect changes on a container'
s filesystem
events Get real time events from the server
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 Login to the docker registry server
logs Fetch the logs of a container
port Lookup the public-facing port which is NAT-ed to PRIVATE_PORT
ps List containers
pull Pull an image or a repository from the docker registry server
push Push an image or a repository to the 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 in the docker index
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
version Show the docker version information
wait Block until a container stops, then print its exit code

Estes comandos permitem gerenciar todo o ciclo de vida de um container, coisas como criar, compartilhar, iniciar, inspecionar, parar, matar e remover containers.

Vamos ver a versão instalada:

[root@localhost ~]# docker version

Client version: 0.11.1-dev
Client API version: 1.12
Go version (client): go1.2
Git commit (client): 02d20af/0.11.1
Server version: 0.11.1-dev
Server API version: 1.12
Go version (server): go1.2
Git commit (server): 02d20af/0.11.1

Vamos trabalhar como no exemplo explicado lá em cima, onde dizemos ao docker para acionar o Registro, fazer o download de um container ubuntu, e rodar o shell dentro do container.

Damos o comando de run, -t para chamar um tty e o -i para permitir nossa interação com o container, pois por padrão, ele iria rodar em background. Em seguida, precisamos informar um nome para a imagem do container que queremos rodar (no caso, ubuntu:12.04) e finalmente o comando que queremos executar no container. (/bin/bash).

[root@localhost ~]# docker run -t -i ubuntu:12.04 /bin/bash

Unable to find image 'ubuntu:12.04' locally
Pulling repository ubuntu
c17f3f519388: Download complete
511136ea3c5a: Download complete
077c3931a6e9: Download complete
e6d0d23ca3e9: Download complete
4e6621283e98: Download complete
f51528fc5eae: Download complete
2124c4204a05: Download complete
root@28ad8f0dd83f:/#

Após dar o enter, o Docker procurou por imagem do Ubuntu 12.04 no cache local. Como não tinha, fez download no Registro.

Note que o prompt mudou para:

root@28ad8f0dd83f:/#

Onde 28ad8f0dd83f, é o ID do container. Sendo assim, significa que estamos dentro do container rodando Ubuntu. Vamos rodar o ps para ver o que temos em execução:

root@28ad8f0dd83f:/# ps

PID TTY TIME CMD
1 ? 00:00:00 bash
8 ? 00:00:00 ps

Note que não existem outros processos do sistema operacional rodando. Você só tem dois processos, o bash e o ps.

Para sair, não use exit. Use ctrl+p+q. O exit sai do container colocando ele em stop.

Voltando ao console do CentOS, rode o comando docker ps:

[root@localhost ~]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28ad8f0dd83f ubuntu:12.04 /bin/bash 17 minutes ago Up 4 minutes cocky_kirch5

Conseguimos ver o id do nosso container e o que está em execução nele. Como temos apenas um rodando o bash, é o que vemos acima.

Agora vamos voltar para o nosso container. Basta rodar o comando docker attach <ID do Container>

[root@localhost ~]# docker attach 28ad8f0dd83f

root@28ad8f0dd83f:/#

Se você ainda tem dúvidas, vamos dar um ls no /:

root@28ad8f0dd83f:/# ls /

bin boot dev etc home lib lib64 media mnt opt proc root run sbin selinux srv sys tmp usr var

Para os que ainda não acreditam, um cat no /etc/issue.net:

root@28ad8f0dd83f:/# cat /etc/issue.net

Ubuntu 12.04.5 LTS

Uma outra coisa interessante é que o docker faz um tracking de tudo que fazemos em nosso container, muito similar à sistemas de controle de versões. Então você pode passar o ID e ver todas as alterações feitas.

Por exemplo:

[root@localhost ~]# docker diff 28ad8f0dd83f

A /.bash_history

Ou seja, como só rodamos alguns comandos no shell, apenas o que alteramos foi o conteúdo do history, salvo no /root/.bash_history.

Agora vamos fazer o seguinte. Vamos criar um container instalar algumas coisas nele e salvá-lo como nossa imagem base:

Voltado para o container:

[root@localhost ~]# docker attach 28ad8f0dd83f
root@28ad8f0dd83f:/# apt-get update

root@28ad8f0dd83f:/# apt-get install -y vim curl wget multitail

Depois de finalizado, saia (ctrl+p+q) e rode o comando docker ps -a para pegar o ID do seu container (caso já não tenha tomado nota). Agora rode outro diff (docker diff <ID>). Verifique a quantidade de coisas adicionadas (A) e alteradas (C). Bacana né?!

Agora vamos salvar esta versão para ser nossa imagem base de modo a usarmos ela mais tarde. Nós vamos fazer commit das mudanças, dar um nome e uma tag para elas. Execute:

docker commit <ID> <Nome>:<Tag>

[root@localhost ~]# docker commit 28ad8f0dd83f ricardo/teste:0.1

eacfb1e33a194803c5c2be11f8bd159424bd4b938123f9f70530d14676d6382b

Agora Vamos ver as imagens disponíveis:

[root@localhost ~]# docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ricardo/teste 0.1 eacfb1e33a19 40 seconds ago 192.4 MB
ubuntu latest 826544226fdc 5 days ago 194.2 MB
ubuntu 12.04 c17f3f519388 5 days ago 106.2 MB

Todas as que você já tenha usado aparecerão aqui. Mas o legal é que também temos nossa própria imagem agora.

Construindo um servidor com o Dockerfile

Vamos criar nosso servidor web com o Dockerfile agora. O docker file disponibiliza uma série de instruções para o docker rodar no container. Isso nos permite automatizar a instalação de coisas.

Crie um novo diretório e entre nele. Como vamos instalar o Nginx, vou criar um arquivo de conrfiguração que vamos usar nele.

[root@localhost ~]# mkdir nginx; cd nginx

[root@localhost nginx]# pwd

/root/nginx

Agora vamos criar um arquivo chamado Dockerfile. Nele vamos inserir o conteúdo abaixo alterando a seção FROM pelo nome dado à sua imagem:

[root@localhost ~]# vim /root/nginx/Dockerfile

FROM ricardo/teste:0.1
# Install Nginx.
RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/* && echo "daemon off;" >> /etc/nginx/nginx.conf

# Define working directory.
WORKDIR /etc/nginx

# Define default command.
CMD ["nginx"]

# Expose ports.
EXPOSE 80

O que estamos fazendo?

  • FROM: Informa ao Docker qual imagem (e tag neste caso) será usada como base;
  • RUN: Irá executar o comando informado (como root) , usando sh -c “comando”;
  • EXPOSE: Irá expor a porta para a máquina host. Você pode expor múltiplas portas, como por exemplo EXPOSE 80 443 8080
  • CMD: Irá executar o comando (sem utilizar sh -c). Geralmente este é o passo mais demorado. No nosso caso, iremos apenas iniciar o Nginx.
    Em produção, geralmente é recomendável algo monitorando o processo do nginx para o caso de falhas. Você pode usar o monit para isso.

Uma vez salvo, podemos gerar o nova imagem à partir do Dockerfile:

[root@localhost ~]# docker build -t nginx-exemplo .

Se funcionar, você verá: Successfully built fc9d3f802962 (O ID do seu container será diferente).

Vamos ver o que temos agora:

[root@localhost nginx]# docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
nginx-exemplo latest fc9d3f802962 29 seconds ago 205.4 MB
ricardo/teste 0.1 eacfb1e33a19 47 minutes ago 192.4 MB
ubuntu latest 826544226fdc 5 days ago 194.2 MB
ubuntu 12.04 c17f3f519388 5 days ago 106.2 MB

Finalmente, vamos executar o webserver:

Use o comando docker run -p 80:80 -d nginx-exemplo (Assumindo que você tenha dado este mesmo nome quando criamos)

O -p 80:80 faz o bind entre a porta 80 do container e das máquinas que forem acessá-lo. Então se fizermos um curl localhost ou formos ao endereço IP do servidor no browser, iremos ver o resultado do processamento das requests do Nginx na porta 80 do container.

[root@localhost nginx]# docker run -p 80:80 -d nginx-exemplo

102326cfb0e85a50b1d358c4a92ad4770d00d8b1383a0d113dfcb88a6ea68a86

Explicando:

  • docker run – Executa o container;
  • -p 80:80 – Fazer o bind entre a porta 80 do host e do container;
  • -d nginx-exemplo – Rodar nossa imagem nginx-exemplo, onde temos o “CMD” para rodar o nginx.
[root@localhost nginx]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
102326cfb0e8 nginx-exemplo:latest nginx 30 seconds ago Up 29 seconds 0.0.0.0:80-&gt;80/tcp hungry_feynman1
28ad8f0dd83f ubuntu:12.04 /bin/bash 3 hours ago Up About an hour cocky_kirch5

Como podemos ver, temos dois containers em execução. O que criamos inicialmente e o que acabamos de criar à partir da nossa imagem customizada com nginx. Vamos verificar se o Nginx está funcionando?

[root@localhost nginx]# curl localhost

<center></center>
<h1>Welcome to nginx</h1>

Beleza! Temos o Nginx funcionando corretamente!

Agora vamos customizar o conteúdo exibido? Primeiro, vamos criar um arquivo chamado default dentro do nosso diretório onde estamos trabalhando (/root/nginx) e adicionar o seguinte conteúdo:

[root@localhost nginx]# vim /root/nginx/default
server {

root /var/www;
index index.html index.htm;
server_name localhost;

location / {
try_files $uri $uri/ /index.html;
}
}

Em seguida vamos criar um arquivo index.html com conteúdo customizado para ser exibido:

[root@localhost nginx]# vim /root/nginx/index.html

<center></center>
<h1>Docker | Nginx!</h1>
&nbsp;

<center></center>
<h1>http://ricardomartins.com.br</h1>

Vamos fazer uma modificação no nosso Docker file, adicionando o comando add, deixando ele assim:

[root@localhost nginx]# vim /root/nginx/Dockerfile
FROM ricardo/teste:0.1
# Install Nginx.
RUN
apt-get update &&
apt-get install -y nginx &&
rm -rf /var/lib/apt/lists/* &&
echo "daemon off;" >> /etc/nginx/nginx.conf

# Define working directory.
WORKDIR /etc/nginx

# Define default command.
CMD ["nginx"]

# Add custom content
ADD default /etc/nginx/sites-available/default
ADD index.html /var/www/

# Expose ports.
EXPOSE 80

O que faz o add:

  • ADD: Irá copiar os arquivos da máquina host para o container nos locais especificados. No caso, o arquivo default contendo nossa configuração do Nginx para /etc/nginx/sites-available e o index.html para o /var/www.

Agora vamos gerar uma nova imagem com nosso conteúdo customizado no Nginx:

[root@localhost nginx]# $ docker build -t nginx-exemplo-custom .

Uploading context 4.608 kB
Uploading context
Step 0 : FROM ricardo/teste:0.1
---> eacfb1e33a19
Step 1 : RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/* && echo "daemon off;" >> /etc/nginx/nginx.conf
---> Using cache
---> f11f100bab8f
Step 2 : WORKDIR /etc/nginx
---> Using cache
---> 9af9478528d0
Step 3 : CMD ["nginx"]
---> Using cache
---> df3975d470d3
Step 4 : ADD default /etc/nginx/sites-available/default
---> Using cache
---> 4681201a599d
Step 5 : ADD index.html /var/www/
---> Using cache
---> 21fc710d7cc8
Step 6 : EXPOSE 80
---> Using cache
--->; 8c9b0d33f68a
Successfully built 8c9b0d33f68a

Agora vamos iniciar nosso novo container. Primeiro você precisa dar um stop no container iniciado antes, caso contrário irá dar um erro informando que a porta 80 já está em uso. (Ou se preferir, rode o novo container em outra porta). Para dar stop, rode o comando:

[root@localhost nginx]# docker stop

Iniciando o novo container:

[root@localhost nginx]# docker run -p 80:80 -d nginx-exemplo-custom

84e770995a853cdd913195c6498e72ee8e8a3f0ad4196046fdae6c571a99d5ec

Agora rodamos novamente o curl:

[root@localhost nginx]# curl localhost

<center></center>
<h1>Docker | Nginx!</h1>


<center></center>
<h1>http://ricardomartins.com.br</h1>

… ou melhor ainda, aponte seu browser para o endereço IP do servidor:

screen-nginx

Note que o endereço IP é o endereço do meu servidor de teste com CentOS instalado. Você poderia ter seu container com a própria configuração de rede, mas isto fica para um próximo post 😀

Ahh, já ia esquecendo. Você pode rodar comandos dentro do seu container. Por exemplo, vamos conferir o nosso arquivo index.html dentro do container:

[root@localhost nginx]# docker run -t -i nginx-exemplo-custom cat /var/www/index.html

<center></center>
<h1>Docker | Nginx!</h1>
<center></center>
<h1>http://ricardomartins.com.br</h1>

Note que não subimos um novo container, é o mesmo que está em execução:

[root@localhost nginx]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb41e8f2b62b nginx-exemplo-custom:latest nginx 10 minutes ago Up 10 minutes 0.0.0.0:80&gt;80/tcp trusting_ptolemy9

Dicas úteis

Para remover um container: docker rm ContainerID
Para remover todos os containers: docker rm $(docker ps -a -q)
Para remover imagens: docker rmi ContainerID
Para remover todas as imagens: docker rmi $(docker ps -a -q)

Finalizando

Eu não conheço muito o docker e estou dando meus primeiro passos com ele. Mas o fato é que ele é o grande boom hoje, então se quiser se destacar no mercado, não espere uma tecnologia ficar totalmente madura para começar a olhar.

Aumente seu conhecimento sobre ela junto com o crescimento dela. Desta forma você estará mais preparado e qualificado quando ela estiver pronta.

Assim que tiver novas descobertas (e tempo para postar), coloco por aqui.

Referências:

http://blog.docker.com/2013/08/containers-docker-how-secure-are-they/
http://dockerfile.github.io/#/nginx
https://coreos.com/using-coreos/docker/
https://github.com/wsargent/docker-cheat-sheet/
http://www.allthingsdistributed.com/2014/04/docker-in-elastic-beanstalk.html
http://pt.slideshare.net/dotCloud/docker-intro-november/
http://www.ricardomartins.com.br/docker-um-engine-linux-container/
https://www.docker.com/tryit/
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-getting-started

  • Ficou muito bom o post, Ricardo. Recentemente escrevi um post bem mao na massa de docker tb, separando minha aplicação rails do banco de dados em containers. http://goo.gl/aqPiiE

  • Parabéns pelo Post, ficou muito bom, eliminou varias das minhas dúvidas.

  • Grande Ricardo, parabéns pelo post sobre o Docker e acredito no sucesso do mesmo, mas será que existe algum frontend para administração do mesmo? Não tenho problemas ou medo do terminal mas para o dia a dia um frontend para administração pode fazer falta. Você conhece ou sabe se existe algum para o Docker??

    Abração

  • Ricardo, parabéns pelo post e pelo blog.
    me ajudou muito, espero novos post sobre docker hem!!!

    Abração

  • jhonathas

    Vi na documentação do Dockerfile, um método chamado ONBUILD, para que serve? Tentei entender mas não consegui.

  • Ricardo Martins

    Olá Jhonathas,

    Também não conheço. Já chegou a dar uma lida aqui: http://www.tech-d.net/2014/02/06/docker-quicktip-3-onbuild/ ?

  • Eduardo Henrik

    Ricardo, parabéns pelo blog!

    Post ficou muito claro, gostei bastante também.

    Uma dúvida, você pela sua experiência, acredita que o docker já tenha maturidade para rodar aplicações em produção? Levando em consideração que algumas empresas já utilizam (Spotify, twitter, Playstation..) porém para ambientes menores e aplicações mais modestas. 🙂

    Valeu!

    • Ricardo Martins

      Olá Eduardo,

      Tenho visto gente utilizando em Produção em ambientes rodando microserviços. Ambientes com coisas mais robustas, ainda não ví usando em produção.

      • Eduardo Henrik

        Ok, muito obrigado pelo retorno.

        Estou rodando alguns containers em ambiente de homologação, utilizando tomcat e nginx, o resultado é satisfatório por enquanto.

  • Carlos Bittarello

    Olá Ricardo Parabéns! Estou precisando dessa parte “Você poderia ter seu container com a própria configuração de rede, mas isto fica para um próximo post “, tens algum material que pode ajudar, pois não estou conseguindo resolver isso;

    • Ricardo Martins

      Oi Carlos, obrigado. Desculpe, mas ainda não consegui preparar um post sobre a parte de nerworking.

      Estou fazendo alguns laboratórios ainda, e deve sair em breve.

  • ggarnier

    Parabéns pelo post! É uma excelente introdução ao Docker, muito bem explicado.

    • Ricardo Martins

      Valeu Guilherme, muito obrigado!

  • Fábio Silva

    Show de bola

  • Fábio Silva

    Massa! Show!

  • jociel

    Parabéns pelo trabalho. Gostaria de saber como faço para configurar um IP fixo em um container do Docker. Desde já Obrigado.

  • Ricardo Drumond

    Oi, tenho que colocar a imagem do IoT DevKit https://software.intel.com/sites/landingpage/iotdk/board-boot-image.html no container no Docker e instalar o nodejs. Eu entendi sua tutorial pra fazer com o ubuntu, mas não consegui fazer pra yocto. Pode me ajudar? Desde já grato.

  • Pingback: Primeiros passos com Docker – Aécio Pires()

  • Marcos

    Ricardo Martins Boa tarde

    Sou O marcos estou com um erro no DOCKER esta novidade caiu no meu colo, estou precisando um ajuda neste erro, não sei o que é vou postar o erro e se puder ver e me dizer qual passo devo tomar agradeço muito.

    docker: Error response from daemon: devmapper: Thin Pool has 1530 free data blocks which is less than minimum required 1534 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior.
    See ‘/usr/bin/docker-current run –help’

  • Marcos

    Ricardo Martins Boa tarde

    Sou O marcos estou com um erro no DOCKER esta novidade caiu no meu colo, estou precisando um ajuda neste erro, não sei o que é vou postar o erro e se puder ver e me dizer qual passo devo tomar agradeço muito.

    docker: Error response from daemon: devmapper: Thin Pool has 1530 free data blocks which is less than minimum required 1534 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior.
    See ‘/usr/bin/docker-current run –help’

  • Alan Santos

    Olá Ricardo,

    Gostei muito da introdução ao assunto. Bem explicado e com detalhes técnicos bem importantes. Está muito intuitivo, o que é ótimo. Segui o artigo a risca e incrementei fazendo algumas experiências, foi muito proveitoso.

    Obrigado e parabéns pelo excelente trabalho!

  • juliano

    boa tarde, Ricardo, muito bom o tutorial, poderia dar um exemplo de docker com jenkins e deploy continuo?

  • juliano

    Está de parabens Ricardo.

  • Parabéns pelo trabalho!

    Apenas um detalhe, na parte do código abaixo de “Vamos fazer uma modificação no nosso Docker file, adicionando o comando add, deixando ele assim”

    RUN
    apt-get update &&
    apt-get install -y nginx &&
    rm -rf /var/lib/apt/lists/* &&
    echo “daemon off;” >> /etc/nginx/nginx.conf

    Essas quebras de linhas geram um problema ao executar o build do docker.

    —> Running in 75cbb13c8aee
    /bin/sh: 0: -c requires an argument
    The command ‘/bin/sh -c’ returned a non-zero code: 2

    Pesquisei o problema e vi algumas sugestões para atualizar a versão do docker, mas estou com a ultima versão: Docker version 1.9.1

    A solução foi deixar na mesma linha a execução como no exemplo

    RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/* && echo “daemon off;” >> /etc/nginx/nginx.conf

    • ggarnier

      A versão mais recente do Docker é 1.12.3. Talvez o problema seja que o `apt-get update` deveria estar na mesma linha do `RUN`. O restante pode ficar nas linhas seguintes:

      “`
      RUN apt-get update &&
      apt-get install -y nginx &&
      rm -rf /var/lib/apt/lists/* &&
      echo “daemon off;” >> /etc/nginx/nginx.conf
      “`

      • Ricardo Martins

        Obrigado @ggarnier… Exatamente isto.

  • Icaro José Bilinski

    docker é uma copia muito mau feita do jails do freebsd, bem como tudo que o linux tenta copiar!

  • C C

    Muito bom! Muito bom! Me ajudou a destravar!

  • Pingback: Primeiros passos com Docker – Danilo Pinotti()

  • Vladimir Costa de Alencar

    Muito bom o tutorial.

  • Luiz Dias

    Fala camarada!
    Sei que é um pouco antigo o post, mas tem como eu usar um docker somente na minha rede local (Server) eu disponibilizar as imagens que eu criar para os meus programadores, sem precisar ir na internet baixar nada e usar o server que eu criar??