Um registro de contentores é um catálogo de armazenamento de onde você pode enviar e baixar imagens de contentores.

Existem muitos registros públicos e privados disponíveis para desenvolvedores, como o Docker Hub, o Amazon ECR e o Google Cloud Artifact Registry. Mas às vezes, em vez de confiar em um fornecedor externo, você pode querer hospedar suas imagens sozinho. Isso dá a você mais controle sobre como o registro está configurado e onde os imagens de contentores estão hospedadas.

Este artigo é um tutorial prático que vai ensiná-lo a hospedar um registro de contentores sozinho.

Tabela de Conteúdos

Você conseguirá muito mais deste artigo se estiver familiarizado com ferramentas como Docker e NGINX, e tiver um entendimento geral de que é um container.

O que é uma Imagem de Container?

Antes de falarmos sobre registros de container, vamos primeiro entender o que é uma imagem de container. Em resumo, uma imagem de container é um pacote que inclui todos os arquivos, bibliotecas e configurações necessários para executar um container. Eles são compostos de camadas onde cada camada representa um conjunto de mudanças no sistema de arquivos que adicionam, removem ou modificam arquivos.

A maneira mais comum de criar uma imagem de container é usando um Dockerfile.

# build an image
docker build -t pliutau/hello-world:v0 .

# check the images locally
docker images
# REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
# hello-world   latest    9facd12bbcdd   22 seconds ago   11MB

Isto cria uma imagem de contêiner que é armazenada em sua máquina local. Mas e se você quiser compartilhar essa imagem com outras pessoas ou usá-la em outra máquina? É onde as registries de contêineres entram.

O que é uma Registry de Contêiner?

Uma registry de contêiner é um catálogo de armazenamento onde você pode enviar (push) e baixar (pull) imagens de contêiner. As imagens são agrupadas em repositórios, que são coleções de imagens relacionadas com o mesmo nome. Por exemplo, no registry Docker Hub, nginx é o nome do repositório que contém diferentes versões das imagens NGINX.

Algumas registries são públicas, o que significa que as imagens hospedadas nelas estão acessíveis a qualquer pessoa na Internet. Registries públicas como o Docker Hub são uma boa opção para hospedar projetos open-source.

Por outro lado, as registries privadas fornecem uma maneira de integrar segurança e privacidade ao armazenamento de imagens de contêiner em empresas, tanto hospedadas em nuvem quanto em locais. Essas registries privadas frequentemente vem com funcionalidades de segurança avançadas e suporte técnico.

Há uma lista crescente de registries privadas disponíveis, como o Amazon ECR, GCP Artifact Registry, GitHub Container Registry, e o Docker Hub também oferece uma funcionalidade de repositório privado.

Como desenvolvedor, você interage com um registro de containers quando usa os comandos docker push e docker pull.

docker push docker.io/pliutau/hello-world:v0

# No caso do Docker Hub, podemos também pular a parte do registro
docker push pliutau/hello-world:v0

Vamos olhar na anatomia de uma URL de imagem de container:

docker pull docker.io/pliutau/hello-world:v0@sha256:dc11b2...
                |            |            |          |
                ↓            ↓            ↓          ↓
             registry    repository      tag       digest

Porque você pode querer hospedar um registro de containers em sua própria máquina

Algumas vezes, em vez de confiar em um fornecedor como AWS ou GCP, você pode querer hospedar suas imagens sozinho. Isto mantém sua infraestrutura interna e o torna menos dependente de fornecedores externos. Em algumas indústrias regulamentadas, isso até é uma exigência.

Um registro hospedado localmente roda em seus próprios servidores, dando-lhe mais controle sobre como o registro é configurado e onde as imagens de containers estão hospedadas. Ao mesmo tempo, isso vem com o custo de manutenção e segurança do registro.

Como hospedar um registro de containers em sua própria máquina

Existem várias soluções de registro de containers de código aberto disponíveis. A mais popular é oficialmente suportada por Docker, chamada registry, com sua implementação para armazenamento e distribuição de imagens e artefatos de containers. Isto significa que você pode executar seu próprio registro dentro de um container.

Aqui estão os passos principais para executar um registro em um servidor:

  • Instale o Docker e o Docker Compose no servidor.

  • Configure e execute o container registry.

  • Executar NGINX para lidar com TLS e redirecionar pedidos para o recipiente de registro.

  • Configurar certificados SSL e configurar um domínio.

Passo 1: Instalar o Docker e o Docker Compose no servidor

Você pode usar qualquer servidor que suporte o Docker. Por exemplo, você pode usar um Droplet do DigitalOcean com o Ubuntu. Para este demo, eu usei o Google Cloud Compute para criar uma VM com o Ubuntu.

neofetch

# Sistema Operacional: Ubuntu 20.04.6 LTS x86_64
# CPU: Intel Xeon (2) @ 2.200GHz
# Memória: 3908MiB

Uma vez dentro de nossa VM, devemos instalar o Docker e o Docker Compose. O Docker Compose é opcional, mas facilita a gestão de aplicações multi-recipiente.

# instalar o motor de docker e docker-compose
sudo snap install docker

# verificar a instalação
docker --version
docker-compose --version

Passo 2: Configurar e executar o recipiente de registro

Aqui, precisamos configurar o nosso recipiente de registro. O seguinte arquivo compose.yaml criará um recipiente de registro com um volume para armazenar as imagens e um volume para armazenar o arquivo de senha.

services:
  registry:
    image: registry:latest
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      # Montar o arquivo de senhas
      - ./registry/registry.password:/auth/registry.password
      # Montar o diretório de dados
      - ./registry/data:/data
    ports:
      - 5000

O arquivo de senhas definido em REGISTRY_AUTH_HTPASSWD_PATH é usado para autenticar usuários quando eles enviar ou recebem imagens do registro. Nós devemos criar um arquivo de senhas usando o comando htpasswd. Também devemos criar uma pasta para armazenar as imagens.

mkdir -p ./registry/data

# instalar htpasswd
sudo apt install apache2-utils

# criar um arquivo de senhas. nome de usuário: busy, senha: bee
htpasswd -Bbn busy bee > ./registry/registry.password

Agora nós podemos iniciar o contêiner do registro. Se você ver esta mensagem, então tudo está funcionando como deveria:

docker-compose up

# execução bem-sucedida deveria exibir algo como isto:
# registry | level=info msg="listening on [::]:5000"

Passo 3: Executar NGINX para lidar com TLS

Como mencionado anteriormente, nós podemos usar NGINX para lidar com TLS e encaminhar pedidos para o contêiner do registro.

O Registro Docker necessita de um certificado SSL válido e confiável para funcionar. Você pode usar algo como Let’s Encrypt ou obter manualmente. Certifique-se de ter um nome de domínio apontando para seu servidor (registry.pliutau.com no meu caso). Para este demo, eu já obtive os certificados usando certbot e coloquei-os na pasta ./nginx/certs.

since estamos executando nosso registro do Docker em um container, podemos executar o NGINX em um container também, adicionando o seguinte serviço ao arquivo compose.yaml:

services:
  registry:
    # ...
  nginx:
    image: nginx:latest
    depends_on:
      - registry
    volumes:
      # montar a configuração do nginx
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # montar os certificados obtidos do Let's Encrypt
      - ./nginx/certs:/etc/nginx/certs
    ports:
      - "443:443"

O arquivo nginx.conf poderia parecer assim:

worker_processes auto;

events {
    worker_connections 1024;
}

http {
    upstream registry {
        server registry:5000;
    }

    server {
        server_name registry.pliutau.com;
        listen 443 ssl;

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            # configuração importante para imagens grandes
            client_max_body_size                1000m;

            proxy_pass                          http://registry;
            proxy_set_header  Host              $http_host;
            proxy_set_header  X-Real-IP         $remote_addr;
            proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Proto $scheme;
            proxy_read_timeout                  900;
        }
    }
}

Pronto para começar!

Após esses passos, podemos executar os containers de registro e Nginx.

docker-compose up

Agora, do lado do cliente, você pode enviar e baixar imagens de seu registro. Mas antes, precisamos fazer login no registro.

docker login registry.pliutau.com

# Usuário: busy
# Senha: bee
# Login bem-sucedido

Vamos construir e enviar nossa imagem para o nosso registro auto-hospedado:

docker build -t registry.pliutau.com/pliutau/hello-world:v0 .

docker push registry.pliutau.com/pliutau/hello-world:v0
# v0: digest: sha256:a56ea4... size: 738

No seu servidor, você pode ver as imagens enviadas na pasta de dados:

ls -la ./registry/data/docker/registry/v2/repositories/

Outras opções

Seguindo o exemplo acima, você também pode executar o registro no Kubernetes. Ou você pode usar um serviço de registro gerenciado, como o Harbor, que é um registro de código aberto que oferece recursos de segurança avançados e é compatible com Docker e Kubernetes.

Também, se você quiser ter uma interface de usuário para seu registro hospedado localmente, você poderia usar um projeto como joxit/docker-registry-ui e executá-lo em um container separado.

Conclusão

Registros de Contêineres Hospedados Localmente permitem que você tenha controle total sobre seu registro e a maneira como é implantado. Ao mesmo tempo, isso vem com o custo de manutenção e de segurança do registro.

Qualquer das suas razões para executar um registro hospedado localmente, agora você sabe como fazer. A partir daqui, você pode comparar as diferentes opções e escolher a que melhor se adapta às suas necessidades.

Você pode encontrar o código-fonte completo para este demo no GitHub. Também, você pode assistir como um vídeo no nosso canal do YouTube.