{"id":16243220,"url":"https://github.com/sgtsilvio/gradle-oci","last_synced_at":"2025-10-27T18:13:57.535Z","repository":{"id":57512958,"uuid":"522265898","full_name":"SgtSilvio/gradle-oci","owner":"SgtSilvio","description":"Gradle plugin to ease using and producing (multi-arch) OCI images without requiring external tools","archived":false,"fork":false,"pushed_at":"2024-04-11T07:28:02.000Z","size":1195,"stargazers_count":26,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-11T08:35:54.982Z","etag":null,"topics":["dependency-management","docker","docker-image","dockerhub","gradle-plugin","multiarch","oci","oci-image"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","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/SgtSilvio.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}},"created_at":"2022-08-07T16:31:57.000Z","updated_at":"2024-05-31T15:45:40.258Z","dependencies_parsed_at":"2023-02-16T01:45:55.860Z","dependency_job_id":"6511dde1-b2ce-4782-a048-480e8557b645","html_url":"https://github.com/SgtSilvio/gradle-oci","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SgtSilvio%2Fgradle-oci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SgtSilvio%2Fgradle-oci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SgtSilvio%2Fgradle-oci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SgtSilvio%2Fgradle-oci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SgtSilvio","download_url":"https://codeload.github.com/SgtSilvio/gradle-oci/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244010926,"owners_count":20383333,"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":["dependency-management","docker","docker-image","dockerhub","gradle-plugin","multiarch","oci","oci-image"],"created_at":"2024-10-10T14:14:12.574Z","updated_at":"2025-10-27T18:13:57.528Z","avatar_url":"https://github.com/SgtSilvio.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gradle OCI Plugin\n\n[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.sgtsilvio.gradle.oci?color=brightgreen\u0026style=for-the-badge)](https://plugins.gradle.org/plugin/io.github.sgtsilvio.gradle.oci)\n[![GitHub](https://img.shields.io/github/license/sgtsilvio/gradle-oci?color=brightgreen\u0026style=for-the-badge)](LICENSE)\n[![GitHub Workflow Status (with branch)](https://img.shields.io/github/actions/workflow/status/sgtsilvio/gradle-oci/check.yml?branch=main\u0026style=for-the-badge)](https://github.com/SgtSilvio/gradle-oci/actions/workflows/check.yml?query=branch%3Amain)\n\nGradle plugin to ease using and producing (multi-arch) OCI images without requiring external tools.\n\n## OCI / Docker Conformance\n\nOCI is the acronym of the [Open Container Initiative](https://github.com/opencontainers) that creates open standards around container technology, previously mainly driven by Docker.\nPeople still commonly use the term _Docker image_ even if talking about _OCI images_.\nSo if you are looking for building Docker images, you are right here.\nWhenever OCI is mentioned on this page, just think of it as the successor of Docker (simplified).\n\nThis plugin allows:\n- Building OCI images according to the [OCI Image Format Specification](https://github.com/opencontainers/image-spec)\n- Pulling and pushing images from/to OCI registries according to the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec)\n\n## How to Use\n\nThe following is an example of a basic hello world Java application that is bundled as an OCI image and then executed as a Testcontainer in a JUnit test (using an [integration of gradle-oci and junit-jupiter](https://github.com/SgtSilvio/gradle-oci-junit-jupiter)).\n\n`settings.gradle.kts`\n\n```kotlin\nrootProject.name = \"oci-demo\"\n```\n\n`build.gradle.kts`\n\n```kotlin\nplugins {\n    java\n    id(\"io.github.sgtsilvio.gradle.oci\") version \"0.24.0\"\n}\n\ngroup = \"org.example\"\nversion = \"1.0.0\"\n\ntasks.jar {\n    manifest.attributes[\"Main-Class\"] = \"org.example.oci.demo.Main\"\n}\n\nrepositories {\n    mavenCentral()\n}\n\noci {\n    registries {\n        dockerHub {\n            optionalCredentials()\n        }\n    }\n    imageDefinitions.register(\"main\") {\n        allPlatforms {\n            dependencies {\n                runtime(\"library:eclipse-temurin:21.0.2_13-jre-jammy\")\n            }\n            config {\n                entryPoint = listOf(\"java\", \"-jar\")\n                entryPoint.add(tasks.jar.flatMap { it.archiveFileName })\n            }\n            layer(\"jar\") {\n                contents {\n                    from(tasks.jar)\n                }\n            }\n        }\n    }\n}\n\ntesting {\n    suites {\n        \"test\"(JvmTestSuite::class) {\n            useJUnitJupiter()\n            dependencies {\n                implementation(\"org.testcontainers:testcontainers:1.20.0\")\n                implementation(\"io.github.sgtsilvio:gradle-oci-junit-jupiter:0.7.0\")\n            }\n            oci.of(this) {\n                imageDependencies {\n                    runtime(project)\n                }\n            }\n        }\n    }\n}\n```\n\n`src/main/java/org/example/oci/demo/Main.java`\n\n```java\npackage org.example.oci.demo;\n\npublic class Main {\n    public static void main(final String[] args) {\n        System.out.println(\"Hello world!\");\n        System.out.println(System.getProperty(\"java.version\"));\n    }\n}\n```\n\n`src/test/java/org/example/oci/demo/ImageTest.java`\n\n```java\npackage org.example.oci.demo;\n\nimport io.github.sgtsilvio.gradle.oci.junit.jupiter.OciImages;\nimport org.junit.jupiter.api.Test;\nimport org.testcontainers.containers.GenericContainer;\n\npublic class ImageTest {\n\n    @Test\n    void test() throws InterruptedException {\n        final GenericContainer\u003c?\u003e container = new GenericContainer\u003c\u003e(OciImages.getImageName(\"example/oci-demo:1.0.0\"));\n        container.withLogConsumer(outputFrame -\u003e System.out.println(outputFrame.getUtf8StringWithoutLineEnding()));\n        container.start();\n        Thread.sleep(100);\n        container.stop();\n    }\n}\n```\n\n## Requirements\n\n- Gradle 8.3 or higher\n\n## Why Another Image Builder?\n\nThis plugin does not aim to only be \"yet another image builder\", but instead tries to solve usability issues of other image builders.\n\n### OCI Images as Plain Files\n\nOCI images are a form of distribution of your application.\nYou may know other distribution formats (deb, rpm, some zip/tar); all of them are just plain files with some metadata.\nThe same applies to OCI images: they consist of filesystem layers (tar files) and metadata (json files).\n\nThe problem here is that most image builders hide these files from the user.\nThis creates multiple usability issues.\nFirst, it makes it harder to grasp what an image actually is.\nWhile the previous point might be subjective, the software and services needed for managing the files definitely complicate the development environment.\nExamples for the software in question here are the Docker daemon and registries.\n\nThis plugin simply outputs all artifacts of an OCI image as files; no Docker daemon or registry required.\nHaving access to the plain files of an OCI image is beneficial.\nCopying files and consuming files in other tools is easy.\n\n### Dependency Management for OCI Images\n\nThe following paragraph defines build system terminology before talking about dependency management:\nGradle projects are composed of _tasks_.\nEach task can have _inputs_ and _outputs_ - these are just files.\nSome task outputs are defined as outputs of the project and are then called _artifacts_.\nArtifacts (usually from outside the project) can be consumed by declaring _dependencies_.\nWhen a dependency is resolved, _module metadata_ is used to locate the artifacts and optionally _transitive dependencies_.\nThe dependency and all its transitive dependencies in the end resolve to a set of artifacts - files that can be used as task inputs.\n\nNow that OCI images are just files they can be modelled as artifacts.\nThe OCI image artifacts can then be consumed by declaring dependencies.\nFurthermore, an OCI image can then also have transitive dependencies.\nParent images (for example declared by the FROM statement in Dockerfiles) should actually be a transitive dependency.\nUnfortunately, OCI images lose the metadata about their parent images.\nThe following diagram shows an example comparison of the representation of OCI images (top) and the representation of _OCI components_ by this plugin (bottom).\n\n![parent-image-dependencies-high-level.drawio.svg](docs/images/parent-image-dependencies-high-level.drawio.svg)\n\nIn the above diagram, image 3 has image 2 as parent image that in turn has image 1 as parent image.\nImage 3 has no pointer to their parent images anymore.\nIt is also not possible to split the metadata of image 3 because it is a mix of its own and all parent images' metadata.\nThis representation is good for using the image, but not ideal for building.\nThe bottom part visualizes how it looks, when all three images would be built with this plugin.\nEach component would only contain its own layers and its own metadata with explicit dependencies on the parent images.\nWhen image 3 needs to be used, it needs to be assembled in the OCI image format.\n\nWhile this might just seem like an extra step, it enables a lot of flexibility.\nFor example, it is easy to upgrade the version of a parent image independently, as can be seen in the following example diagram.\n\n![version-upgrade.drawio.svg](docs/images/version-upgrade.drawio.svg)\n\nMore sophisticated dependency management can be applied, such as substituting a parent image with one from a different vendor as long as it provides the same capabilities.\nAlso, the OCI components can be published without the need to republish all artifacts of parent images.\n\nFurthermore, we are used to an image having at maximum one parent image, but this plugin allows to declare multiple parent image dependencies.\nThe dependencies then form a directed graph which will be traversed when assembling the OCI image.\nThe following diagram shows an example where the \"application\" and \"java\" OCI components have two parent image dependencies.\n\n![multiple-parent-image-dependencies.drawio.svg](docs/images/multiple-parent-image-dependencies.drawio.svg)\n\nLooking into more detail, an OCI component can support multiple platforms; and each OCI component could support a different set of platforms.\nWhen resolving the graph of OCI components, the actual set of supported platforms is determined.\nThe following diagram shows an example where the \"app\" OCI component support all platforms and the parent OCI components \"java\" and \"os packages\" support different platforms.\nThe intersection of the supported platforms results in an assembled multi-arch OCI image that supports 2 platforms.\n\n![components-bundles-multi-arch.drawio.svg](docs/images/components-bundles-multi-arch.drawio.svg)\n\nThis plugin uses Gradle's model to represent the OCI component artifacts and dependencies.\nIt does not reinvent the dependency model.\nInstead, it allows to use the same dependency types for declaring dependencies on OCI component artifacts as for declaring any other dependencies on e.g. Java libraries.\nThe following module dependency types can be used for OCI components:\n- Project dependencies: depend on OCI components produced by other Gradle subprojects.\n- External module dependencies:\n  - Can be downloaded from a repository that supports Gradle Module Metadata.\n  - Can also be downloaded from an OCI registry acting as a special kind of a repository.\n  - Can be substituted by project dependencies of included Gradle builds.\n\n### Fine-grained Configurability\n\nThis section of the documentation is still WIP.\n\n- flexible and explicit definition of OCI image layers\n- easy to package outputs of other tasks (similar to Gradle's copyspecs)\n- easy to declare file ownership and permissions\n- full configuration of OCI image metadata (all properties in config, manifest and index)\n- declarative\n\n### Clear Separation Between Image and Registry\n\nThis section of the documentation is still WIP.\n\n- split registry from image name (same as Gradle's repositories and dependencies)\n\n### Reproducible Builds\n\nThe artifacts produced by this plugin are fully reproducible.\nThis includes OCI layers as well as the OCI metadata.\nReproducibility means that the exact same binaries can be recreated when using the same inputs.\nMore information on reproducible builds can be found on [https://reproducible-builds.org/](https://reproducible-builds.org/).\n\n### Gradle Native Integration\n\nThis section of the documentation is still WIP.\n\n- already described above, using Gradle's dependency model (configurations, dependencies, artifacts, attributes, capabilities)\n- utilize Gradle up-to-date checks\n- utilize Gradle build cache\n- utilize Gradle dependency cache for images downloaded from repositories or OCI registries\n- OCI images as test inputs, compatibility with Develocity test distribution\n\nDifference to jib\n- in contrast to jib not opinionated about the content/structure of OCI images, not only suitable to build java application images\n- jib does not allow flexible configuration, not easy to package outputs of other tasks\n- jib is not Gradle native: does not use Gradle caches and up-to-date checks\n- jib does not allow to build multi-arch images as files, requires registry\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsgtsilvio%2Fgradle-oci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsgtsilvio%2Fgradle-oci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsgtsilvio%2Fgradle-oci/lists"}