Advanced config to host your own Juju operator images

For a variety of reasons (e.g., security, or to avoid limitations inherent to Juju’s use of Docker Hub), you may wish to host your own Juju operator images.

You are able to host the jujud-operator, juju-db and charm-base OCI images on your own private registry. The supported registries are listed below:

To bootstrap using a private registry, you just need to get the registry credential in the format shown for each registry below, then set it to controller config caas-image-repo.

Note: The caas-image-repo controller config is immutable, which means you won’t be able to update it after bootstrap.

Docker Hub - docker.io

  1. Get a cloud. Below we use MicroK8s. To install and set up MicroK8s, see here.

  2. Get Docker. (a) Sign up for a Docker account; instructions here. (b) Install Docker Engine; instructions here.

  3. Create a private or public repository for each of the Juju operator images, jujud-operator, juju-db, and charm-base; instructions here.

  4. For each of the Juju operator images, pull the image from Juju’s official repository and push it to the corresponding Docker repository. Juju’s official repositories on DockerHub can be viewed here. Instructions for how to pull from and push to a Docker repository are given here and here.

Note: If you get an error of the form “permission denied while trying to connect to the Docker daemon socket”: (a) Follow the instructions here. Or: (b) Prefix all the Docker commands with sudo.

  1. Now follow the instructions below.

Note: For the private repository, make sure to first create the json file (in an accessible location, e.g., your Home directory). If you choose to log in using your authentication token, the location of the token may vary—if in step 4 you got an error and solved it via option (b) (sudo), your authentication token will be saved in the location indicated in the warning issued there (/root/.docker/config.json).

# public repository
$ juju bootstrap microk8s k1 --config caas-image-repo=jujuqa --debug

# or
$ juju bootstrap microk8s k1 --config caas-image-repo="'{"repository": "jujuqa"}'" --debug
# private repository
$ cat credential.json
{
    "repository": "<your-repository-name>",
    "username": "<your-docker-username>",
    "password": "<your-docker-password>"
}

# or grab the auth token from `~/.docker/config.json`
$ cat credential.json
{
    "auth": "<your-auth-token>",
    "repository": "<your-repository-name>"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat credential.json)'" --debug

Azure container registry - azurecr.io

Set up service principal account with owner role of your repository: https://docs.microsoft.com/en-us/azure/container-registry/container-registry-auth-service-principal

$ cat acr.json
{
    "repository": "<your-repository-name>.azurecr.io",
    "username": "<Service principal ID>",
    "password": "<Service principal password>"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat acr.json)'" 

$ mkubectl -ncontroller-k1 get secret/juju-image-pull-secret -o json | jq -r '.data[".dockerconfigjson"]' | base64 --decode | jq
{
  "auths": {
    "<your-repository-name>.azurecr.io": {
      "auth": "xxxx==",
      "username": "<Service principal ID>",
      "password": "<Service principal password>",
      "serveraddress": "<your-repository-name>.azurecr.io"
    }
  }
}

$ mkubectl -ncontroller-k1 get pod -o json | jq '.items[].spec.containers[].image'
"jujuqa.azurecr.io/juju-db:4.0"
"jujuqa.azurecr.io/jujud-operator:2.9.16"
"jujuqa.azurecr.io/jujud-operator:2.9.16"

AWS Elastic Container Registry - id.dkr.ecr.region.amazonaws.com

$ cat ecr.json
{
    "repository": "xxxx.dkr.ecr.eu-west-1.amazonaws.com",
    "username": "<aws_access_key_id>",
    "password": "<aws_secret_access_key>",
    "region": "ap-southeast-2"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat ecr.json)'" 

$ mkubectl -ncontroller-k1 get secret/juju-image-pull-secret -o json | jq -r '.data[".dockerconfigjson"]' | base64 --decode | jq
{
  "auths": {
    "xxxx.dkr.ecr.eu-west-1.amazonaws.com": {
      "auth": "xxxx==",
      "username": "<aws_access_key_id>",
      "password": "<aws_secret_access_key>",
      "region": "ap-southeast-2",
      "serveraddress": "xxxx.dkr.ecr.eu-west-1.amazonaws.com"
    }
  }
}

$ mkubectl -ncontroller-k1 get pod -o json | jq '.items[].spec.containers[].image'
"xxxx.dkr.ecr.eu-west-1.amazonaws.com/jujud-operator:2.9.15"
"xxxx.dkr.ecr.eu-west-1.amazonaws.com/juju-db:4.0"
"xxxx.dkr.ecr.eu-west-1.amazonaws.com/jujud-operator:2.9.15"

Google Container Registry - gcr.io

# public repository
$ juju bootstrap microk8s k1 --config caas-image-repo="gcr.io/<project-id>" --debug

# or
$ juju bootstrap microk8s k1 --config caas-image-repo="'{"repository": "gcr.io/<project-id>"}'" --debug
# private repository
#  create the JSON key credential: "https://cloud.google.com/container-registry/docs/advanced-authentication#json-key";
# then `docker login`
# grab the auth token from `~/.docker/config.json`

# Note: you should always use the JSON key but never use the short-lived OAuth `access token`.

$ cat credential.json
{
    "auth": "xxxx==",
    "repository": "gcr.io/<project-id>"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat credential.json)'" --debug

Github Container Registry

Follow the official document to create a github personal access token (PAT) for container registry.

Note: Please set the expiration of your PAT to never, because the caas-image-repo controller config is immutable, which means you won’t be able to update it after bootstrap.

$ cat credential.json
{
    "repository": "ghcr.io/<your-repository-name>",
    "username": "<your-username>",
    "password": "<github container registry PAT>"
}

# or grab the auth token from `~/.docker/config.json` if you have already done `docker login`
cat credential.json
{
    "auth": "xxxx",
    "repository": "ghcr.io/<your-repository-name>"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat credential.json)'" --debug

Gitlab Container Registry - registry.gitlab.com

$ cat credential.json
{
    "repository": "registry.gitlab.com/<your-repository-name>",
    "username": "<your-username>",
    "password": "xxxx"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat credential.json)'" --debug

RedHat Container Registry - quay.io

# public repository:
$ juju bootstrap microk8s k1 --config caas-image-repo="quay.io/juju_qa" --debug

# or
$ juju bootstrap microk8s k1 --config caas-image-repo="'{"repository": "quay.io/juju_qa"}'" --debug
# docker login with your quay.io username and password
# copy the credential from ~/.docker/config.json
$ cat credential.json
{
    "auth": "xxxx==",
    "repository": "quay.io/<your-repository-name>"
}

$ juju bootstrap microk8s k1 --config caas-image-repo="'$(cat credential.json)'" --debug
1 Like

This probably needs to be a part of the proper Juju docs somewhere :slight_smile: Nice work though! @tmihoc @pedroleaoc

2 Likes

Thanks for the alert, @jnsgruk. Added to to-do list for Juju docs.