3.7 Setting up the Docker Registry

A Docker registry is a store of Docker images. A Docker image is a read-only template, which is used to create a Docker container. A Docker registry is required to store the Oracle OpenStack for Oracle Linux Docker images, which are used to deploy the OpenStack containers.

The following instructions assume that you set up the Docker registry on a controller node and that Docker is already configured and running, as described in Section 3.4, “Preparing Oracle Linux Nodes”. If you prefer, you can use a separate host. See Section 3.1, “System Requirements”, for the minimum requirements for a separate host.

3.7.1 Setting up the Docker Registry Server

Before you set up the Docker Registry server, note the following:

  • The registry server is a Docker container application. The host must have an Internet connection in order to download the registry image from the public Docker Hub Registry.

  • The registry server runs on port 5000 by default. If you set up the registry on a controller node, you must select a different free port on the host (for example port 5443) because port 5000 is used by the OpenStack Keystone service. The other nodes in your OpenStack deployment must be able to access the registry on this port.

  • The registry host requires a valid Secure Sockets Layer (SSL) certificate and private key, similar to using SSL for a web server.

    If the host already has an SSL certificate, you can use that. However, if the SSL certificate was issued by an intermediate Certificate Authority (CA), you must combine the host's SSL certificate with the intermediate CA's certificate to create a certificate bundle so that Docker can verify the host's SSL certificate. For example:

    # cat control1.example.com.crt intermediate-ca.pem > domain.crt

    If the host does not already have an SSL certificate, the following instructions provide details for creating a self-signed certificate for testing purposes.

  • The registry server requires a btrfs file system mounted on /var/lib/registry with at least 15GB available. The following instructions provide details for setting up a btrfs file system using one or more available devices. The device could be a disk partition, an LVM volume, a loopback device, a multipath device, or a LUN.

To set up a Docker registry server:

  1. Create a btrfs file system for the registry.

    You create a btrfs file system with the utilities available in the btrfs-progs package, which should be installed by default.

    Create a btrfs file system on one or more block devices:

    # mkfs.btrfs [-L label] block_device ...

    where -L label is an optional label that can be used to mount the file system.

    For example:

    • To create a file system in a partition /dev/sdc1:

      # mkfs.btrfs -L var-lib-registry /dev/sdc1

      The partition must already exist. Use a utility such as fdisk (MBR partitions) or gdisk (GPT partitions) to create one if needed.

    • To create a file system across two disk devices, /dev/sdd and /dev/sde:

      # mkfs.btrfs -L var-lib-registry /dev/sd[de]

      The default configuration is to stripe the file system data (raid0) and to mirror the file system metadata (raid1) across the devices. Use the -d (data) and -m (metadata) options to specify the required RAID configuration. For raid10, you must specify an even number of devices and there must be at least four devices.

    • To create a file system in a logical volume named docker-registry in the ol volume group:

      # mkfs.btrfs -L var-lib-registry /dev/ol/docker-registry

      The logical volume must already exist. Use Logical Volume Manager (LVM) to create one if needed.

    More information on using mkfs.btrfs is available in the Oracle Linux Administrator's Guide for Release 7 at:

    http://docs.oracle.com/cd/E52668_01/E54669/html/ol7-create-btrfs.html

  2. Mount the btrfs file system on /var/lib/registry.

    1. Obtain the UUID of the device containing the btrfs file system.

      Use the blkid command to display the UUID of the device and make a note of this value, for example:

      # blkid /dev/sdc1 
      /dev/sdc1: LABEL="var-lib-registry" UUID="50041443-b7c7-4675-95a3-bf3a30b96c17" \
      UUID_SUB="09de3cb1-2f9b-4bd8-8881-87e591841c75" TYPE="btrfs"

      If the btrfs file system is created across multiple devices, you can specify any of the devices to obtain the UUID. Alternatively you can use the btrfs filesystem show command to see the UUID. For a logical volume, specify the path to the logical volume as the device for example /dev/ol/docker-registry. Ignore any UUID_SUB value displayed.

    2. Edit the /etc/fstab file and add an entry to ensure the file system is mounted when the system boots.

      UUID=UUID_value /var/lib/registry  btrfs  defaults  1 2

      Replace UUID_value with the UUID that you found in the previous step. If you created a label for the btrfs file system, you can also use the label instead of the UUID, for example:

      LABEL=label /var/lib/registry  btrfs  defaults  1 2
    3. Create the /var/lib/registry directory.

      # mkdir /var/lib/registry
    4. Mount all the file systems listed in /etc/fstab.

      # mount -a
    5. Verify that the file system is mounted.

      # df
      Filesystem     1K-blocks    Used Available Use% Mounted on
      ...
      /dev/sdc1            ...    ...  ...       1%   /var/lib/registry
      
  3. Add the host's SSL certificate and private key to Docker.

    1. Create the /var/lib/registry/conf.d directory.

      # mkdir -p /var/lib/registry/conf.d
    2. Copy the host's SSL certificate and private key to the /var/lib/registry/conf.d directory.

      # cp certfile /var/lib/registry/conf.d/domain.crt
      # cp keyfile /var/lib/registry/conf.d/domain.key

      where certfile is the full path to the host's SSL certificate and keyfile is the full path to the host's private key. For example:

      # cp /etc/pki/tls/certs/control1.example.com.crt \
      /var/lib/registry/conf.d/domain.crt
      # cp /etc/pki/tls/private/control1.example.com.key \
      /var/lib/registry/conf.d/domain.key

      If the host does not have an SSL certificate and private key, you can create a self-signed certificate for testing purposes, as follows:

      # cd /var/lib/registry/conf.d
      
      # openssl req -newkey rsa:4096 -nodes -sha256 -x509 -days 365 \
      -keyout domain.key -out domain.crt
      Generating a 4096 bit RSA private key
      ............................................................................................
      ............................................................................................
      .....++
      ............................................................................................
      ............................................................................................
      .........................++
      writing new private key to 'domain.key'
      -----
      You are about to be asked to enter information that will be incorporated
      into your certificate request.
      What you are about to enter is what is called a Distinguished Name or a DN.
      There are quite a few fields but you can leave some blank
      For some fields there will be a default value,
      If you enter '.', the field will be left blank.
      -----
      Country Name (2 letter code) [XX]:US
      State or Province Name (full name) []: Massachusetts
      Locality Name (eg, city) [Default City]:Boston
      Organization Name (eg, company) [Default Company Ltd]:Example Com
      Organizational Unit Name (eg, section) []:DevOps            
      Common Name (eg, your name or your server's hostname) []:control1.example.com
      Email Address []:admin@example.com
      
      # mkdir -p /etc/docker/certs.d/control1.example.com:port
      
      # cp /var/lib/registry/conf.d/domain.crt \
      /etc/docker/certs.d/control1.example.com:port/ca.crt

      The Common Name must be the same as the fully qualified domain name (FQDN) of the host. Replace port with the port number you selected for your Docker registry, for example 5443.

    3. Change the file permissions on the private key:

      # chmod 600 /var/lib/registry/conf.d/domain.key 
  4. Create the Docker registry container.

    In the following example, port is the port number you selected for your Docker registry server, for example 5443.

    # docker run -d -p port:5000 --name registry --restart=always \
        -v /var/lib/registry:/registry_data \
        -e REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/registry_data \
        -e REGISTRY_HTTP_TLS_KEY=/registry_data/conf.d/domain.key \
        -e REGISTRY_HTTP_TLS_CERTIFICATE=/registry_data/conf.d/domain.crt \
        registry:2.3
    Unable to find image 'registry:2.3' locally
    2.3: Pulling from library/registry
    fdd5d7827f33: Pull complete 
    a3ed95caeb02: Pull complete 
    a79b4a92697e: Pull complete 
    6cbb75c7cc30: Pull complete 
    4831699594bc: Pull complete 
    Digest: sha256:0c8c2a39d64da5eef305f9b50e0d889d823d799414c5a1d42f9cfdab2462da19
    Status: Downloaded newer image for registry:2.3
    3c2a7fae6db4dd7e163cab530e7c40209792afeded771f2853a4c4244a147d7b

    The registry image is pulled from the public Docker Hub Registry and the Docker registry container is started. The --restart=always option ensures that the registry container is started whenever Docker is started.

  5. If the registry host uses a self-signed SSL certificate, distribute the SSL certificate to all master and target nodes in your deployment.

    Perform the following steps on each node, where registry_hostname is the name of the registry host, and port is the port number you selected for your Docker registry server, for example 5443:

    1. Create the /etc/docker/certs.d/registry_hostname:port directory.

      # mkdir -p /etc/docker/certs.d/registry_hostname:port
    2. Copy the SSL certificate from the registry host.

      # scp root@registry_hostname:/etc/docker/certs.d/registry_hostname:port/ca.crt \
      /etc/docker/certs.d/registry_hostname:port/ca.crt

      For example:

      # mkdir -p /etc/docker/certs.d/control1.example.com:5443
      # scp \
      root@control1.example.com:/etc/docker/certs.d/control1.example.com:5443/ca.crt \
      /etc/docker/certs.d/control1.example.com:5443/ca.crt
    3. Restart the docker service.

      # systemctl restart docker.service

3.7.2 Importing Images into the Docker Registry

Once you have set up a Docker registry server, you import the Oracle OpenStack for Oracle Linux Docker images into the registry so that they can be used to deploy OpenStack containers.

To import the Oracle OpenStack for Oracle Linux images into the Docker registry:

  1. Ensure the unzip and bzip2 packages are installed on the host.

    # yum install unzip bzip2
  2. Download the Oracle OpenStack for Oracle Linux Docker images zip file from the Oracle Software Delivery Cloud at https://edelivery.oracle.com/linux.

    On Oracle Software Delivery Cloud, search by product for 'openstack' and then select Oracle OpenStack for Oracle Linux.

    Download the zip file to a temporary location on the host, such as /tmp.

  3. Change to the temporary directory and unzip the Oracle OpenStack for Oracle Linux Docker images zip file.

    # cd /tmp
    # unzip ol-openstack-images-version.zip
    Archive:  ol-openstack-images-version.zip
      inflating: import_to_registry.sh   
      inflating: ol-openstack-images-version.tar.bz2  
      inflating: ol-openstack-images-version.sha256sum 

    The following files are unzipped to the directory:

    • import_to_registry.sh: A script to load the images to the Docker registry.

    • ol-openstack-images-version.sha256sum: A sha256sum hash file.

    • ol-openstack-images-version.tar.bz2: Contains the Oracle OpenStack for Oracle Linux Docker images files. Do not decompress this file.

  4. Use the import_to_registry.sh script to import the Oracle OpenStack for Oracle Linux Docker images to the registry.

    # ./import_to_registry.sh [-c] registry_hostname:port

    where registry_hostname is the name of the host, and port is the port number you selected for your Docker registry, for example 5443.

    For example:

    # ./import_to_registry.sh control1.example.com:5443
    Checking file integrity:
    ol-openstack-images-2.1.1.tar.bz2: OK
    
    Please wait, this will take quite some time to complete!
    The push refers to a repository [control1.example.com:5443/oracle/ol-openstack-nova-base]
    (len: 1)
    a8e1024207cf: Pushed 
    ...
    63adc2d9636b: Pushed 
    2.1.1: digest: sha256:fd81fb1da57e6134a4aeb130eab8289e72a69642b582f0cdf06ac55c913a size: 9782
    

    It may take some time to import the images to the Docker registry.

  5. Confirm the registry is working.

    Run the following command on each node in your deployment:

    # docker pull registry_hostname:port/oracle/ol-openstack-base:2.1.1
    2.1.1: Pulling from oracle/ol-openstack-base
    f359075ce4d8: Pull complete 
    63adc2d9636b: Pull complete 
    befb6606d561: Pull complete 
    0820ef56f3c1: Pull complete 
    1280ba3080af: Pull complete 
    d99cb6b1a071: Pull complete 
    3b37b5a7d26b: Pull complete 
    66688385d842: Pull complete 
    90c52512690d: Pull complete 
    59f148406044: Pull complete 
    18fcc7170d65: Pull complete 
    fc3d5a774ca5: Pull complete 
    f8a61519e470: Pull complete 
    Digest: sha256:7d48bd1cd0bd23d610ffa49c575deda2cebf97f1e3977d00ea42c1f07761e8ab
    Status: Downloaded newer image for 
    control1.example.com:5443/oracle/ol-openstack-base:2.1.1

    This command confirms that the node can download a Docker image from the registry and verifies that there are no issues with access to the registry port or with the registry host's SSL certificate.