{"id":15657320,"url":"https://github.com/flavio/collage","last_synced_at":"2025-05-05T15:44:20.307Z","repository":{"id":66493625,"uuid":"120291797","full_name":"flavio/collage","owner":"flavio","description":"read-only docker registry made of images coming from different locations","archived":false,"fork":false,"pushed_at":"2018-12-10T09:17:40.000Z","size":7926,"stargazers_count":23,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T22:05:50.051Z","etag":null,"topics":["cont","containers","docker","docker-registry"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flavio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-05T10:46:58.000Z","updated_at":"2021-01-11T19:47:42.000Z","dependencies_parsed_at":"2023-02-21T16:30:27.215Z","dependency_job_id":null,"html_url":"https://github.com/flavio/collage","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flavio%2Fcollage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flavio%2Fcollage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flavio%2Fcollage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flavio%2Fcollage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flavio","download_url":"https://codeload.github.com/flavio/collage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252525578,"owners_count":21762327,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cont","containers","docker","docker-registry"],"created_at":"2024-10-03T13:06:17.604Z","updated_at":"2025-05-05T15:44:20.281Z","avatar_url":"https://github.com/flavio.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Collage\n\n\u003e Collage (from the French: coller, \"to glue\"; French pronunciation: [kɔ.laʒ])\n\u003e is a technique of an art production, primarily used in the visual arts,\n\u003e where the artwork is made from an assemblage of different forms, thus\n\u003e creating a new whole.\n\nCollage acts as a read-only [docker registry](https://github.com/docker/distribution)\nthat is made of images coming from different locations.\n\nUsers can define remote repositories hosted on different registries and \"mount\"\nthem under specific paths.\n\n\n# Installation\n\nCollage is a Go program, it can be installed by doing:\n\n```\ngo get github.com/flavio/collage\n```\n\nYou can also use the [flavio/collage](https://hub.docker.com/r/flavio/collage/)\nimage available on the Docker Hub.\n\n```\n$ docker run --rm -p 5000:5000 -v /path/to/local/config.json:/app/config.json:ro flavio/collage\n```\n\n**Note well:** this image is based on Alpine Linux. If you some of your registries\nare using self-signed certificates you just have to mount them into the running\nimage under `/usr/local/share/ca-certificates/\u003ccert.pem\u003e`. The entrypoint of\nthe image will automatically load them.\n\nopenSUSE and SUSE packages are available inside of `obs://Virtualization:containers`.\n\n# Usage\n\nCollage expects a json configuration file that specifies all the mappings.\n\nFor example, given the following configuration file:\n\n```json\n{\n  \"mappings\" : {\n    \"cool/stuff\":  \"index.docker.io/flavio\",\n    \"cool/distro\": \"index.docker.io/opensuse\",\n    \"etcd\":        \"quay.io/coreos/etcd\",\n    \"foobar\":      \"http://insecure-registry.local.lan/foo\"\n  }\n}\n```\n\nThe repository `coreos/etcd` from the quay.io registry is mounted as repository\n`etcd`.\n\nThe images of the repository `flavio/` from the Docker Hub are now available\nunder the `/cool/stuff` repository.\nThe same applies to the images of the `opensuse/` repository, now mounted as\n`cool/distro`.\n\nHaving a collage instance running on `collage.local.lan`, the command\n`docker pull collage.local.lan/etcd/etcd:v3.3` will retrieve\nthe `quay.io/coreos/etcd/etcd:v3.3` image transparently.\n\nAll the images inside of [/flavio](https://hub.docker.com/u/flavio/) are\navailable as `collage.local.lan/cool/stuff/\u003crepository\u003e:\u003ctag(s)\u003e`. For\nexample: [collage.local.lan/cool/stuff/guestbook](https://hub.docker.com/r/flavio/guestbook/)\n[collage.local.lan/cool/stuff/guestbook](https://hub.docker.com/r/flavio/guestbook-go/),...\n\n**Note well:** by default collage assumes the mapped registries are using TLS.\nYou must be explicit about registries **not** using TLS: provide the `http://`\nprefix inside of their URL.\n\n## Docker image\n\nA Docker image is automatically built on the DockerHub based on the contents\nof the `master` branch of this repository.\n\nThe image can be found [here](https://hub.docker.com/r/flavio/collage/), or\nsimply via:\n\n```\ndocker pull flavio/collage\n```\n\nThe image runs collage as unprivileged `web` user.\n\n## Virtual hosts config\n\nIt's possible to configure collage to have virtual hosts specific mappings.\n\nThis can be achieved by using the following configuration:\n\n```json\n{\n  \"vhosts\" : {\n    \"docker-io-mirror.local.lan\": {\n      \"mappings\" : {\n        \"/\" : \"mirror.local.lan/docker.io\"\n      }\n    },\n    \"quay-io-mirror.local.lan\": {\n      \"mappings\" : {\n        \"/\" : \"mirror.local.lan/quay.io\"\n      }\n    }\n  },\n  \"mappings\" : {\n    \"cool/stuff\" : \"index.docker.io/flavio\",\n    \"cool/distro\" : \"index.docker.io/opensuse\",\n    \"etcd\": \"quay.io/coreos/etcd\",\n    \"foobar\": \"http://insecure-registry.local.lan/foo\"\n  }\n}\n```\n\nLet's assume the host running collage can be reached using the following FQDNs:\n\n  * `docker-io-mirror.local.lan`\n  * `quay-io-mirror.local.lan`\n  * `collage.local.lan`\n\nThat will lead to the following behaviours:\n\n  * `docker pull docker-io-mirror.local.lan/busybox:latest` will\n    be resolved to `mirror.local.lan/docker.io/busybox:latest`\n  * `docker pull quay-io-mirror.local.lan/cores/etcd:latest` will\n    be resolved to `mirror.local.lan/quay.io/coreos/etcd:latest`\n  * `docker pull collage.local.lan/cool/stuff/collage:latest` will\n    be resolved to `index.docker.io/flavio/collage:latest`\n\nThis is particularly useful when to host multiple \"/\" mappings with the same\ncollage instance.\n\n**Note well:** also in this case collage assumes the mapped registries are using TLS.\nYou must be explicit about registries **not** using TLS: provide the `http://`\nprefix inside of their URL.\n\n\n# A nice use case\n\nMy team is building different docker images in an automated fashion. The images\nare pushed to an internal registry (*registry.local.lan*) under a special\nrepository (`kubic/v3/`).\n\nAfter an internal process the images are promoted to a production registry\n(*registry.production.lan*) inside of a different repository (`/caasp`).\n\nWhile developing we don't want to rewrite all our kubernetes manifest files,\nhelm charts, Dockerfile(s),... to point at `registry.local.lan/kubic/v3/...`.\nFor example we would like to keep referencing `velum:2.0` image as\n`registry.production.lan/caasp/velum:2.0` instead of\n`registry.local.lan/kubic/v3/velum:2.0`.\n\nWith collage we can setup a mapping like the following one:\n\n```json\n\"mappings\": {\n  \"caasp\": \"registry.local.lan/kubic/v3\"\n}\n```\n\nBy doing that we can do a `docker pull collage.local.lan/caasp/velum:2.0`\nand get our image downloaded.\n\nWe are almost there: the repository, name and tags are fine, but the registry\nname is not (it's `collage.local.lan` instead of `registry.production.lan`).\n\n## Enter docker mirroring\n\nWe have been working upstream to allow Docker to handle mirroring of 3rd party\nregistries. The work is ongoing [here](https://github.com/moby/moby/pull/34319).\n\nWith this patch in place we just have to configure `collage.local.lan` to\nbe used as a mirror of `registry.production.lan` and then we will be able\nto perform:\n\n```\ndocker pull registry.production.lan/caasp/velum:2.0\n```\n\nBy doing that the docker engine will reach out to `collage.local.lan` looking\nfor `caasp/velum:2.0`. The collage instance will translate all the request\nas redirections to `registry.local.lan/kubic/v3/velum:2.0`. No caching is\ndone by collage, but the final image will have the name we expect.\n\n# Caveats\n\nThis is an experimental project, done for fun over a weekend. It surprisingly\nworks, but there are probably areas to make more robust and bugs ;)\n\nSome known issues:\n\n  * GET catalog: some registries don't allow this request to be performed\n    (eg: docker hub, quay.io); there's nothing collage can do in that case.\n    However everything works as expected if you know what you are looking for.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflavio%2Fcollage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflavio%2Fcollage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflavio%2Fcollage/lists"}