Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado

DockerDockerBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introduction

Docker has become an essential tool for developers and DevOps teams, enabling the seamless deployment and management of containerized applications. When working with a private Docker registry, securing communication between Docker clients and the registry server is crucial for protecting your container images.

In this lab, you will learn how to set up a local Docker registry and secure it using a self-signed SSL certificate. This approach is perfect for development environments, testing, and learning scenarios where you need a secure registry without purchasing a certificate from a trusted authority.

By the end of this tutorial, you will have a functioning Docker registry that uses HTTPS for secure communication, allowing you to safely push and pull Docker images within your development environment.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/start("Start Container") docker/ContainerOperationsGroup -.-> docker/rm("Remove Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/ImageOperationsGroup -.-> docker/tag("Tag an Image") docker/ImageOperationsGroup -.-> docker/push("Push Image to Repository") docker/ImageOperationsGroup -.-> docker/rmi("Remove Image") subgraph Lab Skills docker/run -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/ps -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/start -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/rm -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/create -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/pull -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/tag -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/push -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} docker/rmi -.-> lab-411514{{"Cómo configurar un registro Docker para utilizar un certificado SSL autofirmado"}} end

Setting Up a Basic Docker Registry

Before securing our Docker registry with SSL, let's first understand what a Docker registry is and set up a basic registry to work with.

What is a Docker Registry?

A Docker registry is a storage and distribution system for Docker container images. It allows you to:

  • Store your Docker images in a central location
  • Share images with your team or organization
  • Control access to your images
  • Deploy containers from your images across different environments

Docker Hub is the most well-known public registry, but for many organizations, having a private registry is essential for security, performance, and control.

Setting Up a Basic Registry

Let's start by running a simple, insecure Docker registry:

  1. Create a directory to store our registry data:

    mkdir -p ~/project/registry-data
  2. Run a basic Docker registry using the official image:

    docker run -d -p 5000:5000 --restart=always --name registry -v ~/project/registry-data:/var/lib/registry registry:2

    This command:

    • Runs the registry container in detached mode (-d)
    • Maps port 5000 on your host to port 5000 in the container
    • Sets the container to restart automatically if it stops
    • Names the container "registry"
    • Mounts the directory we created to store registry data
  3. Verify the registry is running:

    docker ps

    You should see output similar to:

    CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS                    NAMES
    a7d8098de3a2   registry:2   "/entrypoint.sh /etc…"   5 seconds ago   Up 4 seconds   0.0.0.0:5000->5000/tcp   registry
  4. Test the registry by pushing a sample image:

    First, pull a small image:

    docker pull hello-world

    Tag it for your local registry:

    docker tag hello-world localhost:5000/hello-world

    Push it to your registry:

    docker push localhost:5000/hello-world

    You should see output showing the image being pushed to your registry.

  5. Stop the registry container before we secure it in the next steps:

    docker stop registry
    docker rm registry

This basic registry works but has a significant limitation: it uses HTTP, which is insecure. Docker clients refuse to push or pull from insecure registries by default. In the next steps, we'll secure our registry with SSL.

Generating a Self-Signed SSL Certificate

Now that we understand the basics of Docker Registry, let's secure it by generating a self-signed SSL certificate. This certificate will enable HTTPS communication with our registry.

What is a Self-Signed Certificate?

A self-signed certificate is an SSL certificate that isn't signed by a trusted Certificate Authority (CA). While not suitable for production environments exposed to the public internet, self-signed certificates are perfect for development, testing, and internal applications.

Generate the Certificate and Key

We'll use OpenSSL, a widely-used cryptography toolkit, to create our certificate:

  1. Create a directory to store our certificates:

    mkdir -p ~/project/registry-certs
    cd ~/project/registry-certs
  2. Generate a private key:

    openssl genrsa -out registry.key 2048

    This command generates a 2048-bit RSA private key. You should see no output if successful.

  3. Create a certificate signing request (CSR) using the private key:

    openssl req -new -key registry.key -out registry.csr

    You'll be prompted to enter information that will be included in your certificate:

    Country Name (2 letter code) [AU]:US
    State or Province Name (full name) [Some-State]:California
    Locality Name (eg, city) []:San Francisco
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Company
    Organizational Unit Name (eg, section) []:IT
    Common Name (e.g. server FQDN or YOUR name) []:localhost
    Email Address []:admin@example.com

    Note: For Common Name, enter localhost since we'll be connecting to the registry on our local machine.

    You'll also be asked for:

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:

    You can leave these blank by pressing Enter.

  4. Generate the self-signed certificate using the CSR:

    openssl x509 -req -days 365 -in registry.csr -signkey registry.key -out registry.crt

    This command creates a self-signed certificate valid for 365 days.

    You should see output similar to:

    Signature ok
    subject=C = US, ST = California, L = San Francisco, O = Example Company, OU = IT, CN = localhost, emailAddress = admin@example.com
    Getting Private key
  5. Verify that the certificate and key files have been created:

    ls -l

    You should see three files:

    total 12
    -rw-r--r-- 1 labex labex 1220 [date] registry.crt
    -rw-r--r-- 1 labex labex 1054 [date] registry.csr
    -rw-r--r-- 1 labex labex 1679 [date] registry.key

Now we have the necessary files to secure our Docker registry. In the next step, we'll configure our registry to use this certificate for HTTPS communication.

Configuring Docker Registry with SSL Certificate

Now that we have our self-signed certificate, we can configure our Docker registry to use SSL for secure communication.

Setting Up the Secure Registry

  1. First, let's create a simple configuration file for our registry. This file will specify the HTTPS settings:

    mkdir -p ~/project/registry-config
    cd ~/project/registry-config
    nano config.yml
  2. Add the following configuration to the file:

    version: 0.1
    storage:
      filesystem:
        rootdirectory: /var/lib/registry
    http:
      addr: 0.0.0.0:5000
      tls:
        certificate: /certs/registry.crt
        key: /certs/registry.key

    This configuration tells the registry to:

    • Use the filesystem for storage
    • Listen on all interfaces on port 5000
    • Use TLS (HTTPS) with our certificate and key
  3. Save and exit by pressing Ctrl+X, then Y, and then Enter.

  4. Now let's run our registry with the SSL certificate:

    docker run -d -p 5000:5000 --restart=always --name registry \
      -v ~/project/registry-data:/var/lib/registry \
      -v ~/project/registry-certs:/certs \
      -v ~/project/registry-config/config.yml:/etc/docker/registry/config.yml \
      registry:2

    This command:

    • Mounts our certificate and key directory
    • Mounts our configuration file
    • Uses the same data directory we created earlier
  5. Verify the registry is running:

    docker ps

    You should see output showing the registry container is running.

Configuring Docker Client to Trust the Certificate

By default, Docker clients don't trust self-signed certificates. We need to tell Docker to trust our certificate:

  1. Create a directory for Docker to store trusted certificates:

    sudo mkdir -p /etc/docker/certs.d/localhost:5000
  2. Copy our certificate to this directory:

    sudo cp ~/project/registry-certs/registry.crt /etc/docker/certs.d/localhost:5000/ca.crt
  3. Restart the Docker service to pick up the changes:

    sudo systemctl restart docker

    This may take a few seconds to complete.

  4. Since restarting Docker will stop our registry container, let's start it again:

    docker start registry
  5. Verify the registry is running again:

    docker ps

Now our Docker registry is configured to use HTTPS with our self-signed certificate, and our Docker client is configured to trust this certificate when connecting to localhost:5000.

Testing the Secure Docker Registry

Now that we have our Docker registry running with SSL, let's test it by pushing and pulling images. This will confirm that everything is working correctly.

Testing with a Sample Image

  1. First, let's pull a sample image to use for testing:

    docker pull alpine:latest

    You should see output showing Docker downloading the Alpine Linux image.

  2. Tag the image for our secure registry:

    docker tag alpine:latest localhost:5000/alpine:latest

    This command creates a new tag that points to our local registry.

  3. Push the image to our secure registry:

    docker push localhost:5000/alpine:latest

    You should see output showing the image layers being pushed to your registry:

    The push refers to repository [localhost:5000/alpine]
    213ec9aee27d: Pushed
    latest: digest: sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f size: 528
  4. Remove the local image to ensure we're pulling from the registry:

    docker rmi localhost:5000/alpine:latest
    docker rmi alpine:latest
  5. Pull the image from our secure registry:

    docker pull localhost:5000/alpine:latest

    You should see output showing Docker downloading the image from your registry:

    latest: Pulling from alpine
    213ec9aee27d: Pull complete
    Digest: sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f
    Status: Downloaded newer image for localhost:5000/alpine:latest
    localhost:5000/alpine:latest

Verifying Registry Contents

Let's examine the contents of our registry using the Docker Registry API:

  1. List all repositories in the registry:

    curl -X GET https://localhost:5000/v2/_catalog --cacert ~/project/registry-certs/registry.crt

    You should see output like:

    { "repositories": ["alpine", "hello-world"] }

    This shows all the images we've pushed to our registry.

  2. List all tags for the alpine repository:

    curl -X GET https://localhost:5000/v2/alpine/tags/list --cacert ~/project/registry-certs/registry.crt

    You should see output like:

    { "name": "alpine", "tags": ["latest"] }

Understanding What We've Accomplished

Let's review what we've done:

  1. Set up a Docker registry with HTTPS using a self-signed SSL certificate
  2. Configured our Docker client to trust this certificate
  3. Successfully pushed and pulled images to and from our secure registry

This setup provides:

  • Encrypted communication: All data transferred between Docker client and registry is encrypted.
  • Authentication foundation: SSL is the first step toward implementing authentication.
  • Docker client compatibility: Docker clients require HTTPS by default for non-localhost registries.

You can now use this secure registry for your development and testing needs. For production environments, you would typically use a certificate from a trusted certificate authority instead of a self-signed certificate.

Summary

Congratulations! You have successfully set up a secure Docker registry using a self-signed SSL certificate. Here's what you've accomplished:

  1. Set up a basic Docker registry and understood its purpose and functionality
  2. Generated a self-signed SSL certificate for securing your registry
  3. Configured the Docker registry to use HTTPS with your certificate
  4. Configured your Docker client to trust the self-signed certificate
  5. Successfully tested the secure registry by pushing and pulling images

These skills allow you to create secure private registries for your development and testing environments. Private registries give you control over where your Docker images are stored and who can access them, while SSL encryption ensures that your data remains secure during transmission.

For production environments, you would typically use certificates from a trusted certificate authority, but the configuration process would be similar to what you've learned in this lab.

Now you can confidently implement secure Docker registries in your own projects and development workflows, enhancing the security of your containerized applications.