How to publish a resource to Charmhub

See also:

You have a charm that you’ve published to Charmhub. You also have a resource name that has been associated to your charm. This document shows you how you can now publish your resource to Charmhub too. Because resources are defined in a charm’s metadata.yaml, they are intrinsically linked to a charm, so there is no need to register them separately in Charmhub—all you need to do is upload the resource.

Other charms may have resources with the same name, but this is not a problem; references to resources always contain the charm name and resource name.


Upload a file resource

To upload a file resource, simply follow the template below:

    jdoe@machine:~/blogsystem$ charmcraft upload-resource my-super-charm someresource --filepath=/tmp/superdb.bin
    Revision 1 created of resource 'someresource' for charm 'my-super-charm'

To update a pre-uploaded resource, simply run the upload command again. The result will be a new revision.

jdoe@machine:~/blogsystem$ charmcraft upload-resource my-super-charm someresource --filepath=/tmp/superdb.bin
Revision 2 created of resource 'someresource' for charm 'my-super-charm'

To verify all the revisions for a specific resource, execute:

jdoe@machine:~/blogsystem$ charmcraft resource-revisions my-super-charm someresource 
Revision    Created at    Size
2           2021-03-05  192.3K
1           2021-03-05  204.9K

Upload an OCI-image resource

Uploading oci-image resources is similar to uploading file resources, but with a few different parameters to the command.

For example, if an oci-image is defined in metadata.yaml like so:

# ...

    type: oci-image
    description: OCI image for Redis
# ...

It can be uploaded like so:

# charmcraft upload-resource --image <image digest> <charm name> <resource name>

$ charmcraft upload-resource my-super-charm redis-image --image=sha256:64aa8983ec5cea7bc143af18829836914fa405184d56dcbdfd9df672ade85249
Revision 1 created of resource 'redis-image' for charm 'my-super-charm'

The option --image must indicate an OCI image’s digest, being it in the short or long form (e.g.: 70aa8983ec5c or sha256:64aa8983ec5cea7bc143af18829836914fa405184d56dcbdfd9df672ade85249).

Charmcraft will first check if that specific image is available in Canonical’s Registry, and just use it if that’s the case. If not, it will try to get it from the developer’s local OCI repository (needs dockerd to be installed and running), push it to the Canonical’s Registry, and then use it.

When using the “short form” of the digest, the image needs to be present locally so its proper ID (the “long form”) can be retrieved.

The following is an example of charmcraft using an image already present in Canonical’s Registry:

$ charmcraft upload-resource my-super-charm redis-image --image=sha256:c8f0dbc0d5a5e3aef7281a4d3941e97f204390b2cba9de6c117341361cbe84e4

Using the OCI image from Canonical's registry

Revision 7 created of resource 'redis-image' for charm 'my-super-charm'

The following is the case of charmcraft needing to push the image first:

$ charmcraft upload-resource my-super-charm redis-image --image=sha256:70aa8983ec5cea7bc143af188b4bdc424fa405184d56dcbdfd9df672ade85249

Remote image not found, uploading from local registry

Image uploaded, new remote digest: sha256:29b027d656acae6e50693a2ec063d40c7de59a2f7b4c0d62c765d2f1cbde616c

Revision 5 created of resource 'redis-image' for charm 'my-super-charm'

One detail to take into consideration: when charmcraft pushes the local image to Canonical’s registry, the remote manifest ends up slightly different to the local one. This is deterministic, so future operations will continue to use the same manifest, but it does take some work each time to compute the target manifest.

1 Like

By default version and revision are identical and increment by 1 together.
How was the version pinned to 7.4a?

That’s a good question - I stole this from @facundo so he may have more details :slight_smile:

Hello! Sure, I can explain it.

The revision is a monotonically increasing number. Everytime you push a new charm file, the revision will be incremented by 1.

The version, however, comes from the version file the charm has inside, so it can be anything.

That said, the version file is optional, and many charms don’t include one. In that case, Charmhub will assign to the version field the same number than revision, and that’s why in many cases those numbers are the same.

Please let me know if you have more questions around this, glad to help!

Aha! I didn’t know that. We should probably have that file documented here if you have the relevant details? /cc @rbarry

@sed-i @facundo @jnsgruk updated docs are up


After quite a bit of struggling I realized that in order to upload an OCI image, you need to supply not the image digest but the image id as shown with docker images --no-trunc. Perhaps we should mention this in the dock.

It will be useful to have to clarifications in this document

  1. Query if a specific version of a resource has already been uploaded to charmhub. For example if is already available as a resource in Charmhub for the MongoDB charm.
  2. What happens if one uploads the same resource version twice. For example what happens if is uploaded twice.

How to obtain the coveted sha256 digest – notes for future self

Use docker pull

$ docker pull
2.4.0: Pulling from grafana/mimir
213ec9aee27d: Pull complete 
94108ba43ede: Pull complete 
b3023ed4c9d8: Pull complete 
Digest: sha256:91f0c6a484fc5946f400bd736aefa218067e0b386e5398f95d17a283b22bce09
Status: Downloaded newer image for grafana/mimir:2.4.0

The coveted digest is right there, under digest.

Or, after pulling, run this:

$ docker images grafana/mimir --digests
REPOSITORY      TAG       DIGEST                                                                    IMAGE ID       CREATED        SIZE
grafana/mimir   2.4.0     sha256:91f0c6a484fc5946f400bd736aefa218067e0b386e5398f95d17a283b22bce09   1e86d06b7482   3 months ago   58.1MB

Or, inspect the image and look at RepoDigests (NOT the Id):

$ docker image inspect
        "Id": "sha256:1e86d06b7482735bf318c4902b8bcaa70c656a3f7d533140b8fa7a95db08dcbf",
        "RepoTags": [
        "RepoDigests": [

Use skopeo (no need to pull the image)

Use skopeo to inspect and look at Digest.

$ skopeo inspect docker://grafana/mimir:2.4.0 
    "Name": "",
    "Digest": "sha256:91f0c6a484fc5946f400bd736aefa218067e0b386e5398f95d17a283b22bce09",

Use online container explorer

For example, to view the prom/alertmanager image, head over to: