User Tools

Site Tools


wiki:docker:docker_images_management

Gerenciando Imagens no Docker

Imagens do Docker

Imagens do Docker são arquivos binários que contém todas as ferramentas necessárias para executar uma aplicação dentro de um recipiente. Cada imagem é criada a partir de uma conjunto de camadas, sendo que cada camada representa um comando ou um arquivo modificado no aplicativo. As camadas são agrupadas em um único arquivo chamado de Dockerfile.

Diferença entre um container e uma imagem Docker

Uma das principais diferenças entre um container e uma imagem Docker é que os containers são instâncias de imagens Docker. Isso significa que os containers são cópias de uma imagem Docker que podem se executadas com um processo independente. Além disso, as imagens Docker são imutáveis, o que significa que não podem ser alteradas depois de serem criadas. Por outro lado, os containers são mutáveis, o que significa que podem se alterados depois de serem criados.

Camadas de imagens

Todas as gravaçõesno container que adicionan novos dados ou modificam dados existentes, são armazenadas nessa camada gravável. Quando um container é excluido, a camada gravável tembém é excluida.

Camadas Lógicas

Existem duas camadas lógicas de um container, a camada de leitura e a camadade escrita. Todos os containers têm duas camadas. No entanto, apenas um dos containers pode se a camada de escrita e os outros contêm camadas de leitura.

Docker Hub

Docker Hub é uma plataforma online para compartilhamento e criação de imagens Docker. É um repositório de imagens públicas e privadas, e é o lugar onde os usuários do Docker compartilham e gerenciam suas imagens. As imagens do Docker Hub podem se usadas como modelos para criar novas imagens.

Criar conta no Docker Hub

Para criar uma conta no Docker Hub, acesse a página: Docker Hub

Testar acesso a conta do Docker Hub

Após criar a conta, execute o comando para logar no Docker Hub:

docker login -u user_docker_hub <TECLE ENTER>
Password: senha_docker_hub

Verifique se um arquivo de autorização foi criado:

cat ~/.docker/config.json
{
}
    "auths": {
       "https://index.docker.io/v1/": {
          "auth": "o_hash_da_senha_do_usuario_docker_hub"
       },
    },
    "HttpHeaders": {
        "User-Agent": "Docker-Client/19.03.11 (linux)"
     }
}

Para encerrar o login da conta do Docker Hub, execute o comando:

docker logout

Gerenciamento de imagens no Docker

Comandos iniciais

Liste as imagens e verifique o histórico de comandos utilizados para sua construção:

docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    7f553e8bbc89   3 days ago     192MB
busybox      latest    27a71e19c956   9 days ago     4.27MB
httpd        latest    5daf6a4bfe74   2 months ago   148MB
docker image history nginx
IMAGE          CREATED      CREATED BY                                      SIZE      COMMENT
7f553e8bbc89   3 days ago   CMD ["nginx" "-g" "daemon off;"]                0B        buildkit.dockerfile.v0
<missing>      3 days ago   STOPSIGNAL SIGQUIT                              0B        buildkit.dockerfile.v0
<missing>      3 days ago   EXPOSE map[80/tcp:{}]                           0B        buildkit.dockerfile.v0
<missing>      3 days ago   ENTRYPOINT ["/docker-entrypoint.sh"]            0B        buildkit.dockerfile.v0
<missing>      3 days ago   COPY 30-tune-worker-processes.sh /docker-ent…   4.62kB    buildkit.dockerfile.v0
<missing>      3 days ago   COPY 20-envsubst-on-templates.sh /docker-ent…   3.02kB    buildkit.dockerfile.v0
<missing>      3 days ago   COPY 15-local-resolvers.envsh /docker-entryp…   389B      buildkit.dockerfile.v0
<missing>      3 days ago   COPY 10-listen-on-ipv6-by-default.sh /docker…   2.12kB    buildkit.dockerfile.v0
<missing>      3 days ago   COPY docker-entrypoint.sh / # buildkit          1.62kB    buildkit.dockerfile.v0
<missing>      3 days ago   RUN /bin/sh -c set -x     && groupadd --syst…   117MB     buildkit.dockerfile.v0
<missing>      3 days ago   ENV DYNPKG_RELEASE=1~bookworm                   0B        buildkit.dockerfile.v0
<missing>      3 days ago   ENV PKG_RELEASE=1~bookworm                      0B        buildkit.dockerfile.v0
<missing>      3 days ago   ENV NJS_RELEASE=1~bookworm                      0B        buildkit.dockerfile.v0
<missing>      3 days ago   ENV NJS_VERSION=0.8.6                           0B        buildkit.dockerfile.v0
<missing>      3 days ago   ENV NGINX_VERSION=1.27.2                        0B        buildkit.dockerfile.v0
<missing>      3 days ago   LABEL maintainer=NGINX Docker Maintainers <d…   0B        buildkit.dockerfile.v0
<missing>      9 days ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      9 days ago   /bin/sh -c #(nop) ADD file:a9a95cfab16803be0…   74.8MB

Inspecionando uma imagem:

docker image inspect nginx
[
    {
        "Id": "sha256:7f553e8bbc897571642d836b31eaf6ecbe395d7641c2b24291356ed28f3f2bd0",
        "RepoTags": [
            "nginx:latest"
        ],
        "RepoDigests": [
            "nginx@sha256:d2eb56950b84efe34f966a2b92efb1a1a2ea53e7e93b94cdf45a27cf3cd47fc0"
        ],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2024-10-02T17:55:35Z",
        "DockerVersion": "",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "NGINX_VERSION=1.27.2",
                "NJS_VERSION=0.8.6",
                "NJS_RELEASE=1~bookworm",
                "PKG_RELEASE=1~bookworm",
                "DYNPKG_RELEASE=1~bookworm"
            ],
            "Cmd": [
                "nginx",
                "-g",
                "daemon off;"
            ],
            "ArgsEscaped": true,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": [
                "/docker-entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
                "maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
            },
            "StopSignal": "SIGQUIT"
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 191670478,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/9e3035a82c04e43e25c36d1b4373771eb8d0daf1007330d5a5e58c3ac424437e/diff:/var/lib/docker/overlay2/bf258a85b3f8a0d031d09f30d8649ceab8bd91730dff839f96d8bc5965fcb08e/diff:/var/lib/docker/overlay2/0493cb757dad4fd38fd14170ce5a86eb9f2e574c0e04e64c0a8f709e2f60f5f2/diff:/var/lib/docker/overlay2/2f6b485a59fa43f8e6e9b80f0d9a773b5eaf50bf4cff7f690d5f5c081ad25f88/diff:/var/lib/docker/overlay2/d4ec436d53a293abd36de76608ce84b6a0076d1f618d8b6c0741e68b662d5e26/diff:/var/lib/docker/overlay2/7e5c8ab7790a56d50dbf267e2c5413ab74b31c09eba48e53cf7a56b370d31f2b/diff",
                "MergedDir": "/var/lib/docker/overlay2/ba3cc15f18ab4010226d49b4a220657f8edb8ef02280747d13a104b8ba5478ab/merged",
                "UpperDir": "/var/lib/docker/overlay2/ba3cc15f18ab4010226d49b4a220657f8edb8ef02280747d13a104b8ba5478ab/diff",
                "WorkDir": "/var/lib/docker/overlay2/ba3cc15f18ab4010226d49b4a220657f8edb8ef02280747d13a104b8ba5478ab/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:8d853c8add5d1e7b0aafc4b68a3d9fb8e7a0da27970c2acf831fe63be4a0cd2c",
                "sha256:756474215d2903298a97a89b17f234450ca3a7219cae4dd63800afe9b350052f",
                "sha256:3d07a4a7eb2aaf0068689502ddeebce2c379a25f42b33837a21dc5b539efc3a4",
                "sha256:6b133b4de5e62775fe5eabdaa6adb4a6092880d245c87db08328117fd6e4ac51",
                "sha256:1c1f11fd65d69317e2fec888cd90ddff07b7106ac55c32163cbe8876bb381cb5",
                "sha256:7619c0ba3c92e5c80cfdb021261bb0b93be94bb7e56d2cd6ee1f94449a020032",
                "sha256:825fb68b603345fb0c5d2436998e848cdfdcf5642d3c403204ed9fd833ee4080"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

Criando uma nova imagem a partir das alterações feitas em um container:

docker image pull debian
docker container run -dit --name c1-debian debian
docker container exec c1-debian apt-get update
docker container exec c1-debian apt-get install nginx -y

Criando a nova imagem:

docker commit c1-debian c2-web
docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
c2-web       latest    983baca7d68b   25 seconds ago   153MB
nginx        latest    7f553e8bbc89   3 days ago       192MB
debian       latest    c7f9867d6721   9 days ago       117MB
busybox      latest    27a71e19c956   9 days ago       4.27MB
httpd        latest    5daf6a4bfe74   2 months ago     148MB

Inspecione a nova imagem:

docker image inspect c2-web
[
    {
        "Id": "sha256:983baca7d68b2258fda2be0289a1965798c85597a7a3dcf319402b8255382ef5",
        "RepoTags": [
            "c2-web:latest"
        ],
        "RepoDigests": [],
        "Parent": "sha256:c7f9867d67219411cb7dff983c83eddb881d415eae5495ad9116fb5d6db8bb60",
        "Comment": "",
        "Created": "2024-10-06T14:21:03.875819968Z",
        "DockerVersion": "27.3.1",
        "Author": "",
        "Config": {
            "Hostname": "70cf4fd07bdb",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "bash"
            ],
            "Image": "debian",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 153392789,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/38f00b683217a1fe3ac8020e0bdfd6ec521649fe6652a6d726f4bdc0e0813e10/diff",
                "MergedDir": "/var/lib/docker/overlay2/b99bc1a43aacfb3c1421aac6e40c90aebc8ff9c4503aa70db82f88dd73be135d/merged",
                "UpperDir": "/var/lib/docker/overlay2/b99bc1a43aacfb3c1421aac6e40c90aebc8ff9c4503aa70db82f88dd73be135d/diff",
                "WorkDir": "/var/lib/docker/overlay2/b99bc1a43aacfb3c1421aac6e40c90aebc8ff9c4503aa70db82f88dd73be135d/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:d50132f2fe78aaa8e67f229e53305d0c4a7a86c9deda4bf3160be0a678926458",
                "sha256:48fc1e454263cd3ff48307f0603d15faf5606be4e4ef2567e20daf0e6369710d"
            ]
        },
        "Metadata": {
            "LastTagTime": "2024-10-06T14:21:03.88412007Z"
        }
    }
]

Backup e Restore de Imagens

Salvando uma imagem:

docker image save c2-web -o img-c2-web.tar
<code bash>

du -sch img-c2-web.tar 152M img-c2-web.tar 152M total </code>

Remova o container c1-debian e apenas a imagem c2-web:

docker container rm -f c1-debian
c1-debian
docker image rm -f c2-web
Untagged: c2-web:latest
Deleted: sha256:983baca7d68b2258fda2be0289a1965798c85597a7a3dcf319402b8255382ef5
Deleted: sha256:0012f89cc28c990921b2ec045b91d065c9e5964729a2400dff113a75e55bc0cc
docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    7f553e8bbc89   3 days ago     192MB
debian       latest    c7f9867d6721   9 days ago     117MB
busybox      latest    27a71e19c956   9 days ago     4.27MB
httpd        latest    5daf6a4bfe74   2 months ago   148MB

Para remover imagens não utilizadas, execute o seguinte comando:

docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] yes

Carregue a imagem c2-web a partir do arquivo tar, e inicie o container c2-web utilizando a nova imagem:

docker image load -i img-c2-web.tar 
48fc1e454263: Loading layer [==================================================>]  37.33MB/37.33MB
Loaded image: c2-web:latest
docker image ls c2-web
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
c2-web       latest    983baca7d68b   20 minutes ago   153MB

Execute o container e em seguida a aplicação nginx através da imagem restaurada:

docker container run -tid --name=c2-web --hostname=c2-web -p 80:80 c2-web
1f3da5b0c82681ded84fb4e017eeaa296346286da61aa66fa814980e10e1f277
docker container exec -ti c2-web nginx
curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
 
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
 
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
docker container rm -f c2-web
c2-web

Dockerfile

Dockerfile é um arquivo de texto que contém um conjunto de instruções que serão usadas para criar um imagem Docker. Essas intruções podem incluir tarefas como a instalação de software e bibliotacas, configurar o ambiente de execução e copiar arquivos para a imagem.

Instruções do arquivo Dockerfile

  • FROM
  • ENV
  • RUN
  • WORDIR
  • EXPOSE
  • ENTRYPOINT
  • CMD

Dockerfile - FROM

O comando FROM é utilizado para definir a imagem base a qual será criada a nova imagem. Exemplo:

FROM: ubuntu:22:04

Dockerfile - ENV

O comando ENV é utilizado para definir variáveis de ambiente que serão acessíveis a todos os comandos definidos no Dockerfile.

Exemplo:

FROM ubuntu:22:04
ENV VARIAVEL=valor-da-variavel

Dockerfile - RUN

O comando RUN é utilizado para executar comandos que irão alterar o estado da imagem.

Exemplo:

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y vim

Dockerfile - WORKDIR

O comando WORKDIR é utilizado para definir o diretório de trabalho.

Exemplo:

FROM ubuntu:22:04
RUN mkdir /app
WORKDIR /app

Dockerfile - EXPOSE

O comando EXPOSE é utilizado para indicar qual porta será exposta para o conatiner

Exemplo:

FROM ubuntu:22.04
EXPOSE 3306

Dockerfile - ENTRYPOINT

O comando ENTRYPOINT é utilizado para executar um comando quando o um container é criado.

Exemplo:

FROM ubuntu:22.04
ENTRYPOINT ["/bin/bash"]

Dockerfile - CMD

O comando CMD é utilizado para executar um comando quando for criado.

Exemplo:

FRON ubuntu:22.04
CMD ["/bin/bash"]

Otimizando a criação de imagens Docker

Otimização de imagens Docker é a arte de manter as suas imagens peguenas, leves e rápidas, fazendo com que o uso do Docker seja o mais eficiente possível em relação ao sistema de arquivos de host, RAM, CPU e rede.

Dicas para otimizar as imagens Docker

  • Usar um Gerenciador de Pacotes para evitar baixar arquivos repetidamente;
  • Limpar arquivos temporários e não necessários;
  • Usar um gerenciador de cache de imagens;
  • Usar a imagem Alpine para manter as imagens pequenas;
  • Usar multi-stage builds para separar as fases de build e execução;
  • Considere automatizar a criação de imagens Docker.

Usar um gerenciador de pacotes para evitar baixar arquivos repetidamente

  • Uma das melhores maneiras de evitar que as imagens Docker fiquem muito grandes é evitar que os arquivos sejam baixados repetidamente.
  • Isso pode ser feito usando um gerenciador de pacotes como o apt ou o yum.
  • Para usar o apt, você precisa criar um arquivo chamado Dockerfile e adicionar as seguintes linhas:
FROM ubuntu
 
RUN apt-get update && \
    apt-get install -y \
    curl \
    wget \
    && rm -rf /var/lib/apt/lists/*

Para usar o yum, você precisa criar um arquivo Dockerfile e adicionar as seguintes linhas:

FROM centos:7
RUN yum update -y && \
    yum install -y \
    curl \
    wget \
    && yum clean all

Limpar arquivos temporários e não necessários

  • Uma outra maneira de evitar que as imagens Docker fiquem muito grandes é remover arquivos temporários e não necessários.
  • Isso pode ser feito usando os comandos rm e rmdir.
  • Para usar o rm, você precisa criar um arquivo chamado Dockerfile e adicionar as seguintes linhas:
FROM ubuntu
RUN rm -rf /tmp/*
FROM centos:7
RUN rmdir /tmp

Usar um gerenciador de cache de imagens

  • Outra maneira de evitar que as imagens Docker fiquem muito grandes é usar um gerenciador de cache de imagens.
  • Isso pode ser feito usando um gerenciador de cache de imagens como o Docker Hub.
  • Para usar o Docker Hub, você precisa criar um arquivo chamado Dockerfile e adicionar as seguintes linhas:
FROM ubuntu
RUN wget -O - https://hub.docker.com/r/library/ubuntu/ > /etc/apt/sources.list
RUN apt-get update && \
    apt-get install -y \
    curl \
    wget \
    && rm -rf /var/lib/apt/lists/*

Usar a imagem Alpine para manter as imagens pequenas

  • Outra maneira de evitar que as imagens Docker fiquem muito grandes é usar uma imagem Alpine.
  • A Alpine é uma imagem Docker extremamente leve que contém apenas o necessário para executar aplicativos.
  • Para usar a Alpine, você precisa criar um arquivo chamado Dockerfile e adicionar as seguintes linhas:
FROM alpine:3.7
RUN apk update && \
    apk add \
    curl \
    wget \
    && rm -rf /var/cache/apk/*

Usar multi-stage builds para separar as fases de build e execução

  • Multi-stage builds são um recurso do Docker que permitem que você crie uma imagem Docker em várias etapas.
  • Isso é útil para separar as fases de build e execução.
  • Para usar multi-stage builds, você precisa criar um arquivo chamado Dockerfile e adicionar as seguintes linhas:
# Fase de build
FROM golang:1.9-alpine AS build
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o app
 
# Fase de execução
FROM alpine:3.7
RUN mkdir /app
WORKDIR /app
COPY --from=build /app/app .
CMD ["./app"]
  • No exemplo acima, a primeira etapa é criada a partir da imagem golang:1.9-alpine e é usada para compilar o código fonte em um executável chamado app.
  • A segunda etapa é criada a partir da imagem alpine:3.7 e é usada para copiar o executável app para a imagem e executá-lo.

Considere automatizar a criação de imagens Docker

  • A automação da criação de imagens Docker pode ser feita usando um sistema de inte gração e entrega contínua (CI/CD).
  • Isso é útil para garantir que as imagens sejam criadas com frequência, pois você sempre terá uma imagem atualizada.
  • Algumas ferramentas que podem ser usadas para automatizar a criação de imagens Docker são o Jenkins, o CircleCI e o Travis CI.

Melhorar segurança de imagens

  • Alguns ajustes são necessários para melhorar a segurança nas imagens do Docker.
  • Adicionar compilação de vários estágios para diminuir o tamanho da imagem;
  • Utilizar uma tag para definir a versão da imagem;
  • Remover permissão de escrita do diretório /etc;
  • Adicionar usuário e grupo;
  • Remover todos os binários do diretório /bin;
  • Executar o container com usuário regular sem permissão de root;
  • Definir que a pasta em que a aplicação será executada seja a pasta do usuário regular.

Melhorando a segurança de imagens no Docker

Construir imagem sem ajustes de segurança

# cat Dockerfile 
FROM ubuntu
ARG DEBIAN_FRONTEND=noninteractive
 
RUN apt update && apt install -y golang-go
COPY app.go .
 
RUN CGO_ENABLED=0 go build app.go
 
CMD ["./app"]

Descrição:

  • FROM: Define qual será a imagem base de container que vamos utilizar, para criar a nossa imagem;
  • ARG: Define um argumento que será utilizado durante o build da imagem. No exemplo apresentado, está declarando que a variável de ambiente DEBIAN_FRONTEND, terá o valor noninteractive, ou seja, você não precisa de nenhuma interação durante a instalação ou atualização de pacotes;
  • RUN: Permite executar comando durante o build da imagem. No exemplo apresentado,a instrução RUN em um momento atualiza e instala pacotes e em outra, realiza o build a partir do arquivo app.go;
  • COPY: Realiza a cópia de arquivos e pastas para a imagem durante o build;
  • CMD: O objetivo principal de um CMD é fornecer padrões para um contêiner em execução. Esses padrões podem incluir um executável ou omitir o executável. Em nosso exemplo, será executado comando ./app quando o container for executado.

Construindo a imagem:

docker image build -t app-golang .
[+] Building 43.3s (9/9) FINISHED                                                                                                                      docker:default
 => [internal] load build definition from Dockerfile                                                                                                             0.0s
 => => transferring dockerfile: 194B                                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                                                 2.3s
 => [internal] load .dockerignore                                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                                  0.0s
 => [1/4] FROM docker.io/library/ubuntu:latest@sha256:b359f1067efa76f37863778f7b6d0e8d911e3ee8efa807ad01fbf5dc1ef9006b                                           2.1s
 => => resolve docker.io/library/ubuntu:latest@sha256:b359f1067efa76f37863778f7b6d0e8d911e3ee8efa807ad01fbf5dc1ef9006b                                           0.0s
 => => sha256:b359f1067efa76f37863778f7b6d0e8d911e3ee8efa807ad01fbf5dc1ef9006b 1.34kB / 1.34kB                                                                   0.0s
 => => sha256:74f92a6b3589aa5cac6028719aaac83de4037bad4371ae79ba362834389035aa 424B / 424B                                                                       0.0s
 => => sha256:61b2756d6fa9d6242fafd5b29f674404779be561db2d0bd932aa3640ae67b9e1 2.30kB / 2.30kB                                                                   0.0s
 => => sha256:eda6120e237e0bdd328bc3e0f610854590400d4f96d9678dfcf781edb2f541d0 29.75MB / 29.75MB                                                                 1.4s
 => => extracting sha256:eda6120e237e0bdd328bc3e0f610854590400d4f96d9678dfcf781edb2f541d0                                                                        0.5s
 => [internal] load build context                                                                                                                                0.0s
 => => transferring context: 310B                                                                                                                                0.0s
 => [2/4] RUN apt update && apt install -y golang-go                                                                                                            33.5s
 => [3/4] COPY app.go .                                                                                                                                          0.0s 
 => [4/4] RUN CGO_ENABLED=0 go build app.go                                                                                                                      4.0s 
 => exporting to image                                                                                                                                           1.3s 
 => => exporting layers                                                                                                                                          1.3s 
 => => writing image sha256:8316cdccc052e6f13dad5be824892776b7be0289779137d97e831ea5035891fc                                                                     0.0s 
 => => naming to docker.io/library/app-golang

Liste a imagem gerada pela build:

docker image ls app-golang
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
app-golang   latest    8316cdccc052   34 seconds ago   652MB

Execute um container e verifique as permissões de usuário e grupo:

docker container run -d --name app app-golang
cc7b3983a7b673d78e511f440399517f9fcf05394b780769ff87e840d3c56842
docker container exec -ti app id
uid=0(root) gid=0(root) groups=0(root)
docker container rm -f app
app

Aplicando ajustes de segurança na imagem

Dockerfile 
FROM ubuntu
ARG DEBIAN_FRONTEND=noninteractive
 
RUN apt update && apt install -y golang-go
COPY app.go .
 
RUN CGO_ENABLED=0 go build app.go
 
FROM alpine:3.12.1
RUN chmod a-w /etc
RUN addgroup -S docker && adduser -S dca -G docker -h /home/dca
RUN rm -rf /bin/*
COPY --from=0 /app /home/dca
USER dca
CMD ["/home/dca/app"]
docker image build -t app-golang:security .
[+] Building 4.6s (15/15) FINISHED                                                                                                                     docker:default
 => [internal] load build definition from Dockerfile                                                                                                             0.0s
 => => transferring dockerfile: 360B                                                                                                                             0.0s
 => [internal] load metadata for docker.io/library/alpine:3.12.1                                                                                                 3.2s
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                                                 1.1s
 => [internal] load .dockerignore                                                                                                                                0.0s
 => => transferring context: 2B                                                                                                                                  0.0s
 => [stage-0 1/4] FROM docker.io/library/ubuntu:latest@sha256:b359f1067efa76f37863778f7b6d0e8d911e3ee8efa807ad01fbf5dc1ef9006b                                   0.0s
 => [internal] load build context                                                                                                                                0.0s
 => => transferring context: 28B                                                                                                                                 0.0s
 => [stage-1 1/5] FROM docker.io/library/alpine:3.12.1@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a                                   0.6s
 => => resolve docker.io/library/alpine:3.12.1@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a                                           0.0s
 => => sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e 528B / 528B                                                                       0.0s
 => => sha256:d6e46aa2470df1d32034c6707c8041158b652f38d2a9ae3d7ad7e7532d22ebe0 1.51kB / 1.51kB                                                                   0.0s
 => => sha256:188c0c94c7c576fff0792aca7ec73d67a2f7f4cb3a6e53a84559337260b36964 2.80MB / 2.80MB                                                                   0.5s
 => => sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a 1.64kB / 1.64kB                                                                   0.0s
 => => extracting sha256:188c0c94c7c576fff0792aca7ec73d67a2f7f4cb3a6e53a84559337260b36964                                                                        0.0s
 => CACHED [stage-0 2/4] RUN apt update && apt install -y golang-go                                                                                              0.0s
 => CACHED [stage-0 3/4] COPY app.go .                                                                                                                           0.0s
 => CACHED [stage-0 4/4] RUN CGO_ENABLED=0 go build app.go                                                                                                       0.0s
 => [stage-1 2/5] RUN chmod a-w /etc                                                                                                                             0.1s
 => [stage-1 3/5] RUN addgroup -S docker && adduser -S dca -G docker -h /home/dca                                                                                0.2s
 => [stage-1 4/5] RUN rm -rf /bin/*                                                                                                                              0.2s
 => [stage-1 5/5] COPY --from=0 /app /home/dca                                                                                                                   0.1s
 => exporting to image                                                                                                                                           0.1s
 => => exporting layers                                                                                                                                          0.1s
 => => writing image sha256:ca60a787ed562bc3d216bf4f9e63992ccd40672c7c4b38b403ad01785f2ba6b6                                                                     0.0s
 => => naming to docker.io/library/app-golang:security
docker image ls app-golang
REPOSITORY   TAG        IMAGE ID       CREATED              SIZE
app-golang   security   ca60a787ed56   About a minute ago   7.6MB
app-golang   latest     8316cdccc052   11 minutes ago       652MB

Execute um container e verifique permissão de usuário e grupo:

docker container run -d --name app app-golang:security
bfb7e2336d83d2116cd3f2cce7a0c1c631182739afe1e03dc80e5c002928347c
docker container exec -ti app id
OCI runtime exec failed: exec failed: unable to start container process: exec: "id": executable file not found in $PATH: unknown

FIXME Durante o build da imagem removendo todos os binários por questão de segurança!

docker container rm -f app
app

Executar um container novamente, só que agora remova a flag -d que permitia a execução em segundo plano:

docker run --name app app-golang:security
user: dca id: 100
user: dca id: 100
user: dca id: 100
user: dca id: 100
user: dca id: 100
user: dca id: 100
user: dca id: 100
user: dca id: 100
^C

FIXME Podemos observar que a nossa aplicação NÃO está mais rodando com permissão de root!

Scan de Imagens

O comando docker scan permite que você analise as imagens do Docker para encontrar vulnerabilidades e obtenha pontuações de vulnerabilidade para cada imagem. O comando docker scan pode ser executado em uma imagem local ou em um repositório remoto.

Enviar imagens ao Docker Hub

Logue em sua conta do Docker Hub

docker login -u usuario_docker_hub \<TECLE ENTER>

Liste as imagens:

docker image ls

Defina uma tag para a imagem app-golang:

docker image tag app-golang:security \<usuario_docker_hub>/app-golang:security

FIXME Uma tag é um alias do ID de uma imagem. Através das tags adicionamos informações nas imagens, como versões, ambiente de desenvolvimento etc.

Envie a imagem:

docker image push \<usuario_docker_hub>/app-golang:security

Docker Content Trust

O Docker Content Trust é uma ferramenta que fornece verificação de integridade de imagem e de origem para a plataforma Docker. Com a assinatura digital e a verificação de integridade, os usuários podem ter certeza de que as imagens que estão sendo executadas são legítimas e não foram alteradas. A ferramenta usa uma chave pública/privada para assinar as imagens, e as chaves são mantidas em um repositório de confiança. Quando um usuário baixa uma imagem assinada, a ferramenta verifica a assinatura usando a chave pública para garantir que a imagem não foi alterada.

Gerenciar imagens com Docker Content Trust

Ative o Docker Content Trust:

export DOCKER_CONTENT_TRUST=1

FIXME Uma vez que o Docker Content Trust esteja habilitado, não será possível realizar downloads de imagens não assinadas.

Tente baixar a imagem do Docker hub que não assinada:

docker image pull jpetazzo/clock
Using default tag: latest
Error: remote trust data does not exist for docker.io/jpetazzo/clock: notary.docker.io does not have trust data for docker.io/jpetazzo/clock

FIXME A operação falha porque a imagem não está assinada (sem dados confiáveis para a imagem).

Agora tente baixar uma imagem oficial:

docker image pull alpine:latest
Pull (1 of 1): alpine:latest@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d
docker.io/library/alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d: Pulling from library/alpine
43c4264eed91: Pull complete 
Digest: sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d
Status: Downloaded newer image for alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d
Tagging alpine@sha256:beefdbd8a1da6d2915566fde36db9db0b524eb737fc57cd1367effd16dc0d06d as alpine:latest

Enviando a imagem assinada do alpine para o repositório do Docker Hub:

docker image tag alpine:latest \<usuario_docker_hub>/alpine:dct
docker image push \<usuario_docker_hub>/alpine:dct

FIXME Será preciso adicionar uma nova chave raiz e uma chave de assinatura do repositório.

wiki/docker/docker_images_management.txt · Last modified: by Wiki Administrator