Aprenda Docker do Básico ao Avançado

Nos últimos anos, o Docker ganhou muita popularidade devido à maneira como simplifica o empacotamento e a implantação de aplicativos. Entender o Docker e seus conceitos básicos é essencial tanto para engenheiros de software quanto para engenheiros de DevOps. Este guia abrangente aborda desde a introdução ao Docker até tópicos avançados como segurança e otimização, fornecendo um roteiro claro para dominar essa tecnologia.

O que é Docker?

O Docker é uma plataforma de código aberto que permite automatizar o ciclo de vida do seu aplicativo usando tecnologias de contêiner. De forma simples, os contêineres são ambientes simples, leves e isolados que executam seus aplicativos. O Docker fornece uma camada de abstração sobre o sistema operacional hospedeiro, permitindo que os aplicativos sejam executados consistentemente, independentemente das diferenças na infraestrutura subjacente.

Por que usar Docker?

Existem várias razões pelas quais o Docker se tornou tão adotado em todos os processos de TI. Com o Docker, você permite que seus desenvolvedores empacotem seus aplicativos e todas as suas dependências em um único elemento (contêiner), garantindo consistência e reutilização em diferentes ambientes. Isso elimina (ou pelo menos tenta) o infame problema “Funciona na minha máquina”, que, sejamos sinceros, é tão irritante.

O Docker oferece uma alternativa leve à virtualização. A diferença entre contêineres e máquinas virtuais é que os contêineres compartilham o kernel do sistema operacional hospedeiro, resultando em menor sobrecarga e tempos de inicialização mais rápidos em comparação com as máquinas virtuais (as VMs incluem um sistema operacional convidado completo, o que significa que vêm com seu próprio kernel, que é executado sobre um hypervisor). Além disso, o Docker permite fácil escalonamento e implantação de aplicativos em diferentes ambientes, tornando-o uma ótima solução para arquiteturas nativas da nuvem.

Entrevistadores sempre perguntarão qual é a diferença entre contêineres e máquinas virtuais, então certifique-se de entender e lembrar. Aqui estão alguns dos principais benefícios que o Docker oferece: consistência e reutilização — garante que seu aplicativo seja executado de acordo com o plano, independentemente do ambiente em que é executado.

  • Portabilidade – Ao manter suas imagens Docker o menor possível, você pode compartilhá-las facilmente em diferentes ambientes.
  • Eficiência — Sendo leves, os contêineres Docker reduzem a sobrecarga quando comparados às máquinas virtuais.
  • Escalabilidade — Escalonar aplicativos para cima ou para baixo é algo que o Docker pode fazer facilmente.
  • Isolamento — O Docker garante que diferentes aplicativos que são executados no mesmo hospedeiro não interfiram uns com os outros.
  • Controle de versão e rollbacks — Ao emparelhar suas imagens Docker e configurações Docker com o controle de versão, você pode facilmente ter diferentes versões de suas imagens Docker, tornando os rollbacks muito fáceis.

Começando com Docker

Agora que temos uma compreensão fundamental do que é o Docker e quais são os benefícios de usá-lo, vamos começar com a instalação e configuração. Instalar o Docker é simples, pois ele fornece pacotes de instalação para diferentes sistemas operacionais, incluindo macOS, distribuições Linux e Windows. Basta baixar o pacote apropriado para o seu sistema e seguir as instruções de instalação fornecidas pelo Docker.

Para a maioria dos sistemas operacionais, a coisa mais fácil a fazer é instalar o Docker Desktop. Para trabalhar efetivamente com o Docker, você precisa primeiro entender a arquitetura Docker. Em alto nível, o Docker consiste em três componentes principais: Docker daemon (dockerd) — O Docker daemon é responsável por construir, executar e monitorar contêineres. Docker client — O Docker client é uma ferramenta de linha de comando que permite interagir com o Docker daemon. Ele envia comandos para o daemon e recebe informações dele.

Docker registry — O Docker registry é um repositório centralizado para imagens Docker. Ele permite que você puxe imagens do registry e envie suas próprias imagens. Além dos outros componentes da arquitetura, o Docker também depende de outros: Imagem — modelo somente leitura que contém tudo o que é necessário para executar um aplicativo (código, runtime, bibliotecas e ferramentas do sistema). Você pode aproveitar as imagens criadas por outros, ou tem a capacidade de criar as suas próprias. Contêiner — instância de uma imagem que você pode executar, iniciar, parar e excluir. Eles são isolados uns dos outros e do sistema hospedeiro, garantindo que os aplicativos sejam executados em um ambiente consistente. Você pode facilmente criar vários contêineres a partir da mesma imagem.

Imagens Docker e Contêineres Docker

Para prosseguir neste guia, vamos explicar sobre as imagens e contêineres do Docker, explicando melhor os dois principais componentes do sistema.

O que é uma Imagem Docker?

Uma imagem Docker é um modelo que será usado por seus contêineres, no qual você instala todos os pacotes necessários para executar seus aplicativos. Agindo como blueprints para seus contêineres Docker, uma imagem Docker é composta de múltiplas camadas somente leitura, empilhadas umas sobre as outras. Cada uma dessas camadas é uma instrução em seu Dockerfile, e essas camadas podem conter informações diferentes: você pode ter uma camada que especifica a imagem base a partir da qual você está construindo sua imagem, ou você pode ter outra camada que instala algumas dependências que são necessárias para o seu aplicativo, ou uma camada que simplesmente copia alguns arquivos do seu sistema de arquivos local para sua imagem Docker.

Independentemente da infraestrutura subjacente (tendo o Docker instalado em diferentes sistemas operacionais), você pode ter 100% de certeza de que sua imagem será executada nele se o Docker estiver instalado (pequena ressalva, a arquitetura da sua imagem deve corresponder à arquitetura do sistema hospedeiro). Construir essas imagens em camadas significa que o Docker pode reutilizar as camadas para acelerar o processo de construção para a imagem atual que você está usando e até mesmo reutilizar essas camadas em diferentes imagens que você pode estar construindo. É por isso que, para acelerar as coisas, você deve evitar fazer alterações em camadas superiores, pois o caching será quebrado. Por padrão, o caching está habilitado, mas isso não significa que você não possa construir uma imagem sem reutilizar as informações em cache. Em alguns casos, você pode querer fazer isso, e há um argumento que vem a calhar que permite que você faça isso, e esse é o argumento --no-cache.

O que é um Contêiner Docker?

Um contêiner Docker é um elemento criado a partir de uma imagem Docker que se encaixa no propósito que você definiu dentro dessa imagem em particular. Como as imagens Docker são apenas blueprints, elas não fazem nada por conta própria e precisam ser usadas dentro de um contêiner para realizar a tarefa em questão. Os contêineres Docker são executados em seus próprios ambientes, isolados, o que significa que são separados uns dos outros e até mesmo do sistema hospedeiro. Cada um desses contêineres tem seus sistemas de arquivos, processos que estão sendo executados e rede, enquanto ainda compartilham o kernel do sistema operacional.

Como mencionado no artigo anterior, esta é uma das principais diferenças entre contêineres e máquinas virtuais, então não se esqueça de tomar nota. Os contêineres são mais leves quando comparados com suas contrapartes de máquina virtual, e são projetados para serem efêmeros. Você pode facilmente iniciar, parar e destruir contêineres e todos os seus dados podem ser perdidos se os dados não forem explicitamente armazenados fora dele (em um volume Docker, ou as informações relevantes podem ser enviadas para diferentes soluções de armazenamento, como Amazon S3 ou Azure Blob storage). Os contêineres Docker são flexíveis e os tornam uma escolha ideal para aplicativos de microsserviços porque você pode escaloná-los juntos ou independentemente, ou diretamente em plataformas de orquestração de contêineres como Kubernetes ou Docker Swarm.

Como já mencionado, você pode facilmente usar imagens Docker existentes e criar contêineres a partir delas. O Docker tem uma maneira interessante de verificar se você tem uma imagem localmente, caso contrário, ele irá puxá-la do Docker Hub registry. Para puxar uma imagem, podemos usar o comando docker pull image_name. Para este exemplo, vamos puxar a imagem hello-world e criar um contêiner a partir dela:

docker pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
478afc919002: Pull complete 
Digest: sha256:53cc4d415d839c98be39331c948609b659ed725170ad2ca8eb36951288f81b75
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest

Agora, vamos criar o contêiner:

docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Para enviar uma imagem para um registry, você pode executar o comando docker push image_name. Para listar suas imagens, você pode simplesmente executar o comando docker images:

docker images         
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
kindest/node   <none>    c67167dbf296   3 months ago     980MB
hello-world    latest    ee301c921b8a   16 months ago    9.14kB

Para remover uma imagem local, você pode simplesmente executar docker image rm image_name ou docker image rm first_few_letters_of_id:

docker image rm ee
Untagged: hello-world:latest
Untagged: hello-world@sha256:53cc4d415d839c98be39331c948609b659ed725170ad2ca8eb36951288f81b75
Deleted: sha256:ee301c921b8aadc002973b2e0c3da17d701dcd994b606769a7e6eaa100b81d44
Deleted: sha256:12660636fe55438cc3ae7424da7ac56e845cdb52493ff9cf949c47a7f57f8b43
➜  episode2 docker images     
REPOSITORY     TAG       IMAGE ID       CREATED          SIZE
kindest/node   <none>    c67167dbf296   3 months ago     980MB

O que é um Dockerfile?

Um Dockerfile é um documento especial que contém instruções para construir uma imagem Docker. É essencialmente um script de comandos que o Docker usa para criar automaticamente uma imagem de contêiner. O Dockerfile suporta as seguintes instruções, e listaremos em ordem de importância (do ponto de vista do autor do texto original):

  • FROM — isto está criando um novo estágio de construção, começando de uma imagem base.
  • RUN — executa diferentes comandos dentro da imagem base que você está usando. Você pode ter vários comandos em uma única instrução RUN, usando “&&”.
  • CMD — o comando padrão que o contêiner Docker irá executar.
  • ENTRYPOINT — especifica o executável padrão.
  • EXPOSE — portas que seu aplicativo está escutando.
  • ADD — adiciona arquivos do sistema hospedeiro, URLs e também pode adicionar arquivos e extraí-los.
  • COPY — adiciona arquivos apenas do sistema hospedeiro.
  • ARG — variável de tempo de construção que pode ser usada em outras instruções.
  • ENV — define variáveis de ambiente dentro do contêiner Docker.
  • WORKDIR — define o diretório de trabalho para quaisquer outros comandos que possam ser executados após ele.
  • VOLUME — cria um ponto de montagem com o caminho especificado.
  • SHELL — define o shell.
  • USER — define o usuário.
  • HEALTHCHECK — define um comando para testar a saúde do contêiner.
  • STOPSIGNAL — define o sinal de chamada do sistema para sair de um contêiner.
  • ONBUILD — isto definirá uma instrução para a imagem quando ela for usada como uma imagem base para outra.
  • LABEL — adiciona metadados à imagem em um formato de chave-valor.
  • MAINTAINER — obsoleto em favor de LABEL, era usado para especificar o mantenedor da imagem.

Em entrevistas, é comum perguntarem qual é a diferença entre ADD e COPY. É importante lembrar que COPY pode ser usado apenas para copiar arquivos do sistema de arquivos hospedeiro, enquanto ADD também pode obter arquivos de uma URL ou descompactar arquivos. Também podem perguntar sobre a diferença entre CMD e ENTRYPOINT. CMD é usado para fornecer argumentos padrão para o executável do contêiner, enquanto ENTRYPOINT define o próprio executável. Se você definir CMD e não definir ENTRYPOINT, o que acontece é que CMD atua como o ENTRYPOINT.

Tutorial Dockerfile

Suponha que você receba o seguinte ticket: “Crie uma imagem Docker que padronize o processo de desenvolvimento da nossa equipe. Como um engenheiro DevOps, eu quero construir um ambiente de desenvolvimento padrão para minha equipe, para que possamos garantir que todos desenvolvam seu código com as mesmas versões”. A descrição é que a imagem deve ter o seguinte: iniciar a partir de uma imagem Alpine, versão mais recente de código aberto do Terraform instalada, OpenTofu 1.8.1, Python 3.12 e pip, kubectl 1.28, Ansible 2.15 e Golang 1.21.

O critério de aceitação é que um Dockerfile seja criado que construa a imagem com todas as ferramentas especificadas e suas versões. A imagem é construída com sucesso e testada para garantir que todas as ferramentas funcionem corretamente. É fornecida documentação sobre como usar a imagem. Vamos começar com uma versão específica de Alpine, e você pode se perguntar por que não estamos usando a palavra-chave “latest“. Isso acontece porque, em uma nova versão, podemos enfrentar alguns problemas de dependência ou mudanças inesperadas que podem quebrar sua construção de imagem. É uma prática recomendada evitar o uso de “latest” para qualquer coisa que você esteja construindo porque, desta forma, você garante a consistência.

FROM alpine:3.20

No exemplo acima, estamos especificando a imagem base como Alpine:3.20. Agora, não recebemos instruções exatas sobre qual versão do Terraform usar, mas sabemos que temos que usar a versão de código aberto mais recente. Após alguma pesquisa em seu repositório, descobrimos que a versão de código aberto mais recente é 1.5.7.

Agora, estamos prontos para definir nosso ambiente com todas as versões que queremos usar. Definimos elas dentro de um bloco ENV porque queremos ser capazes de atualizar facilmente as versões quando isso for necessário no futuro. Também definimos o diretório bin pipx para algo em nosso caminho. Isso será necessário para instalar facilmente o Ansible.

ENV TERRAFORM_VERSION=1.5.7 \
    OPENTOFU_VERSION=1.8.1 \
    PYTHON_VERSION=3.12.0 \
    KUBECTL_VERSION=1.28.0 \
    ANSIBLE_VERSION=2.15.0 \
    GOLANG_VERSION=1.21.0 \ 
    PIPX_BIN_DIR=/usr/local/bin

Em seguida, vamos instalar algumas das dependências e alguns dos ajudantes que você pode precisar para um ambiente de desenvolvimento bem-sucedido:

RUN apk add --no-cache \
    curl \
    bash \
    git \
    wget \
    unzip \
    make \
    build-base \
    py3-pip \
    pipx \
    openssh-client \
    gnupg \
    libc6-compat

Agora, vamos adicionar as instruções que instalam o Terraform:

RUN wget -O terraform.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \
    unzip terraform.zip && \
    mv terraform /usr/local/bin/ && \
    rm terraform.zip

Estamos primeiro baixando o arquivo Terraform, então estamos descompactando-o, em seguida, estamos movendo o executável em nosso caminho e, no final, estamos removendo o arquivo. Faremos o mesmo processo para OpenTofu:

RUN wget -O tofu.zip https://github.com/opentofu/opentofu/releases/download/v${OPENTOFU_VERSION}/tofu_${OPENTOFU_VERSION}_linux_amd64.zip && \
    unzip tofu.zip && \
    mv tofu /usr/local/bin/ && \
    rm tofu.zip

Em seguida, vamos instalar o kubectl:

RUN curl -LO "https://dl.k8s.io/release/v$KUBECTL_VERSION/bin/linux/amd64/kubectl" && \
    chmod +x kubectl && \
    mv kubectl /usr/local/bin/

Isso fará o download do binário kubectl, torná-lo executável e, em seguida, movê-lo para o caminho. Agora, vamos instalar o Ansible:

RUN pipx install ansible-core==${ANSIBLE_VERSION}

Estamos finalmente prontos para instalar a última ferramenta, golang:

RUN wget https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz && \
    tar -C /usr/local -xzf go$GOLANG_VERSION.linux-amd64.tar.gz && \
    rm go$GOLANG_VERSION.linux-amd64.tar.gz && \
    ln -s /usr/local/go/bin/go /usr/local/bin/go && \
    ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt

Da mesma forma, estamos baixando o arquivo, descompactando-o, mas agora estamos criando alguns symlinks para garantir que o go esteja em nosso PATH. Vamos também definir um workdir. Quando executarmos nosso contêiner, este será nosso diretório inicial:

WORKDIR /workspace

Também devemos adicionar o comando que queremos que nosso Dockerfile execute:

CMD ["bash"]

No final, seu Dockerfile deve ter esta aparência:

FROM alpine:3.20

ENV TERRAFORM_VERSION=1.5.7 \
    OPENTOFU_VERSION=1.8.1 \
    PYTHON_VERSION=3.12.0 \
    KUBECTL_VERSION=1.28.0 \
    ANSIBLE_VERSION=2.15.0 \
    GOLANG_VERSION=1.21.0 \ 
    PIPX_BIN_DIR=/usr/local/bin

RUN apk add --no-cache \
    curl \
    bash \
    git \
    wget \
    unzip \
    make \
    build-base \
    py3-pip \
    pipx \
    openssh-client \
    gnupg \
    libc6-compat

RUN wget -O terraform.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \
    unzip terraform.zip && \
    mv terraform /usr/local/bin/ && \
    rm terraform.zip

RUN wget -O tofu.zip https://github.com/opentofu/opentofu/releases/download/v${OPENTOFU_VERSION}/tofu_${OPENTOFU_VERSION}_linux_amd64.zip && \
    unzip tofu.zip && \
    mv tofu /usr/local/bin/ && \
    rm tofu.zip

RUN curl -LO "https://dl.k8s.io/release/v$KUBECTL_VERSION/bin/linux/amd64/kubectl" && \
    chmod +x kubectl && \
    mv kubectl /usr/local/bin/

RUN pipx install ansible-core==${ANSIBLE_VERSION}

RUN wget https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz && \
    tar -C /usr/local -xzf go$GOLANG_VERSION.linux-amd64.tar.gz && \
    rm go$GOLANG_VERSION.linux-amd64.tar.gz && \
    ln -s /usr/local/go/bin/go /usr/local/bin/go && \
    ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt

WORKDIR /workspace

CMD ["bash"]

Agora, vamos para o diretório que contém nosso Dockerfile e construir a imagem:

docker build -t dev_image:1.0.0 .
[+] Building 38.2s (8/11)                                                                                                                          docker:desktop-linux
[+] Building 48.1s (12/12) FINISHED                                                                                                                docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                               0.0s
 => => transferring dockerfile: 1.46kB                                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/alpine:3.20                                                                                                     0.5s
 => [internal] load .dockerignore                                                                                                                                  0.0s
 => => transferring context: 2B                                                                                                                                    0.0s
 => CACHED [1/8] FROM docker.io/library/alpine:3.20@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5                                        0.0s
 => [2/8] RUN apk add --no-cache     curl     bash     git     wget     unzip     make     build-base     py3-pip     pipx     openssh-client     gnupg     libc  17.3s 
 => [3/8] RUN wget -O terraform.zip https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip &&     unzip terraform.zip &&     mv terraform  2.7s 
 => [4/8] RUN wget -O tofu.zip https://github.com/opentofu/opentofu/releases/download/v1.8.1/tofu_1.8.1_linux_amd64.zip &&     unzip tofu.zip &&     mv tofu /usr  4.1s 
 => [5/8] RUN curl -LO "https://dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl" &&     chmod +x kubectl &&     mv kubectl /usr/local/bin/                       5.8s 
 => [6/8] RUN pipx install ansible-core==2.15.0                                                                                                                    7.8s 
 => [7/8] RUN wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz &&     tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz &&     rm go1.21.0.linux-amd64.tar  9.2s 
 => [8/8] WORKDIR /workspace                                                                                                                                       0.0s 
 => exporting to image                                                                                                                                             0.5s 
 => => exporting layers                                                                                                                                            0.5s 
 => => writing image sha256:23fe925c0eb2e0931bc86f592373bcd13916e6dbbb4ce74b18fff846fb8f2f4d                                                                       0.0s 
 => => naming to docker.io/library/dev_image:1.0.0                                                                                                                 0.0s 

What's next:
    View a summary of image vulnerabilities and recommendations → docker scout quickview

A flag “-t” do comando docker build, permite especificar a imagem :. Vamos ver nossa imagem recém-criada:

docker images
REPOSITORY     TAG       IMAGE ID       CREATED         SIZE
dev_image      1.0.0     23fe925c0eb2   7 minutes ago   783MB

Agora, vamos criar um contêiner a partir de nossa imagem e verificar todas as versões de imagem para ver se atendemos aos critérios de aceitação que temos em nosso ticket:

docker run -ti dev_image:1.0.0
062c8343eef7:/workspace#

Essas duas opções combinadas (“-ti”), permitem executar um contêiner interativamente com um terminal anexado. Isso é especialmente útil para executar um shell dentro do contêiner, para que você possa executar comandos diretamente dentro do contêiner, como gostaríamos de fazer com isso. Vamos verificar as versões de nossas ferramentas:

Agora, atendemos a duas de três coisas relacionadas aos nossos critérios de aceitação, e acho que a documentação pode ser facilmente escrita a partir de todos os detalhes fornecidos acima, então podemos dizer que este ticket pode ser movido para revisão. No mundo real, você provavelmente vai querer aproveitar um editor para editar seu código e executá-lo a partir do contêiner Docker. Você também gostaria de dar um nome ao seu contêiner, então vamos fazer isso. A maneira mais fácil de fazer isso é quando você está criando assim:

docker run -ti --name dev_container2 -v ~/Workspace:/workspace dev_image:1.0.0

Este comando irá vincular o diretório do hospedeiro Workspace da casa do meu usuário para /workspace. Se eu criar um contêiner desta forma, eu serei redirecionado para meu workspace onde eu tenho todo meu código. Por que estou excluindo os arquivos da imagem quando estava criando ela? A razão é bem simples, eu queria fazer a imagem tão pequena quanto possível para mantê-la portátil.

Gerenciando contêineres Docker

Depois de aprender sobre as imagens e os arquivos Docker, é essencial saber como fazer o gerenciamento dos contêineres dentro do sistema.

Listando contêineres

Podemos listar contêineres com o comando docker ps, mas isso sozinho só mostrará os contêineres que estão em execução:

docker ps                                                                     
CONTAINER ID   IMAGE                  COMMAND                  CREATED       STATUS       PORTS                       NAMES
8315e81fd8e6   kindest/node:v1.30.0   "/usr/local/bin/entr…"   2 weeks ago   Up 9 hours   127.0.0.1:53925->6443/tcp   my-cluster-control-plane

Se você quiser ver todos os seus contêineres existentes, você pode executar docker ps -a:

docker ps -a
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS                     PORTS                       NAMES
d6ae4b01f9de   dev_image:1.0.0        "bash"                   5 minutes ago    Exited (0) 5 minutes ago                               dev_container2
ad38f4f944e8   dev_image:1.0.0        "bash"                   5 minutes ago    Exited (0) 5 minutes ago                               dev_container
062c8343eef7   dev_image:1.0.0        "bash"                   16 minutes ago   Exited (0) 7 minutes ago                               mystifying_bhaskara
8315e81fd8e6   kindest/node:v1.30.0   "/usr/local/bin/entr…"   2 weeks ago      Up 9 hours                 127.0.0.1:53925->6443/tcp   my-cluster-control-plane

Iniciando um contêiner

Este é um processo muito simples, você pode simplesmente executar docker start container_name ou docker start first_few_letters_of_id:

episode2 docker start d6
d6
➜  episode2 docker ps      
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS                       NAMES
d6ae4b01f9de   dev_image:1.0.0        "bash"                   7 minutes ago   Up 2 seconds                               dev_container2
8315e81fd8e6   kindest/node:v1.30.0   "/usr/local/bin/entr…"   2 weeks ago     Up 9 hours     127.0.0.1:53925->6443/tcp   my-cluster-control-plane

Anexando a um contêiner

Você iniciou seu contêiner de desenvolvimento, mas como você pode usá-lo? Bem, você precisa anexar a ele. O comando é docker attach container_name ou docker attach first_few_letters_of_id:

episode2 docker attach d6
d6ae4b01f9de:/workspace#

Parando um contêiner

Semelhante ao início, este é um processo muito simples, você pode simplesmente executar docker stop container_name ou docker stop first_few_letters_of_id:

episode2 docker start d6 
d6
➜  episode2 docker ps       
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS         PORTS                       NAMES
d6ae4b01f9de   dev_image:1.0.0        "bash"                   11 minutes ago   Up 5 seconds                               dev_container2
8315e81fd8e6   kindest/node:v1.30.0   "/usr/local/bin/entr…"   2 weeks ago      Up 9 hours     127.0.0.1:53925->6443/tcp   my-cluster-control-plane
➜  episode2 docker stop d6 
d6
➜  episode2 docker ps     
CONTAINER ID   IMAGE                  COMMAND                  CREATED       STATUS       PORTS                       NAMES
8315e81fd8e6   kindest/node:v1.30.0   "/usr/local/bin/entr…"   2 weeks ago   Up 9 hours   127.0.0.1:53925->6443/tcp   my-cluster-control-plane

Removendo contêineres

Para remover um contêiner, você simplesmente executará docker rm container_name ou docker rm first_few_letters_of_id:

docker rm d6
d6
➜ episode2 docker ps -a
CONTAINER

Leave a Comment