{"id":13416419,"url":"https://github.com/ivanilves/lstags","last_synced_at":"2025-04-06T07:15:48.951Z","repository":{"id":23993094,"uuid":"100341708","full_name":"ivanilves/lstags","owner":"ivanilves","description":"Explore Docker registries and manipulate Docker images!","archived":false,"fork":false,"pushed_at":"2023-05-11T20:38:37.000Z","size":12902,"stargazers_count":338,"open_issues_count":10,"forks_count":26,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-30T06:09:10.407Z","etag":null,"topics":["docker","docker-image","docker-registry","docker-registry-v2","kubernetes","mesos"],"latest_commit_sha":null,"homepage":"","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/ivanilves.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}},"created_at":"2017-08-15T05:25:17.000Z","updated_at":"2025-03-30T05:03:02.000Z","dependencies_parsed_at":"2024-01-08T16:09:47.634Z","dependency_job_id":"6d26d8e4-1d9b-4a9f-b439-ee9c2a069c47","html_url":"https://github.com/ivanilves/lstags","commit_stats":null,"previous_names":[],"tags_count":97,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanilves%2Flstags","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanilves%2Flstags/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanilves%2Flstags/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanilves%2Flstags/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivanilves","download_url":"https://codeload.github.com/ivanilves/lstags/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445682,"owners_count":20939961,"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":["docker","docker-image","docker-registry","docker-registry-v2","kubernetes","mesos"],"created_at":"2024-07-30T21:00:58.547Z","updated_at":"2025-04-06T07:15:48.927Z","avatar_url":"https://github.com/ivanilves.png","language":"Go","readme":"[![CircleCI](https://circleci.com/gh/ivanilves/lstags.svg?style=svg)](https://circleci.com/gh/ivanilves/lstags)\n[![Go Report Card](https://goreportcard.com/badge/github.com/ivanilves/lstags)](https://goreportcard.com/report/github.com/ivanilves/lstags)\n[![Coverage Status](https://coveralls.io/repos/github/ivanilves/lstags/badge.svg?branch=master)](https://coveralls.io/github/ivanilves/lstags?branch=master)\n\n![](https://github.com/ivanilves/lstags/raw/master/heading.png)\n\n# L/S tags\n\nUtility and **[API](#api)** to manipulate (analyze, synchronize and aggregate) images across different Docker registries.\n\n### Example invocation\n```\n$ lstags alpine~/^3\\\\./\n\u003cSTATE\u003e      \u003cDIGEST\u003e                                   \u003c(local) ID\u003e    \u003cCreated At\u003e          \u003cTAG\u003e\nABSENT       sha256:9363d03ef12c8c25a2def8551e609f146   n/a             2017-09-13T16:32:00   alpine:3.1\nCHANGED      sha256:9866438860a1b28cd9f0c944e42d3f6cd   39be345c901f    2017-09-13T16:32:05   alpine:3.2\nABSENT       sha256:ae4d16d132e3c93dd09aec45e4c13e9d7   n/a             2017-09-13T16:32:10   alpine:3.3\nCHANGED      sha256:0d82f2f4b464452aac758c77debfff138   f64255f97787    2017-09-13T16:32:15   alpine:3.4\nPRESENT      sha256:129a7f8c0fae8c3251a8df9370577d9d6   074d602a59d7    2017-09-13T16:32:20   alpine:3.5\nPRESENT      sha256:f006ecbb824d87947d0b51ab8488634bf   76da55c8019d    2017-09-13T16:32:26   alpine:3.6\n```\n**NB!** You can specify many images to operate on, e.g: `lstags nginx~/^1\\\\.13/ mesosphere/chronos alpine~/^3\\\\./`\n\n## Why would someone use this?\nYou could use `lstags`, if you ...\n* ... aggregate images from different external registries into your own registry for **speed and locality** reasons.\n* ... compare images present locally with the registry ones (e.g.: know if image tagged \"latest\" was re-pushed).\n* ... continuously pull Docker images from some public or private registry to speed-up Docker run on your system.\n\n### How?\n... pull Ubuntu 14.04 \u0026 16.04, all the Alpine images and Debian \"stretch\" to have the latest software to play with:\n```sh\nlstags --pull ubuntu~/^1[46]\\\\.04$/ alpine debian~/stretch/\n```\n... pull and re-push CoreOS-related images from `quay.io` to your own registry (in case these hipsters will break everything):\n```sh\nlstags -P /quay -r registry.company.io quay.io/coreos/hyperkube quay.io/coreos/flannel\n```\n**NB!** In case you use private registry with authentication, make sure your Docker client knows how to authenticate against it!\n`lstags` will reuse credentials saved by Docker client in its `config.json` file, one usually found at `~/.docker/config.json`\n\n## Possible image states\n`lstags` distinguishes five states of Docker image:\n* `ABSENT` - present in registry, but absent locally\n* `PRESENT` -  present in registry, present locally, with local and remote digests being equal\n* `CHANGED` - present in registry, present locally, but with **different** local and remote digests\n* `LOCAL_ONLY` - present locally, absent in registry\n* `NOT_FOUND` - absent in registry, absent locally, probably does not exist at all\n\n## Authentication\nYou can either:\n* rely on `lstags` discovering credentials \"automagically\" :tophat:\n* load credentials from any Docker JSON config file specified\n\n## Assume tags\nSometimes registry may contain tags not exposed to any kind of search though still existing.\n`lstags` is unable to discover these tags, but if you need to pull or push them, you may \"assume\"\nthey exist and make `lstags` blindly try to pull these tags from the registry. To inject assumed\ntags into the registry query you need to extend repository specification with a `=` followed by a\ncomma-separated list of tags you want to assume.\n\ne.g. we assume tags `v1.6.1` and `v1.7.0` exist like this: `lstags quay.io/calico/cni=v1.6.1,v1.7.0`\n\n## Repository specification\nFull repository specification looks like this:\n```\n[REGISTRY[:PORT]/]REPOSITORY[~/FILTER_REGEXP/][=TAG1,TAG2,TAGn]\n```\nYou may provide infinite number of repository specifications to `lstags`\n\n## Push prefix\nWhen you [re]push images to your \"push\" registry, you can control the destination repository path prefix:\n* by default, repository path prefix will be auto-generated from the source registry hostname, e.g.:\n  * `alpine` :arrow_forward: `/registry/hub/docker/com/`\n  * `localhost:5000/nginx` :arrow_forward: `/localhost/`\n  * `registry.company.com/hype/kubernetes` :arrow_forward: `/registry/company/com/`\n* passing `--push-prefix=/` will push images \"as is\", with no additional repository path prefix\n* passing `--push-prefix=/my/prefix/` will push images appending `/my/prefix/` to the repository path\n* specifying `/my/prefix` without trailing slash is OK, as long as path would still be formatted correctly by API :sparkles:\n* passing `--push-prefix=\"\"` would trigger \"default\" behavior with prefix being auto-generated\n\n## To fail or not to fail?\nBy default application exits after encountering any errors. To make it more tolerant to subsequent failures, you may use CLI option `-N, --do-not-fail` or set environment variable `DO_NOT_FAIL=true` before running application. HINT: Option `-d, --daemon-mode` always implies activation of `--do-not-fail`.\n\n## YAML\n:bulb: You can load repositories from the YAML file just like you do it from the command line arguments:\n```\nlstags -f file.yaml\n```\nA valid YAML file looks like this (mandatory `lstags` root key is here to be able to use \"shared\" YAMLs):\n```yaml\nlstags:\n  repositories:\n    - busybox\n    - nginx:stable\n    - mesosphere/marathon-lb~/^v1/\n    - quay.io/coreos/awscli=master,latest,edge\n    - gcr.io/google-containers/hyperkube~/^v1\\.(9|10)\\./\n```\n**NB!** `lstags` can load repositories from YAML or from CLI args, but not from both at the same time!\n\n## Install: Binaries\nhttps://github.com/ivanilves/lstags/releases\n\n## Install: Wrapper\n```sh\ngit clone git@github.com:ivanilves/lstags.git\ncd lstags\nsudo make wrapper\nlstags -h\n```\nA special wrapper script will be installed to manage `lstags` invocation and updates. :sunglasses:\n\n## Install: From source\n```sh\ngit clone git@github.com:ivanilves/lstags.git\ncd lstags\ndep ensure\ngo build\n./lstags -h\n```\n**NB!** I assume you have current versions of Go \u0026 [dep](https://github.com/golang/dep) installed and also have set up [GOPATH](https://github.com/golang/go/wiki/GOPATH) correctly.\n\n## Using it with Docker\n\n```\ndocker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock ivanilves/lstags\nUsage:\n  lstags [OPTIONS] REPO1 REPO2 REPOn...\n\nApplication Options:\n  -j, --docker-json=          JSON file with credentials (default:\n                              ~/.docker/config.json) [$DOCKER_JSON]\n  -p, --pull                  Pull Docker images matched by filter (will use\n                              local Docker deamon) [$PULL]\n  -P, --push                  Push Docker images matched by filter to some\n                              registry (See 'push-registry') [$PUSH]\n  -r, --push-registry=        [Re]Push pulled images to a specified remote\n                              registry [$PUSH_REGISTRY]\n\n--- OUTPUT WAS CUT HERE TO SAVE SPACE ---\n```\n\n### Analyze an image\n\n```\ndocker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock ivanilves/lstags alpine~/^3\\\\./\nANALYZE alpine\nFETCHED alpine\n-\n\u003cSTATE\u003e   \u003cDIGEST\u003e                                  \u003c(local) ID\u003e    \u003cCreated At\u003e            \u003cTAG\u003e\nCHANGED   sha256:b40e202395eaec699f2d0c5e01e6d6cb8  76da55c8019d    2017-10-25T23:19:51Z    alpine:3.6\nABSENT    sha256:d95da16498d5d6fb4b907cbe013f95032  n/a             2017-10-25T23:20:18Z    alpine:3.1\nABSENT    sha256:cb275b62f789b211114f28b391fca3cc2  n/a             2017-10-25T23:20:32Z    alpine:3.2\nABSENT    sha256:27af7da847283a947c008592f2b2cd6d2  n/a             2017-10-25T23:20:45Z    alpine:3.3\nCHANGED   sha256:246bbbaa81b28837b64cb9dfc574de958  1a19a71e5d38    2017-10-25T23:20:59Z    alpine:3.4\nCHANGED   sha256:aa96c8dc3815c44d4aceaf1ee7903ce58  37c7be7a096b    2017-10-25T23:21:13Z    alpine:3.5\n-\n```\n\n## Development\n\n**You are very welcome to open pull requests to this repository!** :wink:\n\n:warning: CI build will fail, if your commit messages are not **[semantic](https://github.com/fteem/git-semantic-commits)**!\n\nTo maximize our collaboration efficiency we would humbly ask you to follow these recommendations:\n* Please add reasonable description (what?/why?/etc) to your pull request :exclamation:\n* Your code should pass CI (CircleCI) and a [pretty liberal] code review :mag:\n* If code adds or changes some logic, it should be covered by a unit test :neckbeard:\n* Please, put meaningful and [semantic](https://github.com/fteem/git-semantic-commits) messages on your commits :pray:\n\n**NB!** Not a requirement, but a GIF included in PR description would make our world a happier place!\n\n### 'NORELEASE' branches and commits\n**We have automatic release system.** Every PR merge will create a new application release with a changelog generated from PR branch commits.\nFor the most cases it is OK. However, if you work with things that do not need to be released (e.g. non user-facing changes), you have following options:\n* If you don't want to create release from your PR, make it from branch containing \"NORELEASE\" keyword in its name.\n* If you want to prevent single commit from appearing in a changelog, please start commit message with \"NORELEASE\".\n\n:warning: We don't build RPMs/DEBs/etc, as we see no need for it. We ship `lstags` as a single binary or as a Docker container.\n\n## API\n\nYou may use lstags either as a standalone CLI or as a Golang package inside your own application.\n\n#### Set up and build PoC application with our `v1` API:\n\n```sh\nmake poc-app APP_PATH=../lstags-api\ncd ../lstags-api\ngo build\n# run \"./lstags-api\" binary to see PoC in action (examine main.go first to ensure no \"rm -rf /\" is there)\n```\n\n* This installs all necessary dependencies and sets up PoC application at the path `../lstags-api/`\n* We assume you already have recent Golang version installed on your system https://golang.org/dl/\n\n### GoDoc\n* https://godoc.org/github.com/ivanilves/lstags/api/v1\n* https://godoc.org/github.com/ivanilves/lstags/api/v1/collection\n* https://godoc.org/github.com/ivanilves/lstags/repository\n* https://godoc.org/github.com/ivanilves/lstags/tag\n\n**NB!** Far more complete API usage example could be found in **[main.go](https://github.com/ivanilves/lstags/blob/master/main.go)** :wink:\n","funding_links":[],"categories":["Docker Images","Development","Software Packages","Go","软件包","DevOps Tools","Go Tools","Go 工具"],"sub_categories":["Base Tools","Docker","DevOps Tools","Devops","devops 工具","DevOps工具","Contents","DevOps 工具","代码分析"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanilves%2Flstags","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivanilves%2Flstags","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanilves%2Flstags/lists"}