O Docker é uma ferramenta muito completa e com diversos recursos para criar e monitorar o funcionamento dos containers. Abaixo veremos algumas opções úteis que irão nos auxiliar na criação e manutenção dos nossos containers.
Existem algumas configurações de rede que podemos fazer nos nossos containers, listamos abaixo alguns exemplos:
Por padrão o nome do host é o container id, podemos mudar utilizando o parâmetro −−hostname
que irá definir um nome para este container:
# docker run -ti --hostname srv-web debian
root@srv-web:/# hostname
srv-web
Se quisermos definir um dns específico para nosso container, podemos utilizar o parâmetro −−dns:
# docker run -ti --dns 8.8.8.4 debian
root@9d1251fdf034:/# cat /etc/resolv.conf
nameserver 8.8.8.4
Podemos definir um MAC Address específico para a interface de rede do container utilizando o parâmetro --mac-address
:
# docker run -ti --mac-address 12:aa:11:bb:10:cc debian
root@25daa64f4d54:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 12:aa:11:bb:10:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
Definimos que um container terá acesso a uma porta através da opção --expose
:
# docker run -ti --expose 80 --name webapp debian
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ad90e528ebc debian "bash" 10 seconds ago Up 9 seconds 80/tcp webapp
Para acessar um serviço de um container utilizando o IP do host hospedeiro, utilizamos o parâmetro −−publish
, que criará uma regra pelo Iptables direcionando as portas:
# docker run -d --publish 8080:80 --name www httpd
ou
# docker run -d -p 8080:80 --name www httpd
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dda212e8b5af httpd "httpd-foreground" 3 seconds ago Up 1 second 0.0.0.0:8080->80/tcp www
Agora iremos acessar o container para pegar o endereço dele para testarmos o redirecionamento.
# docker exec -ti dda212e8b5af /bin/bash
root@dda212e8b5af:/usr/local/apache2# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:03 txqueuelen 0 (Ethernet)
RX packets 3001 bytes 8866111 (8.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2348 bytes 169737 (165.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Agora vamos executar o comando curl
diretamente do nosso host.
# curl 172.17.0.3 8080
<html><body><h1>It works!</h1></body></html>
Pronto funcionou o redirecionamento! 😄
Podemos verificar através do iptables que o docker adicionou uma regra de direcionamento:
# sudo iptables -nL DOCKER -t nat
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.3:80
Para que um container reconheça outro, utilizamos o parâmetro --link
, basicamente ele acrescenta o container desejado no arquivo /etc/hosts:
# docker run -ti --link www debian
root@f9dc1977bd65:/# ping www
PING www (172.17.0.3) 56(84) bytes of data.
64 bytes from www (172.17.0.3): icmp_seq=1 ttl=64 time=0.171 ms
64 bytes from www (172.17.0.3): icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from www (172.17.0.3): icmp_seq=3 ttl=64 time=0.098 ms
^C
--- www ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 8ms
rtt min/avg/max/mdev = 0.089/0.119/0.171/0.037 ms
root@f9dc1977bd65:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 www dda212e8b5af
172.17.0.4 f9dc1977bd65
Desta forma o ip do container será o mesmo do host hospedeiro com o parâmetro --net=host
. Basicamente seria como se o container estivesse simulando o host hospedeiro. Não é o ideal usar essa opção:
# docker run -ti --net=host debian
Existem diversos comandos do docker que nos auxiliam a gerenciar os recursos e analisar nossos containers, abaixo seguem alguns exemplos:
O comando docker info
, traz diversas informações sobre o Docker, versão, imagens, quantos containers foram criados, quantos estão em execução, pausados, etc:
# docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.5.0-docker)
Server:
Containers: 5
Running: 3
Paused: 0
Stopped: 2
Images: 7
Server Version: 20.10.1
Storage Driver: overlay2
(...)
O comando docker logs
exibe todas as ações realizadas dentro do container:
# docker logs webapp
root@f9dc1977bd65:/# ping www
PING www (172.17.0.3) 56(84) bytes of data.
64 bytes from www (172.17.0.3): icmp_seq=1 ttl=64 time=0.171 ms
64 bytes from www (172.17.0.3): icmp_seq=2 ttl=64 time=0.089 ms
64 bytes from www (172.17.0.3): icmp_seq=3 ttl=64 time=0.098 ms
^C
--- www ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 8ms
rtt min/avg/max/mdev = 0.089/0.119/0.171/0.037 ms
root@f9dc1977bd65:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 www dda212e8b5af
172.17.0.4 f9dc1977bd65
root@f9dc1977bd65:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 115G 69G 41G 63% /
tmpfs 64M 0 64M 0% /dev
tmpfs 7.7G 0 7.7G 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/sdb5 115G 69G 41G 63% /etc/hosts
tmpfs 7.7G 0 7.7G 0% /proc/asound
tmpfs 7.7G 0 7.7G 0% /proc/acpi
tmpfs 7.7G 0 7.7G 0% /proc/scsi
tmpfs 7.7G 0 7.7G 0% /sys/firmware
Se você estiver trabalhando com um container que direciona os logs para saída padrão e quer analisar a saída desses logs, você pode utilizar o parâmetro -f, assim ele será atualizado de acordo com os novos registros:
# docker logs -f www
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this message
[Sun Jan 03 20:05:30.537687 2021] [mpm_event:notice] [pid 1:tid 140355815597184] AH00489: Apache/2.4.46 (Unix) configured -- resuming normal operations
[Sun Jan 03 20:05:30.540778 2021] [core:notice] [pid 1:tid 140355815597184] AH00094: Command line: 'httpd -D FOREGROUND'
172.17.0.1 - - [03/Jan/2021:20:08:25 +0000] "GET / HTTP/1.1" 200 45
O comando docker top
exibe no console, informações dos processos executando no container. Precisamos passar como parâmetro o <nome>
ou :
# docker top www
UID PID PPID C STIME TTY TIME CMD
root 15793 15773 0 17:05 ? 00:00:00 httpd -DFOREGROUND
daemon 15842 15793 0 17:05 ? 00:00:00 httpd -DFOREGROUND
daemon 15843 15793 0 17:05 ? 00:00:00 httpd -DFOREGROUND
daemon 15844 15793 0 17:05 ? 00:00:00 httpd -DFOREGROUND
O comando docker inspect
, lista diversas informações de um container, desde aspectos da sua criação (data, imagem base, autor…), como características (rede, volumes, etc.). É um comando bem completo, que pode ser utilizado em conjunto com o grep para facilitar a pesquisa:
# docker inspect www
[
{
"Id": "dda212e8b5afc20d8b3576906b0d88a9f2e5151c4ecfba23f46124a66a41e855",
"Created": "2021-01-03T20:05:29.923508826Z",
"Path": "httpd-foreground",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 15793,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-01-03T20:05:30.450089691Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:dd85cdbb99877b73f0de2053f225af590ab188d79469eebdb23ec2d26d0d10e8",
(...)
# docker inspect www | grep -i IPAddress
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.3",
"IPAddress": "172.17.0.3",
Também podemos formatar a saída do comando docker, usando o parâmetro -f
, passando algumas strings:
Exibe o IP do container:
# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' centos
172.17.0.3
Exibe o MAC Address do container:
# docker inspect -f '{{range .NetworkSettings.Networks}}{{.MacAddress}}{{end}}' centos
02:42:ac:11:00:03
Exibe os volumes do container:
# docker inspect -f {{.Mounts}} centos
[{bind /volumes/data /data true rprivate}]
Por padrão, quando a memória não é limitada, o container utilizará até o limite de memória do host hospedeiro. O ideal é limitar de acordo com a utilização, evitando que um container interfira no funcionamento do outro. Utilizamos o parâmetro -m
seguindo do tamanho que desejamos:
# docker run -ti -m 512M −−name webs debian
# docker inspect webs | grep -i mem
"Memory": 536870912,
"CpusetMems": "",
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 1073741824,
"MemorySwappiness": null,
Para alterar o valor de um container que está em execução, utilizamos o comando docker update
, com o parâmetro -m
:
# docker update -m 256M webs
webs
# docker inspect webs | grep -i mem
"Memory": 268435456,
"CpusetMems": "",
"KernelMemory": 0,
"KernelMemoryTCP": 0,
"MemoryReservation": 0,
"MemorySwap": 1073741824,
"MemorySwappiness": null,
Por padrão, quando a cpu não é limitada, o container utilizará até o limite de cpu do host hospedeiro. Usamos proporção de uso de cpu para especificar quanto cada container poderá usar.
Caso não seja limitado o uso, o desempenho de um container pode afetar os demais. Utilizamos o parâmetro --cpu-shares
seguindo de um valor proporcional, vamos criar 3 containers como exemplo:
# docker run -ti --cpu-shares 2048 --name container1 ubuntu
# docker run -ti --cpu-shares 1024 --name container2 ubuntu
# docker run -ti --cpu-shares 1024 --name container3 ubuntu
# docker inspect container1 container2 container3 | grep CpuShares
"CpuShares": 2048,
"CpuShares": 1024,
"CpuShares": 1024,
No exemplo acima, container1 poderá usar 50% de recursos de cpu do host hospedeiro, enquanto que o container2 e container3 poderão usar 25% cada.
Para alterar recursos de cpu de containers em execução, utilizamos o comando docker update
. Para igualar uso de cpu (33%) dos 3 containers, vamos alterar o valor do conatiner1, deixando igual aos demais:
# docker update --cpu-shares 1024 container1
# docker inspect container1 container2 container3 | grep CpuShares
"CpuShares": 1024,
"CpuShares": 1024,
"CpuShares": 1024,
O comando docker stats
faz o acompanhamento em tempo real de todos os containers. Ele exibe as seguintes informações:
CONTAINER ID: Identificação do container no docker.
CPU %: Percentual de uso de CPU.
MEM USAGE / LIMIT: Quantidade de memória usada/limite.
MEM %: Percentual de memória usada.
NET I/O: Quantidade de uso de rede.
BLOCK I/O: Quantidade de escrita/leitura de blocos no disco.
PIDS: Quantidade de processos executando.
# docker stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
0ce1b1923a38 container3 0.00% 2.223MiB / 15.33GiB 0.01% 7.26kB / 0B 0B / 0B 1
75ee571056c9 container2 0.00% 1.777MiB / 15.33GiB 0.01% 8.61kB / 0B 0B / 0B 1
4dcfe1743e08 container1 0.00% 4.934MiB / 15.33GiB 0.03% 9.95kB / 0B 4.24MB / 0B 1
ad6351d55ffc webs 0.00% 1.477MiB / 256MiB 0.58% 13.8kB / 0B 0B / 0B 1
dda212e8b5af www 0.01% 45.04MiB / 15.33GiB 0.29% 8.88MB / 171kB 28.4MB / 9.92MB 82
2ad90e528ebc webapp 0.00% 1.449MiB / 15.33GiB 0.01% 20.5kB / 0B 0B / 0B 1
Podemos verificar um container específico, passando como parâmetro o <nome>
ou <container id>
:
# docker stats www
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
dda212e8b5af www 0.01% 45.04MiB / 15.33GiB 0.29% 8.88MB / 171kB 28.4MB / 9.92MB 82
Um arquivo Dockerfile é um script que contém algumas instruções para facilitar a criação de imagens personalizadas. A utilização desses arquivos automatizam o processo de criação e atualização de suas imagens. Abaixo estão descritos os mais importantes comandos usados nos Dockerfiles:
FROM: Define qual imagem base estamos usando para criarmos nossa imagem personalizada;
MAINTAINER: Definimos quem é o mantenedor da imagem, ela é opcional;
RUN: Permite executar comandos no momento da criação da imagem. O ideal é executar diversos comandos na mesma instrução RUN;
LABEL: Define metadados na nossa imagem, como descrição, versão;
ADD: Adiciona arquivos para dentro da imagem que estamos criando. Ele também envia arquivos tar descompactando-os;
COPY: Copia arquivos e diretórios para dentro da imagem;
CMD: Define o comando que será executado na inicialização de um container, pode ser sobrescrito na criação do mesmo. Também serve como parâmetro para o ENTRYPOINT;
ENTRYPOINT: Permite especificar qual será o principal processo dentro de um container. Por padrão é o bash, ele não pode ser sobrescrito;
ENV: Define variáveis de ambiente para o container. Úteis na configuração de uma ambiente;
EXPOSE: Permite determinar quais portas do container estarão disponível para conexão;
USER: Usuário padrão da imagem, o usuário padrão é o root;
WORKDIR: Define o diretório de trabalho do container;
VOLUME: Faz o mapeamento de um diretório para o container;
Para este exemplo, vamos criar uma pasta com alguns arquivos para adicionar na imagem, no momento do build. Também será instalado o supervisor, para controlar a inicialização de dois serviços diferentes dentro da imagem. Segue os passos:
# mkdir nginx
# cd nginx
# vim default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php index.html index.htm index.nginx-debian.html;
server_name localhost;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
# vim supervisord.conf
[supervisord]
nodaemon=true
[program:php-fpm]
command=/etc/init.d/php7.0-fpm start
autostart=true
autorestart=true
[program:httpd]
command=/etc/init.d/nginx start
autostart=true
autorestart=true
Agora iremos criar nosso arquivo Dockerfile, lembrando que ele deve sempre ser escrito desta forma, com a primeira letra maiúscula:
# vim Dockerfile
FROM ubuntu
MAINTAINER Cesar A. Gaspar - rasec.rapsag@gmail.com
LABEL description="Webserver" version="1.0"
RUN apt update && apt dist-upgrade -y && \
apt install -y nginx php-fpm supervisor && \
apt clean && \
sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/7.0/fpm/php.ini
ADD default /etc/nginx/sites-available/
ADD supervisord.conf /etc/supervisord.conf
VOLUME [ "/var/www/html" ]
EXPOSE 80
CMD ["/usr/bin/supervisord"]
Para criarmos a imagem iremos utilizar o comando docker build
, com o parâmetro -t
, para definirmos um nome e versão. O ponto no final do comando indica que o arquivo Dockerfile está na pasta atual, caso o arquivo Dockerfile esteja em outra pasta, basta passar o caminho até a pasta:
# docker build -t webserver:1.0 .
Após finalizar todo o processo de construção da imagem, ela já estará disponível para criar seus containers:
docker images webserver REPOSITORY TAG IMAGE ID CREATED SIZE webserver 1.0 dd85cdbb9987 26 seconds jan 138MB
Agora para finalizar vamos criar um container usando nossa imagem. Para testar se está funcionando corretamente vamos mapear um volume e adicionar um arquivo php de teste:
# mkdir -pv /volumes/nginx
# docker run -d -p 8000:80 −−name nginx-server -v /volumes/nginx:/var/www/html webserver:1.0
# echo "<?php phpinfo() ?>" > /volumes/nginx/index.php
Podemos acessar pelo browser do host hospedeiro, já que definimos um redirecionamento pela porta 8000:
https://docs.docker.com
https://linuxcontainers.org
https://www.howtoforge.com/tutorial/how-to-use-docker-introduction
https://www.server-world.info/en/note?os=Debian_9&p=docker&f=1
https://www.youtube.com/channel/UCJnKVGmXRXrH49Tvrx5X0Sw
Se una com os assinantes de nossa Newsletter, sempre que tiver postagem nova você será notificado.