{"id":13582504,"url":"https://github.com/ipdr/ipdr","last_synced_at":"2025-04-04T15:11:12.388Z","repository":{"id":41157450,"uuid":"158306529","full_name":"ipdr/ipdr","owner":"ipdr","description":"🐋 IPFS-backed Docker Registry","archived":false,"fork":false,"pushed_at":"2024-07-24T20:50:49.000Z","size":10747,"stargazers_count":539,"open_issues_count":9,"forks_count":47,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-10-29T14:19:02.915Z","etag":null,"topics":["cdn","docker","docker-registry","go","golang","interplanetary","ipfs","ipfs-protocol","p2p"],"latest_commit_sha":null,"homepage":"https://github.com/miguelmota/ipdr","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ipdr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["miguelmota"],"patreon":"miguelmota"}},"created_at":"2018-11-20T00:11:20.000Z","updated_at":"2024-10-28T17:35:20.000Z","dependencies_parsed_at":"2024-01-05T20:46:26.520Z","dependency_job_id":"e3ef5a20-00e4-429c-847f-1ff8a1018f50","html_url":"https://github.com/ipdr/ipdr","commit_stats":{"total_commits":70,"total_committers":5,"mean_commits":14.0,"dds":"0.24285714285714288","last_synced_commit":"4ef92b38a0662ab0c9e043d54d01d7ca76fe8ed2"},"previous_names":["miguelmota/ipdr"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipdr%2Fipdr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipdr%2Fipdr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipdr%2Fipdr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ipdr%2Fipdr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ipdr","download_url":"https://codeload.github.com/ipdr/ipdr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182389,"owners_count":20897381,"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":["cdn","docker","docker-registry","go","golang","interplanetary","ipfs","ipfs-protocol","p2p"],"created_at":"2024-08-01T15:02:46.680Z","updated_at":"2025-04-04T15:11:12.367Z","avatar_url":"https://github.com/ipdr.png","language":"Go","funding_links":["https://github.com/sponsors/miguelmota","https://patreon.com/miguelmota"],"categories":["Go","p2p"],"sub_categories":[],"readme":"\u003ch3 align=\"center\"\u003e\n  \u003cbr /\u003e\n  \u003cimg src=\"https://user-images.githubusercontent.com/168240/52895983-7330f100-3176-11e9-855c-246eaabd3adc.png\" alt=\"logo\" width=\"600\" /\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n\u003c/h3\u003e\n\n# IPDR: InterPlanetary Docker Registry\n\n\u003e [IPFS](https://github.com/ipfs/go-ipfs)-backed [Docker](https://github.com/docker/docker) Registry\n\n[![License](http://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/ipdr/ipdr/master/LICENSE)\n[![CircleCI](https://circleci.com/gh/ipdr/ipdr.svg?style=svg)](https://circleci.com/gh/ipdr/ipdr)\n[![Go Report Card](https://goreportcard.com/badge/github.com/ipdr/ipdr?)](https://goreportcard.com/report/github.com/ipdr/ipdr)\n[![GoDoc](https://godoc.org/github.com/ipdr/ipdr?status.svg)](https://godoc.org/github.com/ipdr/ipdr)\n[![stability-experimental](https://img.shields.io/badge/stability-experimental-orange.svg)](https://github.com/emersion/stability-badges#experimental)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#contributing)\n\nIPDR is a [Docker Registry](https://docs.docker.com/registry/) tool that proxies Docker registry requests to IPFS for pushing and pulling images. IPDR allows you to store Docker images on IPFS instead of a central registry like Docker Hub or Google Container Registry. Docker images are referenced by their IPFS hash instead of the repo tag names.\n\nIPDR is compatabile with the *Docker Registry HTTP [API V2 Spec](https://docs.docker.com/registry/spec/api/)* for pulling images\u0026ast;\n\n\u003csup\u003e\u003csub\u003e\u0026ast;not fully 1:1 implemented yet\u003c/sub\u003e\u003c/sup\u003e\n\nHigh-level overview:\n\n\u003cimg src=\"https://user-images.githubusercontent.com/168240/52923314-14858780-32dc-11e9-80f8-9a0025de6090.png\" alt=\"logo\" width=\"500\" /\u003e\n\n## Contents\n\n- [Install](#install)\n- [Getting started](#getting-started)\n- [CLI](#cli)\n- [Test](#test)\n- [FAQ](#faq)\n- [Contributing](#contributing)\n- [Resources](#resources)\n- [License](#license)\n\n## Install\n\n- Install with [Go](https://golang.org/doc/install):\n\n    ```bash\n    go get -u github.com/ipdr/ipdr/cmd/ipdr\n    ```\n\n- Install from [release binaries](https://github.com/ipdr/ipdr/releases):\n\n    ```bash\n    # replace x.x.x with the latest version\n    wget https://github.com/ipdr/ipdr/releases/download/x.x.x/ipdr_x.x.x_linux_amd64.tar.gz\n    tar -xvzf ipdr_x.x.x_linux_amd64.tar.gz ipdr\n    ./ipdr --help\n\n    # move to bin path\n    sudo mv ipdr /usr/local/bin/ipdr\n    ```\n\n## Getting started\n\n### Prerequisites\n\n- Start IPFS daemon ([Install instructions](https://docs.ipfs.io/introduction/install/)):\n\n    ```bash\n    $ ipfs daemon\n    Initializing daemon...\n    Swarm listening on /ip4/127.0.0.1/tcp/4001\n    Swarm listening on /ip4/192.168.86.90/tcp/4001\n    Swarm listening on /ip6/::1/tcp/4001\n    Swarm listening on /p2p-circuit/ipfs/QmR29wrbNv3WrMuodwuLiDwvskuZKKeTtcYDw7SwNffzCH\n    Swarm announcing /ip4/127.0.0.1/tcp/4001\n    Swarm announcing /ip4/192.168.0.21/tcp/43042\n    Swarm announcing /ip4/192.168.86.90/tcp/4001\n    Swarm announcing /ip6/::1/tcp/4001\n    API server listening on /ip4/0.0.0.0/tcp/5001\n    Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080\n    Daemon is ready\n    ```\n\n- Add `docker.local` to `/etc/hosts`:\n\n    ```hosts\n    echo '127.0.0.1 docker.local' | sudo tee -a /etc/hosts\n    echo '::1       docker.local' | sudo tee -a /etc/hosts\n    ```\n\n    - Flush local DNS cache:\n\n      - on macOS:\n\n          ```bash\n          dscacheutil -flushcache; sudo killall -HUP mDNSResponder\n          ```\n\n      - on Ubuntu 18+:\n\n          ```bash\n          sudo systemd-resolve --flush-caches\n          ```\n\n### Example flow\n\n- Create `Dockerfile`:\n\n    ```dockerfile\n    FROM busybox:latest\n\n    CMD echo 'hello world'\n    ```\n\n- Build Docker image:\n\n    ```bash\n    docker build -t example/helloworld .\n    ```\n\n    Test run:\n\n    ```bash\n    $ docker run example/helloworld:latest\n    hello world\n    ```\n\n- Use IPDR CLI to push to IPFS:\n\n    ```bash\n    $ ipdr push example/helloworld\n\n    INFO[0000] [registry] temp: /var/folders/k1/m2rmftgd48q97pj0xf9csdb00000gn/T/205139235\n    INFO[0000] [registry] preparing image in: /var/folders/k1/m2rmftgd48q97pj0xf9csdb00000gn/T/657143846\n    INFO[0000]\n    [registry] dist: /var/folders/k1/m2rmftgd48q97pj0xf9csdb00000gn/T/657143846/default/blobs/sha256:305510b2c684403553fd8f383e8d109b147df2cfde60e40a85564532c383c8b8\n    INFO[0000] [registry] compressing layer: /var/folders/k1/m2rmftgd48q97pj0xf9csdb00000gn/T/205139235/886f4bdfa483cc176e947c63d069579785c051793a9634f571fded7b9026cd3c/layer.tar\n    INFO[0000] [registry] root dir: /var/folders/k1/m2rmftgd48q97pj0xf9csdb00000gn/T/657143846\n    INFO[0000] [registry] upload hash QmRxZ5Wffj6b1j8ckJLcr7yFrbHUhBYXsAMbj7Krwu1pp8\n    INFO[0000]\n    [registry] uploaded to /ipfs/Qmc2ot2NQadXmbvPbsidyjYDvPfPwKZmovzNpfRPKxXUrL\n    INFO[0000] [registry] docker image ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi\n\n    Successfully pushed Docker image to IPFS:\n    /ipfs/Qmc2ot2NQadXmbvPbsidyjYDvPfPwKZmovzNpfRPKxXUrL\n    ```\n\n- Use IPDR CLI to pull from IPFS:\n\n    ```bash\n    $ ipdr pull /ipfs/QmagW4H1uE5rkm8A6iVS8WuiyjcWQzqXRHbM3KuUfzrCup\n\n    INFO[0000] [registry/server] port 5000\n    INFO[0000] [registry] attempting to pull docker.local:5000/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi\n    INFO[0000] [registry/server] /v2/\n    INFO[0000] [registry/server] /v2/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi/manifests/latest\n    INFO[0000] [registry/server] location http://127.0.0.1:8080/ipfs/Qmc2ot2NQadXmbvPbsidyjYDvPfPwKZmovzNpfRPKxXUrL/manifests/latest-v2\n    {\"status\":\"Pulling from ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi\",\"id\":\"latest\"}\n    {\"status\":\"Digest: sha256:1fb36e4704d6ebad5becdcfe996807de5f8db687da396330f112157c888c165b\"}\n    {\"status\":\"Status: Downloaded newer image for docker.local:5000/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi:latest\"}\n\n    Successfully pulled Docker image from IPFS:\n    docker.local:5000/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi\n    ```\n\n- Run image pulled from IPFS:\n\n    ```bash\n    $ docker run docker.local:5000/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi\n    hello world\n    ```\n\n- Retag Docker image:\n\n    ```bash\n    $ docker tag docker.local:5000/ciqmw4mig2uwaygddjlutoywq43udutvdmuxkcxvetsjp2mjdde27wi example/helloworld:latest\n    ```\n\n- We can also pull the image using `docker pull`:\n    - First run the IPDR server in a seperate terminal:\n\n        ```bash\n        $ ipdr server -p 5000\n        INFO[0000] [registry/server] listening on [::]:5000\n        ```\n\n    - Then convert the IPFS hash to a valid format docker allows:\n\n        ```bash\n        $ ipdr convert QmYMg6WAuvF5i5yFmjT8KkqewZ5Ngh4U9Mp1bGfdjraFVk --format=docker\n\n        ciqjjwaeoszdgcaasxmlhjuqnhbctgwijqz64w564lrzeyjezcvbj4y\n        ```\n\n    - Now we can `docker pull` the image from IPFS:\n\n        ```bash\n        $ docker pull docker.local:5000/ciqjjwaeoszdgcaasxmlhjuqnhbctgwijqz64w564lrzeyjezcvbj4y\n        Using default tag: latest\n        latest: Pulling from ciqjjwaeoszdgcaasxmlhjuqnhbctgwijqz64w564lrzeyjezcvbj4y\n        Digest: sha256:6b787c9e04c2038d4b3cb0392417abdddfcfd88e10005d970fc751cdcfd6d895\n        Status: Downloaded newer image for docker.local:5000/ciqjjwaeoszdgcaasxmlhjuqnhbctgwijqz64w564lrzeyjezcvbj4y:latest\n        ```\n\n        Test run:\n\n        ```bash\n        $ docker run docker.local:5000/ciqjjwaeoszdgcaasxmlhjuqnhbctgwijqz64w564lrzeyjezcvbj4y\n        hello world\n        ```\n\n### TLDR; example\n\n```bash\n# build Docker image\ndocker build -t example/helloworld .\n\n# push to IPFS\nIPFS_HASH=\"$(ipdr push example/helloworld --silent)\"\n\n# pull from IPFS\nREPO_TAG=$(ipdr pull \"$IPFS_HASH\" --silent)\n\n# run image pulled from IPFS\ndocker run \"$REPO_TAG\"\n```\n\n## CLI\n\n```bash\n$ ipdr --help\n\nThe command-line interface for the InterPlanetary Docker Registry.\nMore info: https://github.com/ipdr/ipdr\n\nUsage:\n  ipdr [flags]\n  ipdr [command]\n\nAvailable Commands:\n  convert     Convert a hash to IPFS format or Docker registry format\n  help        Help about any command\n  pull        Pull image from the IPFS-backed Docker registry\n  push        Push image to IPFS-backed Docker registry\n  server      Start IPFS-backed Docker registry server\n\nFlags:\n  -h, --help   help for ipdr\n\nUse \"ipdr [command] --help\" for more information about a command.\n```\n\n## IPNS\n\nAn example of using IPNS to resolve image tag names.\n\n1. First start local server:\n\n```bash\nipdr server -p 5000\n```\n\n2. Tag the image:\n\n```bash\ndocker pull hello-world\ndocker tag hello-world docker.local:5000/hello-world\n```\n\n3. Push to local registry:\n\n```bash\ndocker push --quiet docker.local:5000/hello-world\n```\n\nCID mappings live under `~/.ipdr`\n\n```bash\n$ tree ~/.ipdr/\n/home/username/.ipdr/\n└── cids\n    └── hello-world\n        └── latest\n```\n\n4. Add cids directory to IPFS:\n\n```bash\n$ ipfs add -r ~/.ipdr/cids/ --quieter\nQmVtjwa3kdFJHce2wnFuygaCHdSPXraBd4FRSEZKjqZWQp\n```\n\n5. Set `_dnslink` TXT record on the domain to point to the directory IPFS hash:\n\n```\ndnslink=/ipfs/QmVtjwa3kdFJHce2wnFuygaCHdSPXraBd4FRSEZKjqZWQp\n```\n\n6. Verify DNS changes:\n\n```bash\n$ dig _dnslink.example.com -t TXT +short\n\"dnslink=/ipfs/QmVtjwa3kdFJHce2wnFuygaCHdSPXraBd4FRSEZKjqZWQp\"\n```\n\n7. Re-run server, now with domain as resolver:\n\n```bash\n$ ipdr server --cid-resolver=example.com\n```\n\n8. Now we can run ipdr dig to get CID using repo tag name!\n\n```bash\n$ ipdr dig hello-world:latest\nbafybeiakvswzlopeu573372p5xry47tkc2hhcg5q5rulmbfrnkecrbnt3y\n```\n\nNote: if nothing is returned, then make sure the IPFS gateway is correct.\n\n9. Next pull and the docker image from IPFS using the resolved CID formatted for docker:\n\n```bash\ndocker pull docker.local:5000/bafybeiakvswzlopeu573372p5xry47tkc2hhcg5q5rulmbfrnkecrbnt3y\ndocker run docker.local:5000/bafybeiakvswzlopeu573372p5xry47tkc2hhcg5q5rulmbfrnkecrbnt3y\n```\n\n## Test\n\n```bash\nmake test\n```\n\n## FAQ\n\n- Q: How do I configure the local registry host or port that IPDR uses when pushing or pulling Docker images?\n\n  - A: Use the `--docker-registry-host` flag, eg. `--docker-registry-host docker.for.mac.local:5000`\n\n- Q: How do I configure the IPFS host that IPDR uses for pushing Docker images?\n\n  - A: Use the `--ipfs-host` flag, eg. `--ipfs-host 127.0.0.1:5001`\n\n- Q: How do I configure the IPFS gateway that IPDR uses for pulling Docker images?\n\n  - A: Use the `--ipfs-gateway` flag, eg. `--ipfs-gateway https://ipfs.io`\n\n- Q: How can I configure the port for the IPDR registry server?\n\n  - A: Use the `--port` flag, eg. `--port 5000`\n\n- Q: How do I setup HTTPS/TLS on the IPDR registry server?\n\n  - A: Use the `--tlsKeyPath` and `--tlsCertPath` flag, eg. ` --tlsKeyPath path/server.key --tlsCertPath path/server.crt`\n\n- Q: How do I get `docker.local` to work?\n\n  - A: Make sure to add `127.0.0.1  docker.local` to `/etc/hosts`. Optionally, you may use `local.ipdr.io` which resolves to `127.0.0.1`\n\n## Contributing\n\nPull requests are welcome!\n\nFor contributions please create a new branch and submit a pull request for review.\n\n_Many thanks to [@qiangli](https://github.com/qiangli) and all the [contributors](https://github.com/ipdr/ipdr/graphs/contributors) that made this package better._\n\n## Social\n\n- Discuss on [Discord](https://discord.gg/7GJwMjedjh)\n\n## Resources\n\n- [Docker Registry HTTP API V2 Spec](https://docs.docker.com/registry/spec/api/)\n- [Docker Registry 2.0 (slidedeck)](https://www.slideshare.net/Docker/docker-48351569)\n- [image2ipfs](https://github.com/jvassev/image2ipfs/)\n\n## License\n\nReleased under the [MIT](./LICENSE) license.\n\n© [Miguel Mota](https://github.com/miguelmota)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipdr%2Fipdr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fipdr%2Fipdr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipdr%2Fipdr/lists"}