{"id":19435303,"url":"https://github.com/syncom/r10edocker","last_synced_at":"2026-03-16T16:01:59.819Z","repository":{"id":61563041,"uuid":"552165069","full_name":"syncom/r10edocker","owner":"syncom","description":"Make minimum, reproducible Docker container for Go application","archived":false,"fork":false,"pushed_at":"2024-04-18T21:07:57.000Z","size":62,"stargazers_count":18,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-03T11:22:18.415Z","etag":null,"topics":["deterministic-build","distroless-docker","docker-container","docker-image","golang","nix","reproducible-builds"],"latest_commit_sha":null,"homepage":"","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/syncom.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":"2022-10-16T01:01:13.000Z","updated_at":"2024-05-04T00:59:36.000Z","dependencies_parsed_at":"2023-02-18T14:10:18.222Z","dependency_job_id":"653f0e09-e27e-485b-9091-c19b0e1e56aa","html_url":"https://github.com/syncom/r10edocker","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/syncom%2Fr10edocker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syncom%2Fr10edocker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syncom%2Fr10edocker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syncom%2Fr10edocker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/syncom","download_url":"https://codeload.github.com/syncom/r10edocker/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250704938,"owners_count":21473789,"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":["deterministic-build","distroless-docker","docker-container","docker-image","golang","nix","reproducible-builds"],"created_at":"2024-11-10T15:05:22.881Z","updated_at":"2026-03-16T16:01:59.706Z","avatar_url":"https://github.com/syncom.png","language":"Go","readme":"# r10edocker: Reproducible Docker Container for Go Applications\n\n[![sanity checks](https://github.com/syncom/r10edocker/actions/workflows/sanity.yml/badge.svg)](https://github.com/syncom/r10edocker/actions/workflows/sanity.yml)\n\n`r10edocker` creates a framework for making bit-for-bit reproducible Docker\ncontainer images for Go applications. If you deploy backend services as\ncontainers, and care about software supply chain security, reproducible Docker\ncontainers are for you.\n\nIf your Go application is locally reproducible (i.e., it's reproducible on your\nlocal build machine), the containing Docker container is universally\nreproducible (i.e., it's reproducible on different build machines).\n\nThere are some pleasant side-effects\n\n- As a corollary of reproducible container, the executables in it are\n  reproducible. It means that even if you don't care about containerization,\n  `r10edocker` provides a means to get you (universally) reproducible Go\n  applications. We provide a utility [container_cp.sh](scripts/container_cp.sh)\n  to extract a file from a container image, in case it helps you.\n- The resulting Docker container is minimum, in that it contains only the\n  application(s), but does not include an OS shell, a package manager, etc.\n  Minimum containers minimize attack surface.\n\n## FAQs\n\n### What are the constraints\n\nCurrently, `r10edocker` only\n\n- works for \"pure\" Go projects, i.e., those that do not use [cgo](https://pkg.go.dev/cmd/cgo)\n- produces `x86_64` Docker images\n\n### What if my Go application is not locally reproducible\n\nIn general, Go makes it easy to get reproducible statically linked executables.\nIf your Go application is not reproducible, make sure you\n\n- use [go.sum](https://go.dev/ref/mod#go-sum-files) files\n- use the `-trimpath` flag when `go build`\n- don't insert any timestamp information in the executable\n- and as a last resort, perform debugging to find out what causes the builds to\n  be non-deterministic using [these recommended\n  tools](https://reproducible-builds.org/tools/)\n\n## How to Use\n\n### install `r10edocker`\n\n```bash\n# commit SHA for v0.3.6. Pin commit because it's less malleable than a tag\ngo install github.com/syncom/r10edocker@6e88e3d2700d99df77d82164342952d056f6a7e7\n```\n\n### Set up your Go project for reproducible Docker builds\n\n#### Configure your Go project in a JSON file\n\nCreate a simple configuration file, `config.json`, and put it in your project\ndirectory. You will also want to check this file in your project's repository\nfor version control.\n\nHere's an example: [config.json](./config.json)\n\n```json\n{\n  \"project_name\": \"go-r10e-docker\",\n  \"build_cmd\": \"scripts/build-all.sh\",\n  \"maintainers\": [ \"syncom\" ],\n  \"go_version\": \"1.24\",\n  \"artifacts\": [\n    {\n      \"src\": \"build/r10edocker-linux-amd64\",\n      \"dest\": \"/app/r10edocker-linux-amd64\"\n    },\n    {\n      \"src\": \"build/r10edocker-linux-arm64\",\n      \"dest\": \"/app/r10edocker-linux-arm64\"\n    },\n    {\n      \"src\": \"build/r10edocker-darwin-amd64\",\n      \"dest\": \"/app/r10edocker-darwin-amd64\"\n    },\n    {\n      \"src\": \"build/r10edocker-darwin-arm64\",\n      \"dest\": \"/app/r10edocker-darwin-arm64\"\n    }\n  ],\n  \"extern_data\": [\n    {\n      \"src\": \"LICENSE\",\n      \"dest\": \"/LICENSE\"\n    }\n  ],\n  \"include_ca_bundle\": true\n}\n```\n\nFields \"project_name\", \"build_cmd\", and \"artifacts\" are mandatory. Fields\n\"maintainers\", \"extern_data\", \"include_ca_bundle\", and \"go_version\" are\noptional.\n\n| Name              | Value Type | Can be null or empty |\n| :---              | :---       | :---:                |\n| project_name      | string     | false                |\n| build_cmd         | string     | false                |\n| maintainers       | array of strings | true           |\n| go_version        | string     | true                 |\n| artifacts         | array of objects | false          |\n| extern_data       | array of objects | true           |\n| include_ca_bundle | boolean    | true                 |\n\n- \"project_name\" is a name to identify your project. Your reproducible container\n  image will be named after it. Please make sure there's no whitespace\n  characters in the \"project_name\" value\n- \"build_cmd\" is a one-line command to build your Go application(s). You may use\n  a shell script file for it\n- \"artifacts\" contains information about the source and destination path\n  information for the Go executable(s) to get into the container image\n  - \"src\" shall be a *relative path* of the executable file (built with\n    \"build_cmd\" on a build host) with respect to the project's directory root\n  - \"dest\" shall be an *absolute path* of the executable file in the final\n    Docker container image\n- \"maintainer\" contains a list of project maintainer\n  names/aliases/GitHub handles\n- \"go_version\" specifies the desired golang version in `\u003cmajor\u003e.\u003cminor\u003e` format\n  (e.g., `1.24`) to use to build the application. The value of `go_version`\n  shall not be smaller than the `go` version specified in your `go.mod` file. We\n  only support Go version `1.19` and later. Please refer to\n  [nixpkgs_go_versions.go](./pkg/r10e-docker/nixpkgs_go_versions.go) for\n  supported Go versions. If this field is missing from the configuration, a\n  default Go version (also specified in `nixpkgs_go_versions.go`) will be used.\n- \"extern_data\" contains information about the source and destination path\n  information for data external to the Go executable(s) to get into the\n  container. Unlike in \"artifacts\", the external data path can be either a file\n  or a directory. However, the source and destination paths for the same\n  external datum must be of the same type (file or directory) when instantiated.\n  - \"src\" shall be a *relative path* to the project diectory where `r10edocker`\n    is run\n  - \"dest\" shall be an *absolute path* in the final Docker container image\n- \"include_ca_bundle\" dictates a root CA bundle from the `cacert` package of\n  nixpkgs will be installed in the container image. If the value of this field\n  is set to `true` the root CA bundle will be included in the container, which\n  is useful and possibly necessary if your application uses TLS and the\n  system-wide trusted CA store; otherwise if this field is set to `false` or\n  absent from the configuration file, no root CA bundle will be installed in the\n  container.\n\n#### Generate r10e build scripts, and build\n\nMake sure you have the Docker daemon running and `sha256sum` (provided by\n`coreutils`) in your PATH. Under your Go project's directory root, run\n\n```bash\n$ r10edocker -c config.json\n2022/10/15 20:08:33 R10e build scripts created in 'r10e-docker'\n```\n\nThe build scripts are created in subdirectory `r10e-docker` using information in\n`config.json`. You should also check in the `r10e-docker`directory to your\nsource repository.\n\nNow our reproducible Docker container can be built with command (with sample\noutput)\n\n```bash\n$ bash r10e-docker/build_container.sh 2\u003e/dev/null\n[...]\n======= CONTAINER IMAGE INFO ========\nContainer image created in /home/syncom/Development/r10edocker/r10e-docker/out/go-r10e-docker-latest.tar.gz\nIMAGE sha256sum: 43052c5df509e35e5b0fb8c107a63e72025aa9fc75b3596961241b965c8168d4\nIMAGE ID: 05026ca1fc5df69f54ece62ec8fd8eba8b37f7628a00ee872ab802b74a820b88\n```\n\nThe reproducible container is named `\u003cproject_name\u003e.tar.gz`, and can be loaded with\n\n```bash\ndocker load -i r10e-docker/out/\u003cproject_name\u003e-latest.tar.gz\n```\n\n#### Update r10e build scripts\n\nIf you need to change your Go project or Docker container's configuration,\nmodify your `config.json`, and repeat all the steps described in the previous\nsection to get the content of `r10e-docker/` updated.\n\n## Acknowledgments\n\n- Dino Dai Zovi ([@ddz](https://github.com/ddz)): for suggesting Nix to me, and\nfor his encouragement\n- My colleagues at [Thistle](https://www.thistle.tech/) and [Cash\nApp](https://cash.app/): for their feedback on earlier versions of this work,\nand for independently reproducing and verifying the build steps\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyncom%2Fr10edocker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyncom%2Fr10edocker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyncom%2Fr10edocker/lists"}