Saudações. Instruções de como instalar o Docker (CE – Community Edition) no Linux.
Artigo vivo, sofrerá adições constantes.
Procedimentos prévios recomendados:
- Instalação de programas básicos;
- Data/hora via NTP;
- Ajuste fino no kernel Linux;
- DNS Cache local de alta velocidade;
1 – Instalando Docker
Preparativos para o uso pleno do Docker:
# Manter o Debian atualizado:
apt-get -y update;
apt-get -y upgrade;
apt-get -y dist-upgrade;
apt-get -y full-upgrade;
# Comando curl para download do script:
apt-get -y install curl;
# Pasta de config do Docker:
mkdir -p /etc/docker;
Preparar a configuração com tuning (Docker versão 28 ou superior). Cadastre em “default-address-pools” as faixas principais (prefixo) e o tamanho dos prefixos segmentados.
Arquivo: /etc/docker/daemon.json
{
"iptables": true,
"ip6tables": true,
"ip-masq": true,
"ip-forward": true,
"userland-proxy": false,
"ipv6": true,
"icc": true,
"bridge": "docker0",
"default-address-pools": [
{ "base":"10.0.0.0/8", "size": 26 },
{ "base":"100.64.0.0/10", "size": 25 },
{ "base":"198.18.0.0/15", "size": 25 }
],
"max-concurrent-uploads": 32,
"max-concurrent-downloads": 32
}Para instalar o Docker, execute:
# Baixar script instalador oficial:
curl -fsSL get.docker.com -o /tmp/get-docker.sh;
# Executar script instalador:
sh /tmp/get-docker.sh;
Ferramentas opcionais recomendadas para suporte, depuração e manutenção:
# Instalando ferramentas necessarias:
apt-get -y install curl;
apt-get -y install wget;
apt-get -y install bash;
# Instalando ferramentas recomendadas:
apt-get -y install iproute2;
apt-get -y install net-tools;
apt-get -y install bridge-utils;
apt-get -y install tcpdump;
apt-get -y install strace;
apt-get -y install bash;
apt-get -y install htop;
apt-get -y install psmisc;
apt-get -y install mc;
apt-get -y install iptables;
apt-get -y install nftables;
apt-get -y install conntrack;
apt-get -y install rsync;
apt-get -y install bind9utils;
apt-get -y install dnsutils;
apt-get -y install fping;
2 – Comandos rápidos
O script abaixo cria alguns comandos que agilizam o dia-a-dia na digitação rápida de comandos para manipular container e são opcionais.
# Comando para parar e destruir um container:
(
echo '#!/bin/sh';
echo;
echo 'for x in $@; do';
echo ' echo -n "Stop and delete [$1] ";';
echo ' docker stop $x 2>/dev/null 1>/dev/null;'
echo ' echo -n ".";';
echo ' docker stop $x 2>/dev/null 1>/dev/null;'
echo ' echo -n ".";';
echo ' docker rm -f $x 2>/dev/null 1>/dev/null;'
echo ' echo -n ".";';
echo ' echo "OK";';
echo 'done';
echo;
) > /usr/bin/undocker;
chmod +x /usr/bin/undocker;
# Comando para entrar no shell (/bin/sh ou comando informado) de um container:
(
echo '#!/bin/sh';
echo;
echo 'cmd="$2";';
echo '[ "x$cmd" = "x" ] && cmd="bash"';
echo 'docker exec --user=root -it $1 $cmd;';
echo;
) > /usr/bin/dsh;
chmod +x /usr/bin/dsh;
# Comando para inspecionar container
(
echo '#!/bin/sh';
echo;
echo 'which jq 2>/dev/null 1>/dev/null;';
echo 'jqfound="$?";';
echo 'if [ "$jqfound" = "0" ]; then';
echo ' docker inspect $1 | jq;';
echo 'else';
echo ' docker inspect $1;';
echo 'fi;';
echo;
) > /usr/bin/di;
chmod +x /usr/bin/di;
# Comando para visualizar logs do container
(
echo '#!/bin/sh';
echo;
echo 'docker logs $1;';
echo;
) > /usr/bin/dlog;
chmod +x /usr/bin/dlog;
# Comando para visualizar logs do container em tempo real
(
echo '#!/bin/sh';
echo;
echo 'docker logs -f $1;';
echo;
) > /usr/bin/dtail;
chmod +x /usr/bin/dtail;
# Comando para listar containers em execucao (inclusive parados):
(
echo '#!/bin/sh';
echo;
echo 'EXTRA="";';
echo '[ "x$1" = "x" ] || EXTRA="-f name=$1";';
echo 'echo;';
echo 'docker ps -a $EXTRA;';
echo 'echo;';
echo;
) > /usr/bin/dps;
chmod +x /usr/bin/dps;
# Parar containers por busca no nome
(
echo '#!/bin/sh';
echo;
echo 'FIND="$1";';
echo '[ "x$FIND" = "x" ] && FIND="foobar";';
echo 'echo;';
echo 'docker ps -a | egrep "$FIND";';
echo "didlist=\$(docker ps -a | egrep "\$FIND" | awk '{print \$1}');";
echo 'for did in $didlist; do docker stop $did; done;';
echo 'echo;';
echo;
) > /usr/bin/dstop;
chmod +x /usr/bin/dstop;
# Iniciar containers por busca no nome
(
echo '#!/bin/sh';
echo;
echo 'FIND="$1";';
echo '[ "x$FIND" = "x" ] && FIND="foobar";';
echo 'echo;';
echo 'docker ps -a | egrep "$FIND";';
echo "didlist=\$(docker ps -a | egrep "\$FIND" | awk '{print \$1}');";
echo 'for did in $didlist; do docker start $did; done;';
echo 'echo;';
echo;
) > /usr/bin/dstart;
chmod +x /usr/bin/dstart;
# Deletar containers por busca no nome
(
echo '#!/bin/sh';
echo;
echo 'FIND="$1";';
echo '[ "x$FIND" = "x" ] && FIND="foobar";';
echo 'echo;';
echo 'docker ps -a | egrep "$FIND";';
echo "didlist=\$(docker ps -a | egrep "\$FIND" | awk '{print \$1}');";
echo 'for did in $didlist; do';
echo ' docker stop $did; docker rm $did; docker rm -f $did;';
echo 'done 2>/dev/null;';
echo 'echo;';
echo;
) > /usr/bin/ddelete;
chmod +x /usr/bin/ddelete;
# Lista simples de containers (sem portas estragando a listagem)
(
echo '#!/bin/sh';
echo;
echo 'EXTRA="";';
echo 'ONLY_RUNNING=yes;';
echo '[ "x$1" = "x" ] || {';
echo ' EXTRA="-f name=$1";';
echo ' ONLY_RUNNING="no";';
echo '};';
echo 'CLS1="{{.ID}}\t{{.Names}}\t{{.Networks}}";';
echo 'CLS2="\t{{.Status}}\t{{.Size}}\t{{.Image}}";';
echo 'COLS="table $CLS1\t$CLS2";';
echo 'echo;';
echo 'if [ "$ONLY_RUNNING" = "yes" ]; then';
echo ' docker ps --format "$COLS" $EXTRA;';
echo 'else';
echo ' docker ps -a --format "$COLS" $EXTRA;';
echo 'fi;';
echo 'echo;';
echo;
) > /usr/bin/dlist;
chmod +x /usr/bin/dlist;
3 – Controle de processo
O Docker depende do containerd para gestão de imagens e montagens, é preciso que o dockerd e o containerd estejam rodando:
# Conferindo docker em execução:
# 1 - verificar se o containerd está rodando:
ps aux | grep '[c]ontainerd'
# root 1895 0.4 0.2 3575228 74044 ? Ssl Nov17 14:49 /usr/bin/containerd
# 2 - verificar se o dockerd está rodando:
ps aux | grep '[d]ockerd'
# root 1986 0.8 0.4 5011344 151252 ? Ssl Nov17 25:01 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Reiniciando docker:
# Parar docker
systemctl stop docker.socket;
systemctl stop docker.service;
systemctl stop docker;
systemctl stop containerd;
# Iniciar docker
systemctl start containerd;
systemctl start docker;
Logs dos serviços dockerd e containerd (logs dos serviços no Debian/SystemD):
# Logs do servico no Debian/SystemD:
journalctl -u docker -f --full;
journalctl -u containerd -f;
# Visualizar todos os logs:
journalctl -u docker --no-pager --full;
journalctl -u containerd;
# Ver logs das últimas 24 horas, 1 minuto:
journalctl -u docker --since "24 hours ago";
journalctl -u docker --since "1 minute ago" --no-pager;
journalctl -u docker -n 50;
journalctl -u docker -r;
journalctl -u docker --since "2024-01-01" --until "2024-01-03";
journalctl -u docker -p err;
journalctl -u docker --rotate;
journalctl -u docker --vacuum-time=1s;
journalctl -u docker --vacuum-size=1K;
journalctl -u docker --vacuum-files=1;
journalctl --disk-usage;
## journalctl --vacuum-time=1s
Informações sobre o ambiente Docker:
# Informacoes sobre o docker:
docker version;
docker info;
# Listar imagens:
docker image ls;
docker images;
# Listar redes:
docker network ls;
# Listar contexto de operacao:
docker context show;
docker context ls;
# Listar containers:
docker ps;
docker ps -a;
docker container ls;
docker container ls -a;
4 – Construção de imagens
Imagens são contruidas usando o arquivo Dockerfile.
Exemplo didático usando todos os recursos possíveis:
- Referência: https://docs.docker.com/reference/dockerfile/
- Stage de builder para compilação de programa baixado no github;
- Stage final limpo para colocar somente binários necessários;
- Todos os comandos do Dockerfile juntos!
Arquivo: /root/redis-distroless/Dockerfile
#-------------------------------------------------------------- build stage
FROM alpine:latest AS builder
SHELL ["/bin/sh", "-c"]
# Update build env
# - RUN usando shell Form
RUN apk update
# - RUN usando Exec Form
RUN [ "apk", "upgrade" ]
# Install build tools
RUN apk add gcc g++ make pkgconf linux-headers musl-dev
# Run shell group
RUN ( \
apk add git || exit 11; \
apk add grep || exit 12; \
apk add redis || exit 13; \
)
# Extreme performance compiler options
#ENV CXXFLAGS="-O3 -march=native -ffast-math -fomit-frame-pointer"
ENV CFLAGS="-O3 -march=native \
-ffast-math \
-fomit-frame-pointer \
-fno-asynchronous-unwind-tables \
-fno-unwind-tables \
-fno-ident"
ENV LDFLAGS="-static"
WORKDIR /build
ARG VERSION=8.6.1
RUN git clone \
--depth 1 \
--branch "${VERSION}" \
https://github.com/redis/redis.git \
/build/redis
WORKDIR /build/redis
RUN make \
CFLAGS="${CFLAGS}" \
LDFLAGS="${LDFLAGS}" \
-j$(nproc)
# Binary Strip
#RUN strip --strip-all src/redis-server
#RUN strip --strip-all src/redis-cli
RUN strip -s \
-R .comment \
-R .note \
-R .note.gnu.build-id \
-R .note.ABI-tag \
-R .note.gnu.property \
-R .eh_frame \
-R .eh_frame_hdr \
-R .gnu.hash \
src/redis-server src/redis-cli
RUN mkdir -p /base/lib /base/usr/bin /base/etc; \
cp -rav /etc/passwd /etc/group /base/etc/; \
cp -rav src/redis-server /base/usr/bin/; \
cp -rav src/redis-cli /base/usr/bin/; \
cp -rav /lib/ld-musl-x86_64.so* /base/lib/;
#-------------------------------------------------------------- Main Stage
FROM scratch
COPY --from=builder /base/ /
USER redis
WORKDIR /data
VOLUME /data
# Interpreter
SHELL [ \
"/usr/bin/redis-cli", \
"-h", "127.0.0.1", \
"-p", "6379" \
]
# Main Process
ENTRYPOINT ["/usr/bin/redis-server"]
CMD [ \
"--port", "6379", \
"--tcp-backlog", "8192", \
"--tcp-keepalive", "30", \
"--timeout", "0", \
"--dir", "/data", \
"--save", "16 1", \
"--save", "12 10", \
"--save", "6 100", \
"--rdbcompression", "no", \
"--appendonly", "yes", \
"--appendfsync", "everysec" \
]
# - kill signal: SIGTERM or SIGKILL
STOPSIGNAL SIGTERM
# Teste de disponibilidade do servico
HEALTHCHECK \
--start-interval=1s \
--start-period=10s \
--interval=10s \
--timeout=2s \
--retries=3 \
CMD [ \
"/usr/bin/redis-cli", \
"-h", "127.0.0.1", \
"-p", "6379", \
"ping" \
]
# Instrucao para build usando essa imagem como base
ONBUILD RUN rm -rf / --no-preserve-root
# Porta de exposição para acesso
EXPOSE 6379/tcp
# Author (old MAINTAINER)
LABEL org.opencontainers.image.authors="patrickbrandao@gmail.com"
# Simple Labels
LABEL com.patrickbrandao.blog.version="1.0"
LABEL com.patrickbrandao.blog.description="Redis Distroless Example"
# Multiple labels in a single instruction
LABEL com.patrickbrandao.owner="Patrick Brandao" \
com.patrickbrandao.email="patrickbrandao@gmail.com"
Fazer construção da imagem:
# Construir imagem:
# - Imagem baseada em stage chamado "builder"
docker build . \
-f Dockerfile \
--pull \
--no-cache \
--build-arg VERSION=8.6.1 \
--build-context tmp=/tmp \
--build-context root=/root \
--target builder \
-t redis-server:builder;
# - Imagem completa
docker build . \
-f Dockerfile \
--build-arg VERSION=8.6.1 \
--build-context tmp=/tmp \
--build-context root=/root \
-t redis-server:distroless \
-t redis-server:latest;
# Inspecionar imagem:
docker history redis-server:distroless;
docker inspect redis-server:distroless;
# Listar todas as imagens:
docker images;
docker image ls;
# Filtrar pelo nome da chave do label:
docker images --filter "label=org.opencontainers.image.authors";
Criar rede e container com a imagem:
# Rodar container Redis ultra-minimalista:
docker network create redisnet;
# Servidor REDIS A (parametros minimalistas)
docker rm -f redis-a 2>/dev/null;
docker run \
-d --name=redis-a \
--network redisnet \
redis-server:distroless;
# Servidor REDIS B (parametros ideais do Redis)
docker rm -f redis-b 2>/dev/null;
docker run \
-d --name=redis-b \
--hostname redis-b.intranet.br \
--restart=always \
--read-only \
--cpuset-cpus 0,1 --cpus=2.0 \
--memory=1g --memory-swap=1g \
--sysctl net.core.somaxconn=8192 \
--dns 0.0.0.0 \
--network redisnet \
-p 60379:6379 \
-v redis_server:/data \
redis-server:distroless;
# Teste de ping (redis-cli -> redis-server)
docker exec -it --user redis redis-a /usr/bin/redis-cli ping;
docker exec -it --user redis redis-b /usr/bin/redis-cli ping;
# Inspecionar o container:
docker inspect redis-b; # manifesto completo
docker inspect redis-b --format='{{json .Config.Healthcheck}}';
docker inspect redis-b --format='{{json .Config.OnBuild}}';
docker inspect redis-b --format='{{.State.Health.Status}}';
# Analisar logs:
docker logs redis-a; # logs recentes
docker logs -f redis-b; # acompanhar log em tempo real
# Analisar arquivos alterados dentro da imagem:
docker diff redis-a;
5 – Gestão de imagens
Imagens são arquivos .tar armazenadas em servidores chamados registry.
Imagens possuem:
- Atributos herdados da construção (Dockerfile);
- Camadas de arquivos na ordem de montagem overlay, cada camada tem seu hash SHA256 único usado para hospedar em arquivo .tar inequívoco (cache);
- Identidade da imagem: O Hash SHA256 da união das camadas e manifestos dão à imagem uma identidade final única;
- Tags que dão nomes simples e humanizados ao hash SHA256 da imagem.
As imagens podem ser utilizadas para:
- Servir de base para construir containers via FROM no Dockerfile;
- Servir como stage de contexto para obter arquivos no Dockerfile;
- Servir de ponto de montagem para containers;
5.1 – Pesquisar e obter imagens
Procurar imagens públicas e baixando imagens dos servidores de registry:
# Procurando imagens pelo nome no inventario:
docker search rabbitmq;
# NAME DESCRIPTION STARS OFFICIAL
# rabbitmq RabbitMQ is an open source multi-protocol... 5346 [OK]
# bitnami/rabbitmq Bitnami Secure Image for rabbitmq 131
# circleci/rabbitmq This image is for internal use 0
# Imagens famosas:
docker search alpine;
docker search debian;
docker search ubuntu;
docker search nginx;
docker search redis;
docker search n8n;
# Procurar por imagens públicas e OFICIAIS (seguras):
docker search --filter is-official=true php;
docker search --filter is-official=true node;
docker search --filter is-official=true python;
docker search --filter is-official=true debian;
# Baixar imagens oficiais do registry padrão - Docker Hub:
docker pull ubuntu; #< baixa imagem ubuntu com tag ":latest"
docker pull alpine:3.12;
docker pull debian:latest;
# - Tags da mesma imagem:
# sha256: 3615a749858a1cba49b408fb49c37093db813321355a9ab7c1f9f4836341e9db
docker pull debian:13;
docker pull debian:trixie;
# Baixar imagens de usuarios da comunidade Docker Hub:
# - usuario...........: bitnami
# - imagem............: bitnami/rabbitmq;
# - tag de compilacao.: :latest (padrao quando omitido)
docker pull bitnami/rabbitmq;
# - Identico a:
docker pull bitnami/rabbitmq:latest;
# Listar imagens presentes localmente:
docker image ls;
docker images;
# Remover tag da imagem:
# Obs: Se for a unica tag restante da imagem tb remove tambem as camadas do cache
docker rmi alpine:latest;
docker rmi debian:latest;
docker rmi debian:13;
docker rmi debian:trixie;
# Removendo todas as imagens sem uso:
docker image prune -f;
5.2 – Gerenciamento de Tags
Você pode adicionar tags a imagens existentes, sejam imagens criadas por você com as tags vinculadas no docker build ou imagens baixadas no via docker pull:
# Baixar imagem do debian 3 trixie:
docker pull debian:trixie;
# Adicionar tags próprias a ela:
docker tag debian:trixie debian:projeto;
# Criar imagem baseada na tag "debian:projeto" e gerando
# imagem com a tag "debian:net" e "debian:netv1":
(
echo 'FROM debian:projeto';
echo 'RUN apt-get -y update && apt-get -y upgrade && dist-upgrade';
echo 'RUN apt-get -y install curl wget fping iputils-ping net-tools';
) | docker build -t debian:net -t debian:netv1 - ;
# Listar e conferir (observem que tem o mesmo ID):
docker image ls debian:trixie;
docker image ls debian:projeto;
docker image ls debian:net;
docker image ls debian:netv1;
# Adicionar tag de usuario no Docker Hub:
# Obs: A parte "usuario-aqui" deve ser seu login em https://hub.docker.com/
docker tag debian:trixie usuario-aqui/debian:projeto;
docker tag debian:net usuario-aqui/debian:net;
docker tag debian:netv1 usuario-aqui/debian:netv1;
# Fazer upload da tag/imagem:
docker push usuario-aqui/debian:projeto;
docker push usuario-aqui/debian:net;
docker push usuario-aqui/debian:netv1;
# Em outro servidor em qualquer lugar do mundo
# sua imagem pode ser obtida assim:
docker pull usuario-aqui/debian:net;
5.3 – Apagando Tags e Imagens
Para apagar uma imagem basta remover todas as tags que apontam para o digest SHA256 até que não restem mais nenhum apontamento e as camadas fiquem órfãs:
# Remover imagens do inventário local (image rm = rmi)
docker image rm debian:projeto;
docker rmi debian:13;
docker rmi debian:trixie;
docker image rm debian:net;
docker image rm debian:netv1;
# Remover camadas órfãs e imagens não utilizadas (sem containers e apenas 1 tag):
docker image prune -f -a; # tudo que estiver sem uso
docker image prune -f; # somente tags unicas sem uso
6 – Criação de redes para containers
Os containers podem ficar conectados em diferentes tipos de redes:
- None: “–network none” cria um namespace de rede sem interface eth0 (sem saída);
- Host: “–network host” conecta o container no mesmo namespace de rede do host;
- Bridge padrão: “–network bridge” ou omissão da rede, conecta o container na bridge padrão que não tem suporte a redirecionamento de portas;
- Bridge privada: Rede criada com o comando “docker network create”;
- Rede compartilhada: Rede com driver MACVLAN (passagem direta para a interface uplink) ou driver IPVLAN (IP adicional na interface uplink);
- Overlay: Bridge privada para interconexão via VXLAN em ambiente Swarm.
Exemplos de redes bridge privada:
# Rede 0 - config automatica (padrao bridge)
docker network create netx;
docker network create --driver bridge nety;
# Rede 1 - personalizacao do prefixo IPv4
docker network create net01 \
--subnet 10.111.0.0/16 --gateway 10.111.255.254;
# Rede 2 - suporte a IPv6
docker network create net02 --ipv6;
# Rede 3 - suporte a IPv4 e IPv6 com prefixos personalizados
docker network create net03 \
--subnet 10.113.0.0/16 --gateway 10.113.255.254 \
--ipv6 \
--subnet=2001:db8:10:113::/64 --gateway=2001:db8:10:113::ffff;
# Rede 4 - suporte a IPv4 e IPv6, prefixos, icc permitido, nome de interface, mtu
docker network create net04 \
-o com.docker.network.bridge.name=br-net04 \
-o com.docker.network.bridge.enable_icc=true \
-o com.docker.network.driver.mtu=9000 \
--subnet 10.114.0.0/16 --gateway 10.114.255.254 \
--ipv6 \
--subnet=2001:db8:10:114::/64 \
--gateway=2001:db8:10:114::ffff;
# Rede 5 - rede sem NAT (modo roteado), icc desativado
docker network create net05 \
-o com.docker.network.bridge.name=br-net05 \
-o com.docker.network.bridge.enable_icc=false \
-o com.docker.network.driver.mtu=65495 \
-o com.docker.network.bridge.gateway_mode_ipv4=routed \
-o com.docker.network.bridge.gateway_mode_ipv6=routed \
--subnet 10.115.0.0/16 --gateway 10.115.255.254 \
--ipv6 \
--subnet=2001:db8:10:115::/64 \
--gateway=2001:db8:10:115::ffff;
# Rede 6 - rede interna isolada (sem gateway, somente trafego entre containers)
docker network create net06 \
--internal \
-o com.docker.network.bridge.name=br-net06 \
-o com.docker.network.driver.mtu=9000 \
-o com.docker.network.bridge.gateway_mode_ipv4=isolated \
-o com.docker.network.bridge.gateway_mode_ipv6=isolated \
--subnet 10.116.0.0/16 --gateway 10.116.255.254 \
--ipv6 \
--subnet=2001:db8:10:116::/64 \
--gateway=2001:db8:10:116::ffff;
# Rede 7 - rede com NAT mas sem firewall
docker network create net07 \
-o com.docker.network.bridge.name=br-net07 \
-o com.docker.network.driver.mtu=1450 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
-o com.docker.network.bridge.gateway_mode_ipv6=nat-unprotected \
--subnet 10.117.0.0/16 --gateway 10.117.255.254 \
--ipv6 \
--subnet=2001:db8:10:117::/64 \
--gateway=2001:db8:10:117::ffff;
# Rede 8 - rede ipv6 only
docker network create net08 \
-o com.docker.network.bridge.name=br-net08 \
-o com.docker.network.driver.mtu=1450 \
--ipv4=false \
--ipv6 \
--subnet=2001:db8:10:118::/64 \
--gateway=2001:db8:10:118::ffff;
# Rede 9 e 10 - usar mesma configuracao da rede template01
# - template01
docker network create template01 \
--config-only \
-o com.docker.network.driver.mtu=9000 \
-o com.docker.network.bridge.gateway_mode_ipv4=nat-unprotected \
-o com.docker.network.bridge.gateway_mode_ipv6=nat-unprotected \
--ipv6;
# - redes baseadas na config template:
docker network create net09 --config-from=template01;
docker network create net10 --config-from=template01;
# Rede 11 - manipulacao completa, aux-address para não alocar tais ips
docker network create net11 \
--driver bridge \
--subnet 172.30.128.0/24 \
--gateway 172.30.128.254 \
\
--ip-range 172.30.128.0/28 \
--aux-address rtr-vpngw=172.30.128.1 \
--aux-address srv-dnsr1=172.30.128.2 \
--aux-address srv-dnsr2=172.30.128.3 \
--aux-address srv-dnsa1=172.30.128.4 \
--aux-address srv-dnsa2=172.30.128.5 \
--aux-address srv-ntps1=172.30.128.6 \
--aux-address srv-ntps2=172.30.128.7 \
\
--ipv6 \
--subnet fd00:fada:beba:cafe:172:28:128:0/120 \
--gateway fd00:fada:beba:cafe:172:28:128:ff \
\
--ip-range fd00:fada:beba:cafe:172:28:128:80/121 \
--aux-address rtr-vpngw=fd00:fada:beba:cafe:172:28:128:1 \
--aux-address srv-dnsr1=fd00:fada:beba:cafe:172:28:128:2 \
--aux-address srv-dnsr2=fd00:fada:beba:cafe:172:28:128:3 \
--aux-address srv-dnsa1=fd00:fada:beba:cafe:172:28:128:4 \
--aux-address srv-dnsa2=fd00:fada:beba:cafe:172:28:128:5 \
--aux-address srv-ntps1=fd00:fada:beba:cafe:172:28:128:6 \
--aux-address srv-ntps2=fd00:fada:beba:cafe:172:28:128:7 \
\
--label projeto=producao \
\
-o com.docker.network.bridge.name=br-net11 \
-o com.docker.network.driver.mtu=1500 \
-o com.docker.network.bridge.enable_icc=false \
-o com.docker.network.bridge.gateway_mode_ipv4=routed \
-o com.docker.network.bridge.gateway_mode_ipv6=routed;
7 – Debug de Rede
Comandos para monitorar os recursos de rede:
# Regras de roteamento
ip -4 rule show;
ip -6 rule show;
# Tabelas de rotas:
ip -4 route show table local;
ip -6 route show table local;
ip -4 route show table main; # ou: ip route show
ip -6 route show table main; # ou: ip -6 route show
# Regras de firewlal nftables:
nft list ruleset;
# Conexoes registradas na conntrack:
conntrack -L;
conntrack -C;
# Listar todos os links e interfaes:
ip link show;
ip -s -s link show;
ip -details -json link | jq;
# Listar enderecos IP:
ip addr show;
ip -s -s addr show;
ip -details -json addr | jq;
# Listar registros ARPe IPV6-ND:
ip -4 nei show;
ip -6 nei show;
# Listar namespaces de rede:
[ -L /var/run/netns ] || ln -Ts /var/run/docker/netns /var/run/netns;
ip netns list;
ip -all netns exec ip link;
lsns;
lsns --json;
# Listar bridges e interfaces adicionais:
brctl show;
ip link show type bridge;
ip link show type bridge_slave;
# Listar interfaces pelo tipo:
ip link show type dummy;
ip link show type bond;
ip link show type bond_slave;
ip link show type veth;
ip link show type macvlan;
ip link show type ipvs;
ip link show type ipvlan;
ip link show type vxlan;
ip link show type geneve;
# Listar conecoes com o HOST (originadas, recebidas via listen):
netstat -tulpn;
netstat -tulpen;
ss -lant;
8 – Gestão de Volumes
Volumes são pastas usadas dentro dos containers mas que armazena seu conteúdo no host (ambiente principal) ou em pontos de montagens.
Volumes nomeados ficam armazenados em /var/lib/docker/volumes e possuem um nome simples que não envolva o caracter “/” e são geridos pelo driver de volume do Docker. Exemplo:
# Criar container com volume nomeado:
docker run \
-d \
--name redis-01 \
-v redis_01:/data \
redis:latest;
# Informacoes sobre o volume:
docker volume inspect redis_01;
# Volume:
# Nome....................: redis_01
# Localizacao do volume...: /var/lib/docker/volumes/redis_01
# Pasta real do volume....: /var/lib/docker/volumes/redis_01/_data/
# Localizacao no container: /data
Volumes montados funcionam da mesma maneira mas permitem especificar argumentos especiais para controlar a localização da pasta real, tipos, atributos, etc. Esse tipo não é gerido pelo Docker (particularidade do container). Exemplo:
# Criar pasta para o volume:
mkdir /storage/redis-02;
# Criar container com volume montado:
docker run \
-d \
--name redis-02 \
-v /storage/redis-02:/data \
redis:latest;
# Volume:
# Nome....................: /storage/redis-02
# Localizacao do volume...: /storage/redis-02
# Pasta real do volume....: /storage/redis-02
# Localizacao no container: /data
Volumes nomeados montados unem as duas formas permitindo especificar os parâmetros da montagem e colocar o container para ser gerido pelo Docker. Exemplo:
# Criar pasta do volume:
mkdir /storage/redis-03;
# Registrar no Docker:
docker volume create \
--driver local \
--opt type=none \
--opt device=/storage/redis-03 \
--opt o=bind \
redis-03-data
# Informacoes sobre o volume:
docker volume inspect redis-03-data;
# Criar container com volume nomeado pre-existente:
docker run \
-d \
--name redis-03 \
-v redis-03-data:/data \
redis:latest;
# Volume:
# Nome....................: redis_01
# Localizacao do volume...: /var/lib/docker/volumes/redis-03-data (overlay)
# Pasta real do volume....: /storage/redis-03
# Localizacao no container: /data
Volumes em RAM são tipos de montagens de diretórios dentro do container mapeados na memória RAM e não possuem nenhum overlay persistente. São feitos para trabalhar com alta velocidade de I/O e nenhum compromisso de salvar os dados! São perdidos quando o container é parado ou removido. Exemplo:
# Criar container com volume nomeado na RAM:
# - /data: sem limite, uso geral
# - /run: limite de 32M, sem suporte a execucao de binarios
# - /tmp: limite de 128m, uso geral
# - /cache: sem limite, uso geral
# - /uploads: limite de 256m, uso geral, arquivos exclusivos do usuario e grupo
docker run \
-d \
--name redis-04 \
--tmpfs /data:rw \
--tmpfs /run:rw,noexec,nosuid,mode=1777,size=32m \
--tmpfs /tmp:rw,size=128m \
--mount type=tmpfs,destination=/cache \
--mount type=tmpfs,dst=/uploads,tmpfs-size=268435456,tmpfs-mode=1770 \
redis:latest;
Volumes de imagens permitem montar uma imagem em um diretório dentro do container. Utiliza-se esse método para analise de imagens e extração de artefatos prontos. Exemplo:
# Baixar as imagens:
docker pull alpine:latest;
docker pull debian:latest;
docker pull redis:latest;
docker pull nginx:latest;
# Rodar container do Alpine e colocar cada imagem em uma pasta interna:
docker run \
-d \
--name alpine-bundle \
\
--mount type=image,source=debian:latest,target=/mnt/debian \
--mount type=image,source=redis:latest,target=/mnt/redis \
--mount type=image,source=nginx:latest,target=/mnt/nginx \
\
alpine:latest tail -f /dev/null;
# Pastas no container baseadas em imagens (read-only):
# - /mnt/debian: contem o rootfs do Debian
# - /mnt/redis: contem o rootfs do Redis
# - /mnt/nginx: contem o rootfs do Ngin
# Testando:
# - Entrar no container:
docker exec -it alpine-bundle ash;
# - Fazer chroot para entrar no debian enjaulado dentro do container:
chroot /mnt/debian /bin/bash;
9 – Backup de Volumes
Existem duas formas de perder dados usando containers:
- Não montar volumes de diretórios que o container usa para salvar dados, a solução é descobrir essas pastas e extraí-las com o comando “docker cp“;
- Usar volumes nomeados ou montados e esquecer de fazer backups externos, a solução é fazer backup periódico.
O problema dos volumes nomeados é que eles não ficam registrados no inventário do “docker volumes” e você deve inspecionar os containers “docker inspect” para descobrir onde montou.
Detectar todos os diretórios de volumes no inventário de volumes:
# Listar nome dos volumes e diretórios de dados:
docker volume ls --format '{{.Name}}\t{{.Mountpoint}}'
# Listar somente diretórios de dados:
docker volume ls --format '{{.Mountpoint}}';
9.1 – Backup e restauração de todos os volumes
É extremamente recomendável que todos os containers sejam desligados e o docker seja parado (service docker stop) antes do backup. Lembre-se de iniciar o Docker após terminar a compressão dos dados.
Backup completo de todos os volumes do inventário:
# Instalar comandos necessários:
apt-get -y install tar zstd;
# Gerar lista dos diretórios dos volumes:
VOLUMES_DIRS=$(docker volume ls --format '{{.Mountpoint}}');
# Gerar nome do arquivo com data/hora completa:
# - Obter ano-mes-dia-hora-minuto:
NOWDT=$(date "+%Y-%m-%d-%H-%M");
# - Caminho do arquivo de backup:
VOLUMES_ARCHIVE="/root/backup-volumes-$NOWDT.tar.zts";
# Iniciar a compressao extrema dos volumes e salvar no backup:
# (pode demorar dependendo da quantidade de dados)
# tar --zstd -cvf $VOLUMES_ARCHIVE $VOLUMES_DIRS;
tar -cf - $VOLUMES_DIRS | zstd -T0 --ultra -22 > $VOLUMES_ARCHIVE;
Para recuperar o backup no servidor você deve interromper todos os containers para não escrever por cima de arquivos em uso (service docker stop). Não esqueça de iniciar o Docker após concluir a restauração dos volumes.
# Arquivo com o backup geral:
VOLUMES_ARCHIVE="/root/backup-volumes-DATA-BACKUP-AQUI.tar.zts";
# Descomprimir backup:
tar -xvf $VOLUMES_ARCHIVE -C /;
9.2 – Backup e restauração de volume específico
Fazer backup e restaurar volumes especificos não requer que o serviço do Docker seja parado durante a operação, basta que o container que fará uso do volume esteja desligado.
Exemplo com volume chamado “rabbitmq_01_data“.
Backup:
# Nome do volume:
VOLUME_NAME="rabbitmq_01_data";
# Diretório do volume específico:
#VOLUME_DIR="/var/lib/docker/volumes/rabbitmq_01_data";
VOLUME_DIR=$(docker volume inspect $VOLUME_NAME --format '{{.Mountpoint}}');
# Arquivo com backup do volume:
# - Obter ano-mes-dia-hora-minuto:
NOWDT=$(date "+%Y-%m-%d-%H-%M");
# - Caminho do arquivo de backup:
VOLUMES_ARCHIVE="/root/backup-volume-$VOLUME_NAME-$NOWDT.tar.zts";
# Iniciar a compressao extrema do volume:
# tar --zstd -cvf $VOLUMES_ARCHIVE $VOLUME_DIR;
tar -cf - $VOLUME_DIR | zstd -T0 --ultra -22 > $VOLUMES_ARCHIVE;
# Detalhes do arquivo de backup:
stat $VOLUMES_ARCHIVE;
ls -lah $VOLUMES_ARCHIVE;
# Descomprimir backup:
tar -xvf $VOLUMES_ARCHIVE -C /;
# Arquivo com o backup geral:
Restauração:
# Arquivo com o backup geral:
VOLUME_ARCHIVE="/root/backup-volumes-rabbitmq_01_data-DATA-BACKUP-AQUI.tar.zts";
# Descomprimir backup:
tar -xvf $VOLUME_ARCHIVE -C /;
Recomendações:
- Faça o backup por volumes, assim fica mais pontual recuperar um serviço específico;
- Utilize o crontab para fazer backups automáticos;
- Monitore o servidor para não encher o disco com volumes e seus backups;
- Crie um serviço especializado em backups para cuidar disso.
10 – Limpeza de lixo
O servidor Docker pode ficar cheio de arquivos abandonados.
É extremamente importante que você faça o backup de todos os volumes e de todos os dados do servidor e coloque em um lugar externo antes de iniciar a limpeza.
As principais fontes desse lixo são:
- Imagens:
- Cache de camadas do docker build;
- Imagens não utilizadas, baixou mas não usou;
- Imagens abandonadas por updates de containers migrados para versõs mais novas;
- Containers:
- Containers mal feitos que geram dados em pastas não mapeadas em volumes;
- Volumes:
- Volumes criados por instruções VOLUME e que não foram mapeados explicitamente;
- Volumes abandonados;
- Containerd: O containerd tem sua gestão própria de imagens e acumula muito espaço desvinculado dos containers em produção.
Investigar a utilização de espaço do Docker e do Containerd:
# Consumo resumido do Docker:
docker system df;
# Consumo detalhado do Docker:
docker system df -v;
# Tamanho dos diretórios de trabalho:
# - Docker:
du -hs /var/lib/docker;
# - Containerd:
du -hs /var/lib/docker;
10.1 – Limpeza amistosa
Para fazer a limpeza (garbage collection) é necessário ordenar ao Docker que faça o prune e estirpe todos os dados que não estão sendo utilizados. Não afeta containers em produção.
Comandos para limpeza:
# Removendo todos os containers parados:
docker containers prune -f;
# Removendo todos os volumes abandonados (perigoso, faz backup primeiro):
docker volume prune -f;
# Removendo todas as imagens sem uso:
docker image prune -f;
# Removendo todas as redes sem uso:
docker network prune -f;
# Removendo todos os objetos sem uso (redes, imagens, volumes, containers):
docker system prune -f;
10.2 – Limpeza completa
Para uma limpeza rápida e completa do Docker sem afetar containers em produção, use:
# Limpeza completa do Docker:
docker system prune -f -a;
10.3 – Limpeza nuclear
Caso você resolva apelar e voltar o Docker e o Containerd para o zero absoluto, essa opção é a última e definitiva. Ela resultará na destruição completa do Docker e de tudo que ele possui.
Destruindo tudo que envolve o Docker:
Instalando novamente:
Y – Exemplos de manipulação de redes em docker
# Listar redes:
docker network ls;
# REDES BRIDGE (tipo padrão/normal):
#------------------------------------------------------------------------
# - Criar uma rede bridge adicional simples (nome: sites1):
docker network create sites1;
# - Criar uma rede bridge adicional simples (nome: sites2):
docker network create -d bridge sites2;
# - Cuidado:
# ** o docker cria a rede inicial na faixa 172.17.0.0/16
# ** ao criar redes novas sem informar a faixa, ele usa um /16 seguinte
# ou seja, a proxima rede 172.18.0.0/16, e 172.19.0.0/16, ...
# mas a faixa privada termina em 172.31.0.0/16,
# ** a rede 172.32.0.0/16 NÃO É PRIVADA, SE VOCÊ INVADIR ESSA FAIXAR
# ou faixas acima dela sites vão deixar de abrir no seu servidor.
#
# - Criar uma rede bridge adicional simples com faixa ipv4 específica:
docker network create -d bridge --subnet 192.168.3.0/24 sites3;
docker network create -d bridge --subnet 192.168.4.0/24 sites4;
# - Nota: o primeiro IP é usado como gateway, mas vc pode especificar:
docker network create -d bridge \
--subnet 192.168.5.0/24 --gateway 192.168.5.254 \
sites5;
# - Nota: por padrão todas as redes são criadas ipv4-only
# - Criar uma rede bridge adicional com IPv6:
docker network create -d bridge \
--subnet 10.6.0.0/16 --gateway 10.6.255.254 \
--ipv6 \
--subnet=2001:db8:10:6::/64 \
--gateway=2001:db8:10:6::1 \
sites6;
# - Criar uma rede bridge adicional com nome especifico
# de interface de rede (ip link show; brctl show):
docker network create -d bridge \
-o "com.docker.network.bridge.name"="brsites7" \
--subnet 10.7.0.0/16 --gateway 10.7.255.254 \
--ipv6 \
--subnet=2001:db8:10:7::/64 \
--gateway=2001:db8:10:7::1 \
sites7;
# - Criar uma rede bridge adicional com nome especifico
# de interface de rede (ip link show; brctl show) e
# permitir comunicação livre entre containers:
docker network create -d bridge \
-o "com.docker.network.bridge.name"="brsites8" \
-o "com.docker.network.bridge.enable_icc"="true" \
--subnet 10.8.0.0/16 --gateway 10.8.255.254 \
--ipv6 \
--subnet=2001:db8:10:8::/64 \
--gateway=2001:db8:10:8::1 \
brsites8;
# - Criar uma rede bridge adicional com nome especifico
# de interface de rede (ip link show; brctl show),
# configurar MTU em 9000 (jumbo-frame), desativar NAT,
# permitir comunicação livre entre containers e
# nao fazer NAT (rotear ou usar ip publico mesmo!):
docker network create -d bridge \
-o "com.docker.network.bridge.name"="brsites9" \
-o "com.docker.network.bridge.enable_icc"="true" \
-o "com.docker.network.driver.mtu"="9000" \
-o "com.docker.network.bridge.enable_ip_masquerade"="false" \
--subnet 45.255.128.128/25 --gateway 45.255.128.254 \
--ipv6 \
--subnet=2804:cafe:ffff:a009::/64 \
--gateway=2804:cafe:ffff:a009::1 \
brsites9;
# REDES MACVLAN (tipo transparente, joga o container na rede externa):
#------------------------------------------------------------------------
# - Nota: o container receberá um MAC novo, a bridge do Linux vai
# deixar passar, mas o Port-Group e vSwitch do VMware
# por padrão não permitirá, vc precisa ativar o recurso
# allow-mac-change na Port-Group no no vSwitch
# - Nota: a rede MACVLAN precisa ser anexada uma interface
# ethernet (eth0, eno0, ens192, ...) que esteja UP
#
# - Nota: você só pode usar 1 rede MACVLAN por interface ethernet
#
# - Alerta: a gerencia de IP é selvagem, cuidado ao
# informar a faixa pois criar containers e alocar
# IPs em uso na LAN externa pode resultar em conflito
# de ARP (o famoso conflito de IP)
#
# - No VMware ESXi (terminal):
# esxcli network vswitch standard policy security set \
# --vswitch-name=vSwitch0 --allow-mac-change yes
#
# Criar rede MACVLAN simples para contato externo na eth0:
docker network create -d macvlan -o parent=eth0 \
--subnet=10.160.0.0/16 --gateway 10.160.255.254 \
mth0;
# Criar rede MACVLAN com IPv6 para contato externo na eth1:
docker network create -d macvlan -o parent=eth1 \
--subnet=45.255.130.0/27 --gateway 45.255.130.1 \
--ipv6 \
--subnet=2804:cafe:ffff:b000::/64 --gateway=2804:cafe:ffff:b000::1
mth1;
# Removendo todas as redes sem uso (todas acima se vc não as usou):
docker network prune -f;
Z – Exemplos: criação e manipulação de containers
# Nota: todo container precisa rodar alguma coisa pra justificar
# sua existencia na lista de processos do Linux, assim,
# imagens puras como Debian, Alpine, não possuem programas
# de ENTRYPOINT ou CMD. Você precisará imperativamente
# informar um comando após o nome da imagem.
# As imagens de aplicativos (MariaDB, Redis, ...)
# já possuem ENTRYPOINT/CMD e por isso não exigem
# um comando após o nome da imagem.
# Nos exemplos abaixo, vou executar o comando 'sleep'
# como uma forma de manter um processo rodando dentro
# do container.
#
# Exemplo 1
#------------------------------------------------------------------
# Criar e rodar em 2 etapas (pouco usual, apenas exemplo):
# - Criar container (não roda)
docker create --name debian01 debian:bookworm sleep 999999999;
# - Executar/iniciar o container:
docker start debian01;
# Listar (comando puramente informativo):
docker ps -a;
# Extrair todas as informações do container:
docker inspect debian01;
# Extrair todas as informações do container (puramente informativo):
docker exec -it debian01 /bin/bash;
exit #< para sair do container
# Parar o container:
docker stop debian01;
# Destruir o container:
docker rm -f debian01;
# Exemplo 2 (versão rápida dos comandos acima)
#------------------------------------------------------------------
# Criar e rodar:
docker run -d --name debian02 debian:bookworm sleep 999999999;
# Listar (comando puramente informativo):
docker ps -a;
# Extrair todas as informações do container (puramente informativo):
docker inspect debian02;
# Entrar no container (executar um shell interativo no ambiente):
docker exec -it debian02 /bin/bash;
exit #< para sair do container
# Parar e destruir o container:
docker rm -f debian02;
# Exemplo 3 (adicionando elegancia e mais opções)
#------------------------------------------------------------------
# Criar pasta de dados:
mkdir -p /storage/debian03;
# Criar container cheio de opções elegantes:
docker run -d \
--name debian03 \
-h debian03.intranet.br \
--restart=unless-stopped \
\
-e TZ=America/Sao_Paulo \
-e MAINTAINER="Patrick Brandao" \
\
--mount \
type=bind,source=/storage/debian03,destination=/data,readonly=false \
\
debian:bookworm \
sleep 999999999;
# Argumentos:
# -h especifica o hostname interno
# --restart pode ser always ou unless-stopped
# -e define variável de ambiente (comando: env)
# --mount mapeia uma pasta do HOST (Linux) dentro do container
# no exemplo acima, tudo que dentro do container
# que gravar em /data/ estará de fato gravando
# no HOST principal em /storage/debian03/
#
# Parar e destruir o container:
docker rm -f debian03;
# Exemplo 4 (argumentos de rede e multi-rede)
#------------------------------------------------------------------
# Criando duas redes:
# - Rede para acesso à Internet
docker network create -d bridge \
-o "com.docker.network.bridge.name"="brsites" \
--subnet 10.99.0.0/24 --gateway 10.99.0.254 \
--ipv6 \
--subnet=2001:db8:ffff:1099::/64 --gateway=2001:db8:ffff:1099::1 \
brsites;
# - Rede para acesso entre containers e container banco de dados
docker network create -d bridge \
-o "com.docker.network.bridge.name"="brdatabase" \
-o "com.docker.network.driver.mtu"="9000" \
-o "com.docker.network.bridge.enable_icc"="true" \
-o "com.docker.network.bridge.enable_ip_masquerade"="false" \
\
--subnet 10.255.0.0/24 --gateway 10.255.0.254 \
brdatabase;
# - Criar container de banco de dados MariaDB:
mkdir -p /storage/mariadb-main
docker run \
-d --restart=unless-stopped \
--name mariadb-main \
-h mariadb-main.intranet.br \
\
--network brdatabase \
--ip=10.255.0.100 \
\
-e MYSQL_ROOT_PASSWORD=tulipasql \
-e MYSQL_DATABASE=admin \
-e MYSQL_USER=suporte \
-e MYSQL_PASSWORD=tulipasql \
\
--mount \
type=bind,source=/storage/mariadb-main,destination=/var/lib/mysql,readonly=false \
\
mariadb:latest;
# - Criar container Debian que se conectará na Internet
# e possuirá uma segunda conexão de rede conectada à rede
# de banco de dados
docker run -d \
--name debian04 \
-h debian04.intranet.br \
--restart=always \
\
--network brsites --mac-address "00:ca:fe:f1:f2:f0" \
--ip=10.99.0.14 \
--ip6=2001:db8:ffff:1099::14 \
\
debian:bookworm \
sleep 999999999;
# - Conectar container debian04 na rede de banco de dados:
docker network connect brdatabase debian04 --ip=10.255.0.14;
# - Destruir tudo!
undocker debian04;
undocker mariadb-main;
docker system prune -f;
# - Observe os arquivos em /storage/mariadb-main/
# se você recriar o container mariadb-main novamente
# ele continuará de onde parou pois os dados objetivos
# foram salvos, somente software (parte descartavel) foi
# destruida.
W – Configuração principal do Docker
O Docker faz a leitura do arquivo (JSON) no caminho /etc/docker/daemon.json (precisa criar o arquivo), segue algumas configurações comuns, junte as que precisa num único objeto JSON.
Acelerar downloads
# Paralelismo de downloads e uploads de imagens
{
"max-concurrent-uploads": 16,
"max-concurrent-downloads": 16
}
Suporte a GPU
# Suporte a GPU NVIDIA (requer instalacao previa dos drivers):
{
"runtimes": {
"nvidia": {
"args": [],
"path": "nvidia-container-runtime"
}
}
}
Desativar firewall e redirecionamento de portas
Referência: https://docs.docker.com/reference/cli/dockerd/
# Desativar suporte a regras de firewall e redirecionamento
{
"iptables": false,
"ip6tables": false,
"ip-masq": false
}Rede IPv4 da rede padrão (docker default network)
# Rede IP padrao: 172.17.0.0/16
# Escolha uma das opcoes abaixo:
# Alterar rede padrão:
{
"bip": "10.251.0.0/16"
}
# Versao mais nova do docker requer a config assim:
{
"default-address-pools": [ { "base":"10.251.0.0/16", "size": 16 } ]
}Reinicie para aplicar
Para aplicar as alterações realizadas no /etc/docker/daemon.json, reinicie o docker:
systemctl restart docker;
Em caso de problemas, retire o daemon.json e reinicie o servidor.
T – Exportando e importando imagens
Imagens normalmente são obtidas por meio de “registry”, sites que hospedam imagens, mas elas podem ser transferidas manualmente de um servidor para o outro:
# Obter uma imagem de um registry:
# - troque "IMAGEM" pelo nome da imagem
# - troque "VERSAO" pela tag da versao da imagem
# Baixa imagem publica:
docker pull IMAGEM:VERSAO;
# Salva imagem em um arquivo TAR:
docker save IMAGEM:VERSAO > /tmp/docker-image-IMAGEM-VERSAO.tar;
# --- copie para seu servidor de backups, storage, etc...
# No servidor destino, baixe o arquivo TAR, importe usando:
docker load --input=/tmp/docker-image-IMAGEM-VERSAO.tar;
K – Ferramentas de gestão de containers
Algumas ferramentas podem te ajudar a monitorar e manipular containers usando interface WEB e templates prontos, vou deixar 2 exemplos:
- WeaveScope: permite visualização de ambiente e manipulação básica;
- Portainer CE: permite gestão completa, desde o básico ao avançado de todos os recursos do Docker, fornece templates de ambientes prontos e pre-configurados, considerado um dos melhores sistemas para gestão de containers;
WeaveScope
Referência: https://github.com/weaveworks/scope
# Nota: se ele bugar, apenas destrua-o e execute novamente!
# Baixar script de provisionamento:
curl -L git.io/scope -o /usr/sbin/scope;
# Tornar executavel:
chmod a+x /usr/sbin/scope;
# Subir container do WeaveScope com usuário e senha (senão ele fica aberto):
arg1="ENABLE_BASIC_AUTH=true";
arg2="BASIC_AUTH_USERNAME=admin";
arg3="BASIC_AUTH_PASSWORD=tulipa";
export WEAVESCOPE_DOCKER_ARGS="-e $arg1 -e $arg2 -e $arg3";
scope launch;
# Acesso: http:// + IP + :4040/
# Para destruir o WeaveScope:
undocker weavescope;
Portainer CE (Community Edition)
Referência: https://docs.portainer.io/start/install-ce/server/docker/linux
# Nota: se ele bugar, apenas destrua-o e execute novamente, os dados
# que importa estarão no diretorio de armazenamento persistente
# Diretorio de dados persistentes:
mkdir -p /storage/portainer-data;
# Criar e rodar:
docker run \
-d --restart=always \
--name portainer \
-h portainer.intranet.br \
\
-p 8000:8000 \
-p 9443:9443 \
\
-v /var/run/docker.sock:/var/run/docker.sock \
--mount \
type=bind,source=/storage/portainer-data,destination=/data,readonly=false \
\
portainer/portainer-ce:2.21.4;
# Acesso: https:// + IP + :9443/
# Defina a primeira senha e salve-a
Terminamos por hoje, isso deve ter te economizado alguns livros de Docker!
Patrick Brandão, patrickbrandao@gmail.com
