{"id":13509094,"url":"https://github.com/NVIDIA/container-canary","last_synced_at":"2025-03-30T13:31:24.640Z","repository":{"id":41209821,"uuid":"470275149","full_name":"NVIDIA/container-canary","owner":"NVIDIA","description":"A tool for testing and validating container requirements against versioned manifests","archived":false,"fork":false,"pushed_at":"2025-03-26T15:07:38.000Z","size":151,"stargazers_count":260,"open_issues_count":14,"forks_count":16,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T15:02:11.299Z","etag":null,"topics":["automation","ci","containers","docker","kubernetes","podman","utilities","versioning"],"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/NVIDIA.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-15T17:58:50.000Z","updated_at":"2025-03-28T17:30:09.000Z","dependencies_parsed_at":"2024-01-13T19:24:23.571Z","dependency_job_id":"e8319b80-7cbc-4941-8972-66a9ef2d9b53","html_url":"https://github.com/NVIDIA/container-canary","commit_stats":{"total_commits":70,"total_committers":6,"mean_commits":"11.666666666666666","dds":"0.15714285714285714","last_synced_commit":"c47389618e547db3d572ddfd62e3357449880ec9"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NVIDIA%2Fcontainer-canary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NVIDIA%2Fcontainer-canary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NVIDIA%2Fcontainer-canary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NVIDIA%2Fcontainer-canary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NVIDIA","download_url":"https://codeload.github.com/NVIDIA/container-canary/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246323880,"owners_count":20759044,"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":["automation","ci","containers","docker","kubernetes","podman","utilities","versioning"],"created_at":"2024-08-01T02:01:02.856Z","updated_at":"2025-03-30T13:31:24.604Z","avatar_url":"https://github.com/NVIDIA.png","language":"Go","funding_links":[],"categories":["Go","automation","Applications"],"sub_categories":["Cloud and DevOps"],"readme":"# Container Canary\n\n[![Test](https://github.com/NVIDIA/container-canary/actions/workflows/test.yaml/badge.svg)](https://github.com/NVIDIA/container-canary/actions/workflows/test.yaml)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/nvidia/container-canary)\n![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/nvidia/container-canary?label=version)\n\nA little bird to validate your container images.\n\n```console\n$ canary validate --file examples/awesome.yaml your/container:latest\nValidating your/container:latest against awesome\n 📦 Required packages are installed                  [passed]\n 🤖 Expected services are running                    [passed]\n 🎉 Your container is awesome                        [passed]\nvalidation passed\n```\n\nMany modern compute platforms support bring-your-own-container models where the user can provide container images with their custom software environment. However platforms commonly have a set of requirements that the container must conform to, such as using a non-root user, having the home directory in a specific location, having certain packages installed or running web applications on specific ports.\n\nContainer Canary is a tool for recording those requirements as a manifest that can be versioned and then validating containers against that manifest. This is particularly useful in CI environments to avoid regressions in containers.\n\n- [Container Canary](#container-canary)\n  - [Installation](#installation)\n  - [Example (Kubeflow)](#example-kubeflow)\n  - [Validator reference](#validator-reference)\n    - [Metadata](#metadata)\n    - [Runtime options](#runtime-options)\n      - [Environment variables](#environment-variables)\n      - [Ports](#ports)\n      - [Volumes](#volumes)\n      - [Command](#command)\n    - [Checks](#checks)\n      - [Exec](#exec)\n      - [HTTPGet](#httpget)\n      - [TCPSocket](#tcpsocket)\n      - [Delays, timeouts, periods and thresholds](#delays-timeouts-periods-and-thresholds)\n  - [Contributing](#contributing)\n  - [Maintaining](#maintaining)\n  - [License](#license)\n\n## Installation\n\nYou can find binaries and instructions on [our releases page](https://github.com/NVIDIA/container-canary/releases).\n\n## Example (Kubeflow)\n\nThe [Kubeflow](https://www.kubeflow.org/) documentation has a [list of requirements](https://www.kubeflow.org/docs/components/notebooks/container-images/#custom-images) for container images that can be used in the [Kubeflow Notebooks](https://www.kubeflow.org/docs/components/notebooks/) service.\n\nThat list looks like this:\n\n- expose an HTTP interface on port `8888`:\n  - kubeflow sets an environment variable `NB_PREFIX` at runtime with the URL path we expect the container be listening under\n  - kubeflow uses IFrames, so ensure your application sets `Access-Control-Allow-Origin: *` in HTTP response headers\n- run as a user called `jovyan`:\n  - the home directory of `jovyan` should be `/home/jovyan`\n  - the UID of `jovyan` should be `1000`\n- start successfully with an empty PVC mounted at `/home/jovyan`:\n  - kubeflow mounts a PVC at `/home/jovyan` to keep state across Pod restarts\n\nWith Container Canary we could write this list as the following YAML spec.\n\n```yaml\n# examples/kubeflow.yaml\napiVersion: container-canary.nvidia.com/v1\nkind: Validator\nname: kubeflow\ndescription: Kubeflow notebooks\nenv:\n  - name: NB_PREFIX\n    value: /hub/jovyan/\nports:\n  - port: 8888\n    protocol: TCP\nvolumes:\n  - mountPath: /home/jovyan\nchecks:\n  - name: user\n    description: 👩 User is jovyan\n    probe:\n      exec:\n        command:\n          - /bin/sh\n          - -c\n          - \"[ $(whoami) = jovyan ]\"\n  - name: uid\n    description: 🆔 User ID is 1000\n    probe:\n      exec:\n        command:\n          - /bin/sh\n          - -c\n          - \"id | grep uid=1000\"\n  - name: home\n    description: 🏠 Home directory is /home/jovyan\n    probe:\n      exec:\n        command:\n          - /bin/sh\n          - -c\n          - \"[ $HOME = /home/jovyan ]\"\n  - name: http\n    description: 🌏 Exposes an HTTP interface on port 8888\n    probe:\n      httpGet:\n        path: /\n        port: 8888\n      initialDelaySeconds: 10\n  - name: NB_PREFIX\n    description: 🧭 Correctly routes the NB_PREFIX\n    probe:\n      httpGet:\n        path: /hub/jovyan/lab\n        port: 8888\n      initialDelaySeconds: 10\n  - name: allow-origin-all\n    description: \"🔓 Sets 'Access-Control-Allow-Origin: *' header\"\n    probe:\n      httpGet:\n        path: /\n        port: 8888\n        responseHttpHeaders:\n          - name: Access-Control-Allow-Origin\n            value: \"*\"\n      initialDelaySeconds: 10\n```\n\nThe Canary Validator spec reuses parts of the [Kubernetes](https://kubernetes.io/) configuration API including [probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/). In Kubernetes probes are used to check on the health of a pod, but in Container Canary we use them to validate if the container meets our specification.\n\nWe can then run our specification against any desired container image to see a pass/fail breakdown of requirements. We can test one of the default images that ships with Kubeflow as that should pass.\n\n```console\n$ canary validate --file examples/kubeflow.yaml public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-scipy:v1.5.0-rc.1\nValidating public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-scipy:v1.5.0-rc.1 against kubeflow\n 👩 User is jovyan                                   [passed]\n 🆔 User ID is 1000                                  [passed]\n 🏠 Home directory is /home/jovyan                   [passed]\n 🌏 Exposes an HTTP interface on port 8888           [passed]\n 🧭 Correctly routes the NB_PREFIX                   [passed]\n 🔓 Sets 'Access-Control-Allow-Origin: *' header     [passed]\nvalidation passed\n```\n\nFor more examples [see the examples directory](examples/).\n\n## Validator reference\n\nValidator manifests are YAML files that describe how to validate a container image. Check out the [examples](examples/) directory for real world applications.\n\n### Metadata\n\nEach manifests starts with some metadata.\n\n```yaml\n# Manifest versioning\napiVersion: container-canary.nvidia.com/v1\nkind: Validator\n\n# Metadata\nname: foo  # The name of the platform that this manifest validates for\ndescription: Foo runs containers for you  # A description of that platform\ndocumentation: https://example.com  # A link to the documentation that defines the container requirements in prose\n```\n\n### Runtime options\n\nNext you can set runtime configuration for the container you are validating. You should set these to mimic the environment that the compute platform will create. When you validate a container it will be run locally using [Docker](https://www.docker.com/).\n\n#### Environment variables\n\nA list of environment variables that should be set on the container.\n\n```yaml\nenv:\n  - name: HELLO\n    value: world\n  - name: FOO\n    value: bar\n```\n\n#### Ports\n\nPorts that need to be exposed on the container. These need to be configured in order for Container Canary to perform connectivity tests.\n\n```yaml\nports:\n  - port: 8888\n    protocol: TCP\n```\n\n#### Volumes\n\nVolumes to be mounted to the container. This is useful if the compute platform will always mount an empty volume to a specific location.\n\n```yaml\nvolumes:\n  - mountPath: /home/jovyan\n```\n\n#### Command\n\nYou can specify a custom command to be run inside the container.\n\n```yaml\ncommand:\n - foo\n - --bar=true\n```\n\n### Checks\n\nChecks are the tests that we want to run against the container to ensure it is compliant. Each check contains a probe, and those probes are superset of the Kubernetes [probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) API and so any valid Kubernetes probe can be used in a check.\n\n```yaml\nchecks:\n  - name: mycheck  # Name of the check\n    description: Ensuring a thing  # Descrption of what is being checked (will be used in output)\n    probe:\n      ...  # A probe to run\n```\n\n#### Exec\n\nAn exec check runs a command inside the running container. If the command exits with `0` the check will pass.\n\n```yaml\nchecks:\n  - name: uid\n    description: User ID is 1234\n    probe:\n      exec:\n        command:\n          - /bin/sh\n          - -c\n          - \"id | grep uid=1234\"\n```\n\n#### HTTPGet\n\nAn HTTP Get check will perform an HTTP GET request against your container. If the response code is `\u003c300` and the optional response headers match the check will pass.\n\n```yaml\nchecks:\n  - name: http\n    description: Exposes an HTTP interface on port 80\n    probe:\n      httpGet:\n        path: /\n        port: 80\n        httpHeaders:  # Optional, headers to set in the request\n          - name: Foo-Header\n            value: \"myheader\"\n        responseHttpHeaders:  # Optional, headers that you expect to see in the response\n          - name: Access-Control-Allow-Origin\n            value: \"*\"\n```\n\n#### TCPSocket\n\nA TCP Socket check will ensure something is listening on a specific TCP port.\n\n```yaml\nchecks:\n  - name: tcp\n    description: Is listening via TCP on port 80\n    probe:\n      tcpSocket:\n        port: 80\n```\n\n#### Delays, timeouts, periods and thresholds\n\nChecks also support the same delays, timeouts, periods and thresholds that Kubernetes probes do.\n\n```yaml\nchecks:\n  - name: uid\n    description: User ID is 1234\n    probe:\n      exec:\n        command: [...]\n      initialDelaySeconds: 0  # Delay after starting the container before the check should be run\n      timeoutSeconds: 30  # Overall timeout for the check\n      successThreshold: 1  # Number of times the check must pass before moving on\n      failureThreshold: 1  # Number of times the check is allowed to fail before giving up\n      periodSeconds: 1  # Interval between runs if threasholds are \u003e1\n```\n\n## Contributing\n\nContributions are very welcome, be sure to review the [contribution guidelines](./CONTRIBUTING.md).\n\n## Maintaining\n\nMaintenance steps [can be found here](./MAINTAINING.md).\n\n## License\n\nApache License Version 2.0, see [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNVIDIA%2Fcontainer-canary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNVIDIA%2Fcontainer-canary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNVIDIA%2Fcontainer-canary/lists"}