├── .bazelrc ├── .dockerignore ├── .gitignore ├── BUILD.bazel ├── LICENSE ├── MODULE.bazel ├── MODULE.bazel.lock ├── Makefile ├── Makefile_work_in_progress ├── README.md ├── VERSION ├── build └── containers │ ├── athens │ └── docker-compose-athens.yml │ ├── go_nix_simple │ ├── Containerfile │ ├── Containerfile_athens │ ├── Containerfile_http_cache │ ├── Containerfile_nix │ ├── Containerfile_no_cache │ ├── Containerfile_scratch │ └── Containerfile_upx │ ├── go_nix_simple_refactor │ ├── Containerfile.distroless.athens.noupx │ ├── Containerfile.distroless.athens.upx │ ├── Containerfile.distroless.docker.noupx │ ├── Containerfile.distroless.docker.upx │ ├── Containerfile.distroless.http.noupx │ ├── Containerfile.distroless.http.upx │ ├── Containerfile.distroless.none.noupx │ ├── Containerfile.distroless.none.upx │ ├── Containerfile.scratch.athens.noupx │ ├── Containerfile.scratch.athens.upx │ ├── Containerfile.scratch.docker.noupx │ ├── Containerfile.scratch.docker.upx │ ├── Containerfile.scratch.http.noupx │ ├── Containerfile.scratch.http.upx │ ├── Containerfile.scratch.none.noupx │ ├── Containerfile.scratch.none.upx │ └── Containerfile.tmpl │ └── squid │ ├── Containerfile │ ├── docker-compose-squid.yml │ ├── squid.conf │ └── squid.conf.original ├── cmd ├── generate-containerfiles │ ├── .gitignore │ ├── BUILD.bazel │ ├── Makefile │ └── generate-containerfiles.go ├── go_nix_simple │ ├── .gitignore │ ├── BUILD.bazel │ ├── Makefile │ ├── go_nix_simple.go │ └── go_nix_simple_test.go └── validate-image │ ├── .gitignore │ ├── BUILD.bazel │ ├── Makefile │ ├── validate-image │ └── validate-image.go ├── deps.bzl ├── docs ├── example │ ├── BUILD.bazel.example │ └── README.md ├── images │ ├── Screenshot From 2025-04-15 10-23-13.png │ ├── Screenshot From 2025-04-15 10-27-00.png │ ├── Screenshot From 2025-04-15 10-27-36.png │ └── Screenshot From 2025-04-15 10-27-44.png └── nix_on_ubuntu.md ├── flake.lock ├── flake.nix ├── go.mod ├── go.sum ├── gomod2nix.toml ├── platforms └── BUILD.bazel ├── scripts ├── build_docker_image.sh ├── build_nix_image.sh ├── generate_summary.sh ├── generate_validation_summary.sh ├── remove_docker_images.bash └── validate_image.sh └── tools └── python └── BUILD.bazel /.bazelrc: -------------------------------------------------------------------------------- 1 | # 2 | # .bazelrc 3 | # 4 | 5 | # test strategy 6 | # https://github.com/bazelbuild/bazel/blob/master/tools/test/test-setup.sh 7 | 8 | common --enable_bzlmod=true 9 | 10 | # Disable WORKSPACE file 11 | common --noenable_workspace 12 | 13 | # go test race detection needs cgo 14 | # Disable C++ toolchain detection, or you get a weird error even with go and cgo disabled. 15 | # ERROR: /home/das/Downloads/go_nix_simple/cmd/go_nix_simple/BUILD.bazel:34:8: Testing //cmd/go_nix_simple:go_nix_simple_test failed: (Exit 34): Remote Execution Failure: 16 | # Invalid Argument: Failed to run command: Failed to start process: fork/exec external/bazel_tools/tools/test/test-setup.sh: no such file or directory 17 | #common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 18 | 19 | # LLVM toolchain configuration 20 | #common --incompatible_enable_cc_toolchain_resolution 21 | #common --extra_toolchains=@llvm_toolchain//:all 22 | 23 | # Remove any system C++ toolchain detection 24 | # common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 25 | 26 | # Configuration for using Buildbarn on hp4.home 27 | # Use 'build:hp4' to apply these flags to the build command when --config=hp4 is used 28 | build:hp4 --remote_executor=grpc://hp4.home:8980 29 | #build:hp4 --remote_cache=grpc://hp4.home:8980 30 | # Worker {"datacenter":"amsterdam","hostname":"ubuntu-worker.example.com","rack":"3","slot":"10","thread":"4"} 31 | build:hp4 --remote_instance_name=fuse 32 | build:hp4 --remote_default_exec_properties=OSFamily=linux 33 | build:hp4 --remote_default_exec_properties=container-image=docker://ghcr.io/catthehacker/ubuntu:act-22.04@sha256:5f9c35c25db1d51a8ddaae5c0ba8d3c163c5e9a4a6cc97acd409ac7eae239448 34 | build:hp4 --remote_timeout=3600 35 | 36 | # Shell toolchain configuration 37 | build:hp4 --shell_executable=/bin/bash 38 | #build:hp4 --incompatible_strict_action_env 39 | 40 | # Force remote execution 41 | build:hp4 --spawn_strategy=remote 42 | 43 | # Configure specific strategies for remote execution 44 | build:hp4 --strategy=GoCompile=remote 45 | build:hp4 --strategy=GoLink=remote 46 | build:hp4 --strategy=GoPackage=remote 47 | build:hp4 --strategy=Genrule=remote 48 | 49 | # Test strategy configuration - run tests locally without remote execution 50 | build:hp4 --test_strategy=standalone 51 | build:hp4 --strategy=TestRunner=local 52 | build:hp4 --remote_download_outputs=all 53 | 54 | # Remote execution settings 55 | build:hp4 --noremote_local_fallback 56 | build:hp4 --jobs=8 57 | 58 | # Only keep OCI operations local 59 | build:hp4 --strategy=OciImage=local 60 | build:hp4 --strategy=OciPush=local 61 | 62 | # # Python toolchain settings 63 | # build:hp4 --incompatible_use_python_toolchains=true 64 | # build:hp4 --extra_toolchains=//tools/python:python_toolchain 65 | 66 | # Debug settings 67 | build:hp4 --verbose_failures 68 | build:hp4 --worker_verbose 69 | build:hp4 --show_progress_rate_limit=0.5 70 | 71 | # Optional: Download all remote outputs (useful for debugging) 72 | # build:hp4 --remote_download_outputs=all 73 | 74 | # Optional: Set concurrency (adjust based on hp4's resources) 75 | # build:hp4 --jobs=16 76 | 77 | # end -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # .gitignore 3 | # 4 | 5 | output 6 | 7 | # nix output 8 | result 9 | 10 | # Bazel output directories 11 | bazel-bin 12 | bazel-out 13 | bazel-testlogs 14 | bazel-* 15 | 16 | vendor 17 | 18 | # Go binary 19 | go_nix_simple 20 | cmd/go_nix_simple/go_nix_simple 21 | 22 | # end 23 | -------------------------------------------------------------------------------- /BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@gazelle//:def.bzl", "gazelle") 2 | 3 | # Gazelle configuration 4 | gazelle( 5 | name = "gazelle", 6 | args = [ 7 | "-build_file_name=BUILD.bazel", 8 | "-mode=fix", 9 | ], 10 | command = "update", 11 | prefix = "github.com/randomizedcoder/go_nix_simple", 12 | ) 13 | 14 | # Run gazelle with specific arguments for updating Go dependencies 15 | gazelle( 16 | name = "gazelle-update-repos", 17 | args = [ 18 | "-from_file=go.mod", 19 | "-to_macro=deps.bzl%go_dependencies", 20 | "-prune", 21 | ], 22 | command = "update-repos", 23 | ) 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 randomizedcoder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MODULE.bazel: -------------------------------------------------------------------------------- 1 | # 2 | # MODULE.bazel 3 | # 4 | # https://registry.bazel.build/ 5 | # 6 | # Nice example of a MODULE.bazel file: 7 | # https://github.com/aspect-build/bazel-examples/blob/main/MODULE.bazel 8 | # 9 | # https://fzakaria.com/2024/08/29/bazel-overlay-pattern 10 | # 11 | # https://github.com/llvm/llvm-project/blob/main/utils/bazel/README.md 12 | 13 | 14 | module( 15 | name = "go_nix_simple", 16 | version = "0.1.0", 17 | ) 18 | 19 | # Core Bazel dependencies 20 | bazel_dep(name = "rules_go", version = "0.54.0") # https://github.com/bazel-contrib/rules_go/tags 21 | bazel_dep(name = "gazelle", version = "0.43.0") 22 | bazel_dep(name = "rules_cc", version = "0.1.1") # https://github.com/bazelbuild/rules_cc/tags 23 | 24 | bazel_dep(name = "rules_oci", version = "2.2.6") # https://github.com/bazel-contrib/rules_oci/tags 25 | bazel_dep(name = "rules_pkg", version = "1.1.0") # https://github.com/bazelbuild/rules_pkg/tags 26 | #bazel_dep(name = "rules_python", version = "1.4.0") # https://github.com/bazelbuild/rules_python/tags 27 | 28 | bazel_dep(name = "aspect_bazel_lib", version = "2.15.3") # https://registry.bazel.build/modules/aspect_bazel_lib 29 | bazel_dep(name = "platforms", version = "0.0.11") #https://github.com/bazelbuild/platforms/tags 30 | #bazel_dep(name = "rules_platform", version = "0.1.0") #https://github.com/bazelbuild/rules_platform/tags 31 | 32 | bazel_dep(name = "bazel_skylib", version = "1.7.1") #https://github.com/bazelbuild/bazel-skylib/tags 33 | bazel_dep(name = "rules_distroless", version = "0.5.1") # https://github.com/GoogleContainerTools/rules_distroless/tags 34 | 35 | bazel_dep(name = "rules_shell", version = "0.4.1") # https://github.com/bazelbuild/rules_shell/tags 36 | 37 | # LLVM toolchain setup 38 | bazel_dep(name = "toolchains_llvm", version = "1.4.0") # https://github.com/bazel-contrib/toolchains_llvm/tags 39 | 40 | # Configure LLVM toolchain 41 | llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") 42 | llvm.toolchain( 43 | llvm_version = "16.0.0", 44 | ) 45 | 46 | use_repo(llvm, "llvm_toolchain") 47 | # use_repo(llvm, "llvm_toolchain_llvm") # if you depend on specific tools in scripts 48 | 49 | register_toolchains("@llvm_toolchain//:all") 50 | 51 | # Go toolchain setup 52 | # https://github.com/bazel-contrib/rules_go/blob/master/docs/go/core/bzlmod.md#go-sdks 53 | go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") 54 | go_sdk.download( 55 | name = "go_sdk", 56 | version = "1.24.2", 57 | ) 58 | use_repo(go_sdk, "go_sdk") 59 | 60 | # Go dependencies from go.mod 61 | go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") 62 | go_deps.from_file(go_mod = "//:go.mod") 63 | use_repo( 64 | go_deps, 65 | "com_github_clickhouse_clickhouse_go_v2", 66 | "com_github_docker_docker", 67 | "com_github_docker_go_connections", 68 | "com_github_grafana_pyroscope_go", 69 | "com_github_nats_io_nats_go", 70 | "com_github_pkg_profile", 71 | "com_github_prometheus_client_golang", 72 | "com_github_prometheus_common", 73 | "com_github_redis_go_redis_v9", 74 | ) 75 | 76 | oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") 77 | 78 | # https://github.com/GoogleContainerTools/distroless 79 | 80 | # Distroless base images 81 | oci.pull( 82 | name = "distroless_static", 83 | digest = "sha256:c0f429e16b13e583da7e5a6ec20dd656d325d88e6819cafe0adb0828976529dc", 84 | image = "gcr.io/distroless/static-debian12", 85 | platforms = [ 86 | "linux/amd64", 87 | "linux/arm64", 88 | #"linux/arm64/v8", 89 | ], 90 | tag = "nonroot", 91 | ) 92 | use_repo( 93 | oci, 94 | "distroless_static", 95 | "distroless_static_linux_amd64", 96 | "distroless_static_linux_arm64", 97 | #"distroless_static_linux_arm64_v8", 98 | ) 99 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # /go-nix-simple/Makefile 3 | # 4 | 5 | SHELL := /usr/bin/env bash 6 | .SHELLFLAGS := -eu -o pipefail -c 7 | 8 | # --- Build Information --- 9 | VERSION := $(shell cat VERSION) 10 | COMMIT := $(shell git describe --always) 11 | DATE := $(shell date -u +"%Y-%m-%d-%H:%M") 12 | LDFLAGS_STR := "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${VERSION}" 13 | 14 | # --- Helper Variables --- 15 | TIMESTAMP := date +"%Y-%m-%d %H:%M:%S.%3N" 16 | MYPATH = $(shell pwd) 17 | REPO_PREFIX := randomizedcoder 18 | 19 | # --- Output Directory for Metrics --- 20 | BUILD_RUN_TIMESTAMP := $(shell date +"%Y%m%d_%H%M%S") 21 | BUILD_OUTPUT_DIR := ./output/$(BUILD_RUN_TIMESTAMP) 22 | 23 | VALIDATION_OUTPUT_DIR := $(BUILD_OUTPUT_DIR)/validation 24 | 25 | # --- Generator Tool --- 26 | GENERATOR_DIR := cmd/generate-containerfiles 27 | GENERATOR_BIN := $(GENERATOR_DIR)/generate-containerfiles 28 | CONTAINERFILE_DIR := build/containers/go_nix_simple_refactor 29 | 30 | # --- Validator Tool --- 31 | VALIDATOR_DIR := cmd/validate-image 32 | VALIDATOR_BIN := $(VALIDATOR_DIR)/validate-image 33 | 34 | # --- Build Command Macro (Used for Nix builds now) --- 35 | define time_command 36 | @_start_time_ns=$$(date +%s%N); \ 37 | echo "[$($(TIMESTAMP))] Starting $(1)..."; \ 38 | $(2); \ 39 | _end_time_ns=$$(date +%s%N); \ 40 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 41 | echo "[$($(TIMESTAMP))] Finished $(1). Duration: $$_duration_ms ms." 42 | endef 43 | 44 | # --- Nix Flake Outputs (Base names for easier reference) --- 45 | NIX_IMAGE_PREFIX := image-nix 46 | NIX_BINARY_PREFIX := binary-nix 47 | NIX_BUILDERS := buildgomodule gomod2nix 48 | NIX_BASES := distroless scratch 49 | NIX_PACKERS := noupx upx 50 | 51 | # --- Docker Build Variants (Base names for easier reference) --- 52 | DOCKER_BUILD_PREFIX := build_docker 53 | DOCKER_IMAGE_PREFIX := docker-go-nix-simple 54 | DOCKER_BASES := distroless scratch 55 | DOCKER_CACHES := docker athens http none 56 | DOCKER_PACKERS := noupx upx 57 | 58 | # --- Generate Lists of Targets --- 59 | NIX_IMAGE_TARGETS := $(foreach base,$(NIX_BASES), \ 60 | $(foreach builder,$(NIX_BUILDERS), \ 61 | $(foreach packer,$(NIX_PACKERS), \ 62 | build-$(NIX_IMAGE_PREFIX)-$(base)-$(builder)-$(packer)))) 63 | 64 | DOCKER_IMAGE_TARGETS := $(foreach base,$(DOCKER_BASES), \ 65 | $(foreach cache,$(DOCKER_CACHES), \ 66 | $(foreach packer,$(DOCKER_PACKERS), \ 67 | $(DOCKER_BUILD_PREFIX)-$(base)-$(cache)-$(packer)))) 68 | 69 | # No filters yet 70 | INVALID_DOCKER_COMBOS := $(filter %-foo-bar, $(DOCKER_IMAGE_TARGETS)) 71 | # INVALID_DOCKER_COMBOS := $(filter %-athens-upx, $(DOCKER_IMAGE_TARGETS)) \ 72 | # $(filter %-http-upx, $(DOCKER_IMAGE_TARGETS)) \ 73 | # $(filter %-none-upx, $(DOCKER_IMAGE_TARGETS)) \ 74 | # $(filter %-scratch-athens-upx, $(DOCKER_IMAGE_TARGETS)) 75 | 76 | VALID_DOCKER_IMAGE_TARGETS := $(filter-out $(INVALID_DOCKER_COMBOS), $(DOCKER_IMAGE_TARGETS)) 77 | 78 | VALIDATE_NIX_TARGETS := $(NIX_IMAGE_TARGETS:build-%=validate-%) 79 | VALIDATE_DOCKER_TARGETS := $(VALID_DOCKER_IMAGE_TARGETS:$(DOCKER_BUILD_PREFIX)-%=validate_docker-%) 80 | ALL_VALIDATE_TARGETS := $(VALIDATE_NIX_TARGETS) $(VALIDATE_DOCKER_TARGETS) 81 | 82 | PUSH_NIX_TARGETS := $(NIX_IMAGE_TARGETS:build-%=push-%) 83 | PUSH_DOCKER_TARGETS := $(VALID_DOCKER_IMAGE_TARGETS:$(DOCKER_BUILD_PREFIX)-%=push_docker-%) 84 | ALL_PUSH_TARGETS := $(PUSH_NIX_TARGETS) $(PUSH_DOCKER_TARGETS) 85 | 86 | #-------------------------- 87 | # Bazel Configuration 88 | #-------------------------- 89 | BAZEL_REPO := docker.io/randomizedcoder 90 | BAZEL_VERSION := latest 91 | BAZEL_PLATFORMS := //platforms:linux_amd64 92 | #BAZEL_PLATFORMS := //platforms:linux_amd64 //platforms:linux_arm64 93 | 94 | # Generate all combinations 95 | BAZEL_TARGETS := $(foreach img,$(BAZEL_IMAGES),$(foreach plat,$(BAZEL_PLATFORMS),image_bazel_$(img)_$(plat))) 96 | 97 | # --- Phony Targets --- 98 | .PHONY: all all-nix all-docker all-bazel \ 99 | prepare-output-dir generate-containerfiles \ 100 | build-validator \ 101 | validate-all validate-all-nix validate-all-docker \ 102 | load-nix-result \ 103 | summary \ 104 | $(NIX_IMAGE_TARGETS) \ 105 | $(VALID_DOCKER_IMAGE_TARGETS) \ 106 | $(BAZEL_TARGETS) \ 107 | $(ALL_VALIDATE_TARGETS) \ 108 | $(ALL_PUSH_TARGETS) \ 109 | deploy_athens down_athens run_athens ls dive run curl prepare clear_go_mod_cache go_clean \ 110 | flake_metadata flake_show \ 111 | install_bazel gazelle_init gazelle_run bazel_build bazel_run \ 112 | bazel_build_a_tarball bazel_go \ 113 | bazel-setup bazel-update bazel-clean \ 114 | bazel-build-all 115 | 116 | # --- Aggregate Targets --- 117 | all: prepare-output-dir all-nix all-docker summary 118 | all-validate: prepare-output-dir all-nix all-docker validate-all summary validation-summary 119 | all-nix: prepare-output-dir $(NIX_IMAGE_TARGETS) 120 | all-docker: prepare-output-dir generate-containerfiles $(VALID_DOCKER_IMAGE_TARGETS) 121 | 122 | #------------------------ 123 | # Bazel Setup & Maintenance 124 | #------------------------ 125 | .PHONY: bazel-setup bazel-update bazel-clean 126 | 127 | bazel-setup: 128 | go install github.com/bazelbuild/bazel-gazelle/cmd/gazelle@latest 129 | 130 | bazel-update: 131 | bazel run //:gazelle -- update-repos -from_file=go.mod 132 | bazel run //:gazelle 133 | 134 | bazel-clean: 135 | bazel clean --expunge 136 | 137 | #------------------------ 138 | # Bazel Build Targets 139 | #------------------------ 140 | .PHONY: bazel-build-all bazel-build-distroless bazel-build-scratch 141 | 142 | # Build all variants 143 | bazel-build-all: bazel-build-distroless bazel-build-scratch 144 | 145 | # Remote build target for all variants 146 | bazel-build-all-remote: 147 | for platform in $(BAZEL_PLATFORMS); do \ 148 | bazel build --config=hp4 \ 149 | --platforms=$$platform \ 150 | --verbose_failures \ 151 | --execution_log_json_file=bazel-execution.json \ 152 | --show_timestamps \ 153 | //cmd/go_nix_simple:image_bazel_distroless_tarball \ 154 | //cmd/go_nix_simple:image_bazel_scratch_tarball \ 155 | --define REPO_PREFIX=$(BAZEL_REPO) \ 156 | --define VERSION=$(BAZEL_VERSION); \ 157 | done 158 | 159 | # Distroless image variants 160 | bazel-build-distroless: 161 | for platform in $(BAZEL_PLATFORMS); do \ 162 | bazel build --platforms=$$platform \ 163 | //cmd/go_nix_simple:image_bazel_distroless_tarball \ 164 | --define REPO_PREFIX=$(BAZEL_REPO) \ 165 | --define VERSION=$(BAZEL_VERSION); \ 166 | done 167 | 168 | # Scratch image variants 169 | bazel-build-scratch: 170 | for platform in $(BAZEL_PLATFORMS); do \ 171 | bazel build --platforms=$$platform \ 172 | //cmd/go_nix_simple:image_bazel_scratch_tarball \ 173 | --define REPO_PREFIX=$(BAZEL_REPO) \ 174 | --define VERSION=$(BAZEL_VERSION); \ 175 | done 176 | 177 | # --- Add Aggregate Push Targets --- 178 | push-all: $(ALL_PUSH_TARGETS) 179 | @echo "[$($(TIMESTAMP))] Finished pushing all images." 180 | 181 | push-all-nix: $(PUSH_NIX_TARGETS) 182 | @echo "[$($(TIMESTAMP))] Finished pushing all Nix images." 183 | 184 | push-all-docker: $(PUSH_DOCKER_TARGETS) 185 | @echo "[$($(TIMESTAMP))] Finished pushing all Docker images." 186 | 187 | validate-all: $(ALL_VALIDATE_TARGETS) 188 | validate-all-nix: $(VALIDATE_NIX_TARGETS) 189 | validate-all-docker: $(VALIDATE_DOCKER_TARGETS) 190 | 191 | # e.g. make validate-all -j1 192 | 193 | 194 | # --- Prepare Output Directory --- 195 | prepare-output-dir: 196 | @mkdir -p $(BUILD_OUTPUT_DIR) 197 | @echo "Build output directory: $(BUILD_OUTPUT_DIR)" 198 | 199 | #-------------------------- 200 | # Containerfile Generation 201 | generate-containerfiles: 202 | @echo "[$($(TIMESTAMP))] Building Containerfile generator..." 203 | @$(MAKE) -C $(GENERATOR_DIR) build 204 | @echo "[$($(TIMESTAMP))] Running Containerfile generator..." 205 | $(call time_command, $@, $(GENERATOR_BIN) --output $(CONTAINERFILE_DIR)) 206 | 207 | #-------------------------- 208 | # Validator Build Target 209 | build-validator: 210 | @echo "[$($(TIMESTAMP))] Building validator tool..." 211 | @$(MAKE) -C $(VALIDATOR_DIR) build 212 | @echo "[$($(TIMESTAMP))] Finished building validator tool." 213 | 214 | run-valdiator: 215 | ./cmd/validate-image/validate-image --parallel 8 216 | 217 | #-------------------------- 218 | # Nix Build Targets 219 | 220 | $(NIX_IMAGE_TARGETS): build-$(NIX_IMAGE_PREFIX)-% : prepare-output-dir 221 | ./scripts/build_nix_image.sh \ 222 | "$(strip $@)" \ 223 | "$(strip $(NIX_IMAGE_PREFIX)-$(*))" \ 224 | "$(strip $(REPO_PREFIX)/$(subst image-nix-,nix-go-nix-simple-,$(NIX_IMAGE_PREFIX)-$(*)):$(VERSION))" \ 225 | "$(strip $(BUILD_OUTPUT_DIR))" 226 | 227 | 228 | load-nix-result: result 229 | $(call time_command, $@, docker load < result) 230 | 231 | #-------------------------- 232 | # Docker Build Targets 233 | 234 | $(VALID_DOCKER_IMAGE_TARGETS): $(DOCKER_BUILD_PREFIX)-% : prepare-output-dir 235 | ./scripts/build_docker_image.sh \ 236 | "$(strip $(word 1,$(subst -, ,$(patsubst $(DOCKER_BUILD_PREFIX)-%,%,$@))))" \ 237 | "$(strip $(word 2,$(subst -, ,$(patsubst $(DOCKER_BUILD_PREFIX)-%,%,$@))))" \ 238 | "$(strip $(word 3,$(subst -, ,$(patsubst $(DOCKER_BUILD_PREFIX)-%,%,$@))))" \ 239 | "$(strip $(VERSION))" \ 240 | "$(strip $(COMMIT))" \ 241 | "$(strip $(DATE))" \ 242 | "$(strip $(REPO_PREFIX))" \ 243 | "$(strip $(DOCKER_IMAGE_PREFIX))" \ 244 | "$(strip $(CONTAINERFILE_DIR))" \ 245 | "$(strip $(MYPATH))" \ 246 | "$(strip $(BUILD_OUTPUT_DIR))" 247 | 248 | #-------------------------- 249 | # Push Targets 250 | 251 | # Generic rule for pushing Nix images 252 | $(PUSH_NIX_TARGETS): push-$(NIX_IMAGE_PREFIX)-% : build-$(NIX_IMAGE_PREFIX)-% 253 | @echo "[$($(TIMESTAMP))] Pushing Nix image $(subst push-,build-, $@)..." 254 | $(eval IMAGE_TAG_TO_PUSH := $(strip $(REPO_PREFIX)/$(subst image-nix-,nix-go-nix-simple-,$(NIX_IMAGE_PREFIX)-$(*)):$(VERSION))) 255 | docker push "$(IMAGE_TAG_TO_PUSH)" 256 | # Optionally push :latest tag too 257 | docker push "$(strip $(REPO_PREFIX)/$(subst image-nix-,nix-go-nix-simple-,$(NIX_IMAGE_PREFIX)-$(*)):latest)" 258 | 259 | # Generic rule for pushing Docker images 260 | $(PUSH_DOCKER_TARGETS) : push_docker-% : $(DOCKER_BUILD_PREFIX)-% 261 | @echo "[$($(TIMESTAMP))] Pushing Docker image $(subst push_docker-,build_docker-, $@)..." 262 | # Use $(*) for the stem 263 | $(eval STEM := $(*)) 264 | $(eval IMAGE_TAG_TO_PUSH := $(strip $(REPO_PREFIX)/$(subst $(DOCKER_BUILD_PREFIX)-,$(DOCKER_IMAGE_PREFIX)-,$(DOCKER_BUILD_PREFIX)-$(STEM)):$(VERSION))) 265 | docker push "$(IMAGE_TAG_TO_PUSH)" 266 | # Optionally push :latest tag too 267 | docker push "$(strip $(REPO_PREFIX)/$(subst $(DOCKER_BUILD_PREFIX)-,$(DOCKER_IMAGE_PREFIX)-,$(DOCKER_BUILD_PREFIX)-$(STEM)):latest)" 268 | 269 | #-------------------------- 270 | # Validation Targets 271 | 272 | # Generic rule for validating Nix images (Calls script) 273 | $(VALIDATE_NIX_TARGETS): validate-$(NIX_IMAGE_PREFIX)-% : build-$(NIX_IMAGE_PREFIX)-% build-validator 274 | @mkdir -p $(VALIDATION_OUTPUT_DIR) # Create validation dir 275 | $(eval IMAGE_TAG_TO_VALIDATE := $(strip $(REPO_PREFIX)/$(subst image-nix-,nix-go-nix-simple-,$(NIX_IMAGE_PREFIX)-$(*)):$(VERSION))) 276 | ./scripts/validate_image.sh "$@" "$(VALIDATOR_BIN)" "$(IMAGE_TAG_TO_VALIDATE)" "30" "$(VALIDATION_OUTPUT_DIR)" 277 | 278 | # Generic rule for validating Docker images (Calls script) 279 | $(VALIDATE_DOCKER_TARGETS) : validate_docker-% : $(DOCKER_BUILD_PREFIX)-% build-validator 280 | @mkdir -p $(VALIDATION_OUTPUT_DIR) # Create validation dir 281 | @echo "[$($(TIMESTAMP))] Validating Docker image $(subst validate_docker-,build_docker-, $@)..." 282 | # Use $(*) for the stem 283 | $(eval STEM := $(*)) 284 | $(eval IMAGE_TAG_TO_VALIDATE := $(strip $(REPO_PREFIX)/$(subst $(DOCKER_BUILD_PREFIX)-,$(DOCKER_IMAGE_PREFIX)-,$(DOCKER_BUILD_PREFIX)-$(STEM)):$(VERSION))) 285 | ./scripts/validate_image.sh "$@" "$(VALIDATOR_BIN)" "$(IMAGE_TAG_TO_VALIDATE)" "30" "$(VALIDATION_OUTPUT_DIR)" 286 | 287 | #-------------------------- 288 | # Summary Target 289 | 290 | ALL_NIX_IMAGE_TAGS := $(foreach target,$(NIX_IMAGE_TARGETS),$(REPO_PREFIX)/$(subst build-,,$(target)):$(VERSION)) 291 | ALL_DOCKER_IMAGE_TAGS := $(foreach target,$(VALID_DOCKER_IMAGE_TARGETS),$(REPO_PREFIX)/$(subst $(DOCKER_BUILD_PREFIX)-,$(DOCKER_IMAGE_PREFIX)-,$(target)):$(VERSION)) 292 | ALL_IMAGE_TAGS := $(ALL_NIX_IMAGE_TAGS) $(ALL_DOCKER_IMAGE_TAGS) 293 | 294 | summary: 295 | ./scripts/generate_summary.sh 296 | 297 | validation-summary: 298 | ./scripts/generate_validation_summary.sh 299 | 300 | #-------------------------- 301 | # Other Utility Targets (Keep relevant ones) 302 | 303 | ls: 304 | @echo "--- Nix Images (Loaded) ---" 305 | @docker image ls '$(REPO_PREFIX)/nix-go-nix-simple*' || true 306 | @echo "--- Docker Images ---" 307 | @docker image ls '$(REPO_PREFIX)/docker-go-nix-simple*' || true 308 | 309 | #-------------------------- 310 | # docker compose athens 311 | 312 | deploy_athens: 313 | @echo "================================" 314 | @echo "Make deploy_athens" 315 | docker compose \ 316 | --file build/containers/athens/docker-compose-athens.yml \ 317 | up -d --remove-orphans 318 | 319 | down_athens: 320 | @echo "================================" 321 | @echo "Make down_athens" 322 | docker compose \ 323 | --file build/containers/athens/docker-compose-athens.yml \ 324 | down 325 | 326 | athens_traffic: 327 | sudo tcpdump -ni any port 8888 328 | 329 | 330 | #-------------------------- 331 | # docker compose squid 332 | 333 | squid: create_squid deploy_squid 334 | 335 | create_squid: 336 | docker build -t my-custom-squid:latest \ 337 | -f ./build/containers/squid/Containerfile \ 338 | ./build/containers/squid/ 339 | 340 | deploy_squid: 341 | @echo "================================" 342 | @echo "Make deploy_squid" 343 | docker compose \ 344 | --file build/containers/squid/docker-compose-squid.yml \ 345 | up -d --remove-orphans 346 | 347 | down_squid: 348 | @echo "================================" 349 | @echo "Make down_squid" 350 | docker compose \ 351 | --file build/containers/squid/docker-compose-squid.yml \ 352 | down 353 | 354 | #-------------------------- 355 | # nix build athens docker container 356 | 357 | nix_build_athens: 358 | nix build .#athens-nix-image 359 | docker load < result 360 | 361 | run_athens: 362 | docker run -d -p 8888:8888 randomizedcoder/athens-nix:latest 363 | 364 | #-------------------------- 365 | # inspect (Update these if needed) 366 | 367 | # dive: 368 | # dive 369 | 370 | # dive-distroless: 371 | # dive 372 | 373 | # run: 374 | # docker run -d -p 9108:9108 375 | 376 | # run-distroless: 377 | # docker run -d -p 9108:9108 378 | 379 | curl: 380 | curl http://localhost:9108/metrics 381 | 382 | prepare: 383 | nix-shell -p nix-prefetch-docker --run "nix-prefetch-docker --image-name gcr.io/distroless/static-debian12 --image-tag latest" 384 | 385 | #-------------------------- 386 | # clear go mod cache 387 | 388 | clear_go_mod_cache: 389 | sudo rm -rf /home/das/go/pkg/mod/ 390 | 391 | go_clean: 392 | go clean -modcache 393 | 394 | #-------------------------- 395 | # flake commands 396 | 397 | flake_metadata: 398 | nix flake metadata 399 | 400 | flake_show: 401 | nix flake show 402 | 403 | flake_update: 404 | nix flake update 405 | 406 | flake_develop: 407 | nix develop 408 | 409 | #------------------------ 410 | # bazel 411 | install_bazel: 412 | go install github.com/bazelbuild/bazel-gazelle/cmd/gazelle@latest 413 | 414 | gazelle_update: 415 | bazel run //:gazelle -- update-repos -from_file=go.mod 416 | 417 | gazelle_run: 418 | bazel run //:gazelle 419 | 420 | bazel_build: 421 | bazel build --verbose_failures //cmd/go_nix_simple:go_nix_simple_binary_noupx 422 | 423 | bazel_build_oci_distroless: 424 | bazel build //cmd/go_nix_simple:image_bazel_distroless 425 | 426 | bazel_build_oci_scratch: 427 | bazel build //cmd/go_nix_simple:image_bazel_scratch 428 | 429 | 430 | # bazel_build: 431 | # bazel build //cmd/go_nix_simple:go_nix_simple 432 | 433 | bazel_run: 434 | bazel run //cmd/go_nix_simple:go_nix_simple 435 | 436 | bazel_build_a_tarball: 437 | bazel build //cmd/go_nix_simple:image_bazel_distroless_noupx_tarball 438 | 439 | bazel_go: 440 | bazel build //cmd/go_nix_simple:go_nix_simple_binary_noupx 441 | #bazel build //cmd/go_nix_simple:image_bazel_distroless_noupx 442 | 443 | bazel_build_remote: 444 | bazel build --config=hp4 //cmd/go_nix_simple:go_nix_simple_binary_noupx 445 | 446 | bazel_build_distroless: 447 | bazel build //cmd/go_nix_simple:image_bazel_distroless_noupx_tarball \ 448 | --define REPO_PREFIX=docker.io/randomizedcoder \ 449 | --define VERSION=latest 450 | 451 | bazel_build_scratch: 452 | bazel build //cmd/go_nix_simple:image_bazel_scratch_upx_tarball \ 453 | --define REPO_PREFIX=docker.io/randomizedcoder \ 454 | --define VERSION=latest 455 | 456 | bazel_clean: 457 | bazel clean --expunge 458 | 459 | # end 460 | -------------------------------------------------------------------------------- /Makefile_work_in_progress: -------------------------------------------------------------------------------- 1 | # 2 | # /go-nix-simple/Makefile 3 | # 4 | 5 | VERSION := $(shell cat VERSION) 6 | LOCAL_MAJOR_VERSION := $(word 1,$(subst ., ,$(VERSION))) 7 | LOCAL_MINOR_VERSION := $(word 2,$(subst ., ,$(VERSION))) 8 | LOCAL_PATCH_VERSION := $(word 3,$(subst ., ,$(VERSION))) 9 | SHELL := /usr/bin/env bash 10 | .SHELLFLAGS := -eu -o pipefail -c 11 | 12 | MYPATH = $(shell pwd) 13 | COMMIT := $(shell git describe --always) 14 | DATE := $(shell date -u +"%Y-%m-%d-%H:%M") 15 | 16 | TIMESTAMP := date +"%Y-%m-%d %H:%M:%S.%3N" 17 | 18 | # --- New: Summary file --- 19 | SUMMARY_FILE := .build_summary.tmp 20 | 21 | # Fake targets 22 | .PHONY: all nix_build_go-nix-simple nix_build_docker nix_build_docker_scratch \ 23 | nix_build_docker_trace nix_build_docker_load gomod2nix \ 24 | nix_build_docker_gomod2nix nix_build_docker_gomod2nix_load \ 25 | builddocker_go-nix-simple-distroless \ 26 | builddocker_go-nix-simple-distroless-athens \ 27 | builddocker_go-nix-simple-distroless-scratch \ 28 | deploy_athens down_athens athens_traffic nix_build_athens run_athens ls \ 29 | dive dive-distroless run run-distroless curl prepare clear_go_mod_cache \ 30 | go_glean flake_metadata flake_show \ 31 | summary clean_summary # <-- Add summary targets 32 | 33 | # --- Modified: all target --- 34 | all: clean_summary \ 35 | nix_build_docker nix_build_docker_load \ 36 | nix_build_docker_upx nix_build_docker_load \ 37 | nix_build_docker_scratch nix_build_docker_load \ 38 | builddocker_go-nix-simple-distroless \ 39 | builddocker_go-nix-simple-distroless-athens \ 40 | builddocker_go-nix-simple-scratch \ 41 | builddocker_go-nix-simple-upx \ 42 | gomod2nix \ 43 | ls \ 44 | summary # <-- Run summary at the end 45 | 46 | # --- New: Target to clean summary file --- 47 | clean_summary: 48 | rm -f $(SUMMARY_FILE) 49 | 50 | #-------------------------- 51 | # nix build 52 | 53 | # --- Modified: nix_build_go-nix-simple --- 54 | nix_build_go-nix-simple: 55 | @_start_time_ns=$$(date +%s%N); \ 56 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 57 | nix build .#go-nix-simple; \ 58 | _end_time_ns=$$(date +%s%N); \ 59 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 60 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ # Record duration only 61 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 62 | 63 | # --- Modified: nix_build_docker --- 64 | nix_build_docker: 65 | @_start_time_ns=$$(date +%s%N); \ 66 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 67 | nix build .; \ 68 | _end_time_ns=$$(date +%s%N); \ 69 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 70 | # Record duration only 71 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ 72 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 73 | 74 | # --- Modified: nix_build_docker_upx --- 75 | nix_build_docker_upx: 76 | @_start_time_ns=$$(date +%s%N); \ 77 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 78 | nix build .#docker-image-upx; \ 79 | _end_time_ns=$$(date +%s%N); \ 80 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 81 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ # Record duration only 82 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 83 | 84 | # --- Modified: nix_build_docker_scratch --- 85 | nix_build_docker_scratch: 86 | @_start_time_ns=$$(date +%s%N); \ 87 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 88 | nix build .#docker-image-scratch; \ 89 | _end_time_ns=$$(date +%s%N); \ 90 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 91 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ # Record duration only 92 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 93 | 94 | # --- Modified: nix_build_docker_trace (No change needed unless you want its duration too) --- 95 | nix_build_docker_trace: 96 | @_start_time_ns=$$(date +%s%N); \ 97 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 98 | nix build . --show-trace; \ 99 | _end_time_ns=$$(date +%s%N); \ 100 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 101 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ # Optionally record duration 102 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 103 | 104 | # --- Modified: nix_build_docker_load --- 105 | nix_build_docker_load: 106 | @_start_time_ns=$$(date +%s%N); \ 107 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 108 | _loaded_image_line=""; _loaded_image_tag="N/A"; _image_size="N/A"; \ 109 | _loaded_image_line=$$(docker load < result 2>/dev/null | tee /dev/stderr | grep 'Loaded image:'); \ 110 | if [[ -n "$${_loaded_image_line}" ]]; then \ 111 | _loaded_image_tag=$$(echo "$${_loaded_image_line}" | sed 's/Loaded image: //'); \ 112 | sleep 1; \ # Give daemon a moment 113 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_loaded_image_tag}" 2>/dev/null || echo "Error"); \ 114 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 115 | else \ 116 | echo "[$($(TIMESTAMP))] Failed to load image or capture tag from ./result"; \ 117 | _loaded_image_tag="(load failed)"; \ 118 | fi; \ 119 | _end_time_ns=$$(date +%s%N); \ 120 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 121 | echo "$@,$${_duration_ms},$${_loaded_image_tag:-N/A},$${_image_size:-N/A}" >> $(SUMMARY_FILE); \ 122 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Loaded: $${_loaded_image_tag:-None}. Size: $${_image_size:-N/A}"; 123 | 124 | #--------- 125 | # gomod2nix 126 | # --- Modified: Treat gomod2nix like other build/load pairs --- 127 | gomod2nix: nix_build_docker_gomod2nix nix_build_docker_gomod2nix_load 128 | 129 | # --- Modified: nix_build_docker_gomod2nix --- 130 | nix_build_docker_gomod2nix: 131 | @_start_time_ns=$$(date +%s%N); \ 132 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 133 | nix build .#docker-image-gomod2nix; \ 134 | _end_time_ns=$$(date +%s%N); \ 135 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 136 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ # Record duration only 137 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 138 | 139 | # --- Modified: nix_build_docker_gomod2nix_load (Similar to nix_build_docker_load) --- 140 | nix_build_docker_gomod2nix_load: 141 | @_start_time_ns=$$(date +%s%N); \ 142 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 143 | _loaded_image_line=""; _loaded_image_tag="N/A"; _image_size="N/A"; \ 144 | _loaded_image_line=$$(docker load < result 2>/dev/null | tee /dev/stderr | grep 'Loaded image:'); \ 145 | if [[ -n "$${_loaded_image_line}" ]]; then \ 146 | _loaded_image_tag=$$(echo "$${_loaded_image_line}" | sed 's/Loaded image: //'); \ 147 | sleep 1; \ # Give daemon a moment 148 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_loaded_image_tag}" 2>/dev/null || echo "Error"); \ 149 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 150 | else \ 151 | echo "[$($(TIMESTAMP))] Failed to load image or capture tag from ./result (gomod2nix)"; \ 152 | _loaded_image_tag="(load failed)"; \ 153 | fi; \ 154 | _end_time_ns=$$(date +%s%N); \ 155 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 156 | echo "$@,$${_duration_ms},$${_loaded_image_tag:-N/A},$${_image_size:-N/A}" >> $(SUMMARY_FILE); \ 157 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Loaded: $${_loaded_image_tag:-None}. Size: $${_image_size:-N/A}"; 158 | 159 | #-------------------------- 160 | # docker build 161 | 162 | # --- Modified: builddocker_go-nix-simple-distroless --- 163 | builddocker_go-nix-simple-distroless: 164 | @_start_time_ns=$$(date +%s%N); \ 165 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 166 | echo "================================"; \ 167 | _image_tag="randomizedcoder/docker-go-nix-simple-distroless:${VERSION}"; \ 168 | _latest_tag="randomizedcoder/docker-go-nix-simple-distroless:latest"; \ 169 | echo "Make builddocker_go_nix_simple $${_image_tag}"; \ 170 | docker build \ 171 | --network=host \ 172 | --build-arg MYPATH=${MYPATH} \ 173 | --build-arg COMMIT=${COMMIT} \ 174 | --build-arg DATE=${DATE} \ 175 | --build-arg VERSION=${VERSION} \ 176 | --file build/containers/go_nix_simple/Containerfile \ 177 | --tag "$${_image_tag}" \ 178 | --tag "$${_latest_tag}" \ 179 | ${MYPATH}; \ 180 | _build_exit_code=$$?; \ 181 | _image_size="N/A"; \ 182 | if [[ $$_build_exit_code -eq 0 ]]; then \ 183 | sleep 1; \ # Give daemon a moment 184 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_image_tag}" 2>/dev/null || echo "Error"); \ 185 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 186 | else \ 187 | echo "[$($(TIMESTAMP))] Docker build failed for $@"; \ 188 | _image_tag="$${_image_tag} (build failed)"; \ 189 | fi; \ 190 | _end_time_ns=$$(date +%s%N); \ 191 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 192 | echo "$@,$${_duration_ms},$${_image_tag},$${_image_size}" >> $(SUMMARY_FILE); \ 193 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Image: $${_image_tag}. Size: $${_image_size:-N/A}"; \ 194 | exit $$_build_exit_code 195 | 196 | # --- Modified: builddocker_go-nix-simple-distroless-athens --- 197 | builddocker_go-nix-simple-distroless-athens: 198 | @_start_time_ns=$$(date +%s%N); \ 199 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 200 | echo "================================"; \ 201 | _image_tag="randomizedcoder/docker-go-nix-simple-distroless-athens:${VERSION}"; \ 202 | _latest_tag="randomizedcoder/docker-go-nix-simple-distroless-athens:latest"; \ 203 | echo "Make builddocker_go_nix_simple $${_image_tag}"; \ 204 | docker build \ 205 | --progress=plain \ 206 | --network=host \ 207 | --build-arg MYPATH=${MYPATH} \ 208 | --build-arg COMMIT=${COMMIT} \ 209 | --build-arg DATE=${DATE} \ 210 | --build-arg VERSION=${VERSION} \ 211 | --file build/containers/go_nix_simple/Containerfile_athens \ 212 | --tag "$${_image_tag}" \ 213 | --tag "$${_latest_tag}" \ 214 | ${MYPATH}; \ 215 | _build_exit_code=$$?; \ 216 | _image_size="N/A"; \ 217 | if [[ $$_build_exit_code -eq 0 ]]; then \ 218 | sleep 1; \ 219 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_image_tag}" 2>/dev/null || echo "Error"); \ 220 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 221 | else \ 222 | echo "[$($(TIMESTAMP))] Docker build failed for $@"; \ 223 | _image_tag="$${_image_tag} (build failed)"; \ 224 | fi; \ 225 | _end_time_ns=$$(date +%s%N); \ 226 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 227 | echo "$@,$${_duration_ms},$${_image_tag},$${_image_size}" >> $(SUMMARY_FILE); \ 228 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Image: $${_image_tag}. Size: $${_image_size:-N/A}"; \ 229 | exit $$_build_exit_code 230 | 231 | # --- Modified: builddocker_go-nix-simple-scratch --- 232 | builddocker_go-nix-simple-scratch: 233 | @_start_time_ns=$$(date +%s%N); \ 234 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 235 | echo "================================"; \ 236 | _image_tag="randomizedcoder/docker-go-nix-simple-scratch:${VERSION}"; \ 237 | _latest_tag="randomizedcoder/docker-go-nix-simple-scratch:latest"; \ 238 | echo "Make builddocker_go_nix_simple $${_image_tag}"; \ 239 | docker build \ 240 | --network=host \ 241 | --build-arg MYPATH=${MYPATH} \ 242 | --build-arg COMMIT=${COMMIT} \ 243 | --build-arg DATE=${DATE} \ 244 | --build-arg VERSION=${VERSION} \ 245 | --file build/containers/go_nix_simple/Containerfile_scratch \ 246 | --tag "$${_image_tag}" \ 247 | --tag "$${_latest_tag}" \ 248 | ${MYPATH}; \ 249 | _build_exit_code=$$?; \ 250 | _image_size="N/A"; \ 251 | if [[ $$_build_exit_code -eq 0 ]]; then \ 252 | sleep 1; \ 253 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_image_tag}" 2>/dev/null || echo "Error"); \ 254 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 255 | else \ 256 | echo "[$($(TIMESTAMP))] Docker build failed for $@"; \ 257 | _image_tag="$${_image_tag} (build failed)"; \ 258 | fi; \ 259 | _end_time_ns=$$(date +%s%N); \ 260 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 261 | echo "$@,$${_duration_ms},$${_image_tag},$${_image_size}" >> $(SUMMARY_FILE); \ 262 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Image: $${_image_tag}. Size: $${_image_size:-N/A}"; \ 263 | exit $$_build_exit_code 264 | 265 | # --- Modified: builddocker_go-nix-simple-upx --- 266 | builddocker_go-nix-simple-upx: 267 | @_start_time_ns=$$(date +%s%N); \ 268 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 269 | echo "================================"; \ 270 | _image_tag="randomizedcoder/docker-go-nix-simple-scratch-upx:${VERSION}"; \ 271 | _latest_tag="randomizedcoder/docker-go-nix-simple-scratch-upx:latest"; \ 272 | echo "Make builddocker_go_nix_simple $${_image_tag}"; \ 273 | docker build \ 274 | --network=host \ 275 | --build-arg MYPATH=${MYPATH} \ 276 | --build-arg COMMIT=${COMMIT} \ 277 | --build-arg DATE=${DATE} \ 278 | --build-arg VERSION=${VERSION} \ 279 | --file build/containers/go_nix_simple/Containerfile_upx \ 280 | --tag "$${_image_tag}" \ 281 | --tag "$${_latest_tag}" \ 282 | ${MYPATH}; \ 283 | _build_exit_code=$$?; \ 284 | _image_size="N/A"; \ 285 | if [[ $$_build_exit_code -eq 0 ]]; then \ 286 | sleep 1; \ 287 | _image_size=$$(docker image inspect --format='{{.Size}}' "$${_image_tag}" 2>/dev/null || echo "Error"); \ 288 | if [[ "$${_image_size}" == "Error" ]]; then _image_size="N/A"; fi; \ 289 | else \ 290 | echo "[$($(TIMESTAMP))] Docker build failed for $@"; \ 291 | _image_tag="$${_image_tag} (build failed)"; \ 292 | fi; \ 293 | _end_time_ns=$$(date +%s%N); \ 294 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 295 | echo "$@,$${_duration_ms},$${_image_tag},$${_image_size}" >> $(SUMMARY_FILE); \ 296 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms. Image: $${_image_tag}. Size: $${_image_size:-N/A}"; \ 297 | exit $$_build_exit_code 298 | 299 | # ... (Keep docker compose athens, nix build athens, inspect targets etc. as they are, unless you want durations for them too) ... 300 | 301 | # --- Modified: ls target (Optional: Add duration) --- 302 | ls: 303 | @_start_time_ns=$$(date +%s%N); \ 304 | echo "[$($(TIMESTAMP))] Starting $@..."; \ 305 | docker image ls randomizedcoder/nix-go-nix-simple-distroless; \ 306 | docker image ls randomizedcoder/nix-go-nix-simple-scratch; \ 307 | docker image ls randomizedcoder/gomod2nix-go-nix-simple-scratch; \ 308 | docker image ls randomizedcoder/docker-go-nix-simple-distroless; \ 309 | docker image ls randomizedcoder/docker-go-nix-simple-distroless-athens; \ 310 | docker image ls randomizedcoder/docker-go-nix-simple-distroless-scratch; \ 311 | docker image ls randomizedcoder/gomod2nix-go-nix-simple-scratch; \ 312 | @echo "===="; \ 313 | docker image ls | grep go-nix-simple; \ 314 | _end_time_ns=$$(date +%s%N); \ 315 | _duration_ms=$$(( (_end_time_ns - _start_time_ns) / 1000000 )); \ 316 | echo "$@,$${_duration_ms},N/A,N/A" >> $(SUMMARY_FILE); \ 317 | echo "[$($(TIMESTAMP))] Finished $@. Duration: $$_duration_ms ms." 318 | 319 | 320 | # ... (Keep dive, run, curl, prepare, clear_go_mod_cache, go_glean, flake commands) ... 321 | 322 | # --- New: Summary Target --- 323 | summary: 324 | @echo "" 325 | @echo "========================================= Build Summary ==========================================" 326 | @echo "| Target | Duration (ms) | Image Tag / Info | Size |" 327 | @echo "|----------------------------------------|---------------|--------------------------------------------|------------|" 328 | @if [ -f $(SUMMARY_FILE) ]; then \ 329 | LC_NUMERIC=C awk -F',' '{ \ 330 | target=$1; \ 331 | duration=$2; \ 332 | tag=$3; \ 333 | size_bytes=$4; \ 334 | size_human="N/A"; \ 335 | \ 336 | if (tag == "N/A") { tag = "-"; } \ 337 | if (size_bytes == "N/A") { \ 338 | size_human = "-"; \ 339 | } else if (size_bytes == "Error") { \ 340 | size_human = "Error"; \ 341 | } else if (size_bytes ~ /^[0-9]+$$/) { \ 342 | if (size_bytes > 1024*1024*1024) { \ 343 | size_human = sprintf("%.2f GiB", size_bytes / 1024 / 1024 / 1024); \ 344 | } else if (size_bytes > 1024*1024) { \ 345 | size_human = sprintf("%.2f MiB", size_bytes / 1024 / 1024); \ 346 | } else if (size_bytes > 1024) { \ 347 | size_human = sprintf("%.2f KiB", size_bytes / 1024); \ 348 | } else { \ 349 | size_human = sprintf("%d B", size_bytes); \ 350 | } \ 351 | } else { \ 352 | size_human = "?"; \ 353 | } \ 354 | \ 355 | printf "| %-38s | %-13s | %-42s | %-10s |\n", target, duration, tag, size_human; \ 356 | }' $(SUMMARY_FILE); \ 357 | else \ 358 | echo "| No summary data found ($(SUMMARY_FILE) missing). |"; \ 359 | fi; \ 360 | echo "==================================================================================================" 361 | 362 | #-------------------------- 363 | # docker compose athens 364 | 365 | # https://docs.docker.com/engine/reference/commandline/docker/ 366 | # https://docs.docker.com/compose/reference/ 367 | deploy_athens: 368 | @echo "================================" 369 | @echo "Make deploy_athens" 370 | docker compose \ 371 | --file build/containers/athens/docker-compose-athens.yml \ 372 | up -d --remove-orphans 373 | 374 | down_athens: 375 | @echo "================================" 376 | @echo "Make down_athens" 377 | docker compose \ 378 | --file build/containers/athens/docker-compose-athens.yml \ 379 | down 380 | 381 | athens_traffic: 382 | sudo tcpdump -ni any port 8888 383 | 384 | #-------------------------- 385 | # nix build athens docker container 386 | 387 | nix_build_athens: 388 | nix build .#athens-nix-image 389 | docker load < result 390 | 391 | run_athens: 392 | docker run -d -p 8888:8888 randomizedcoder/athens-nix:latest 393 | 394 | #-------------------------- 395 | # inspect 396 | 397 | # ls: 398 | # docker image ls randomizedcoder/nix-go-nix-simple-distroless; 399 | # docker image ls randomizedcoder/nix-go-nix-simple-scratch; 400 | # docker image ls randomizedcoder/gomod2nix-go-nix-simple-scratch 401 | # docker image ls randomizedcoder/docker-go-nix-simple-distroless; 402 | # docker image ls randomizedcoder/docker-go-nix-simple-distroless-athens; 403 | # docker image ls randomizedcoder/docker-go-nix-simple-distroless-scratch; 404 | # docker image ls randomizedcoder/gomod2nix-go-nix-simple-scratch; 405 | # @echo "====" 406 | # docker image ls | grep go-nix-simple 407 | 408 | dive: 409 | dive randomizedcoder/go-nix-simple:latest 410 | 411 | dive-distroless: 412 | dive randomizedcoder/go-nix-simple-distroless:latest 413 | 414 | run: 415 | docker run -d -p 9108:9108 randomizedcoder/go-nix-simple:latest 416 | 417 | run-distroless: 418 | docker run -d -p 9108:9108 randomizedcoder/go-nix-simple-distroless:latest 419 | 420 | curl: 421 | curl http://localhost:9108/metrics 422 | 423 | # https://ryantm.github.io/nixpkgs/builders/images/dockertools/#ssec-pkgs-dockerTools-fetchFromRegistry 424 | # https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/docker/nix-prefetch-docker 425 | prepare: 426 | nix-shell -p nix-prefetch-docker 427 | nix-prefetch-docker --image-name gcr.io/distroless/static-debian12 --image-tag latest 428 | 429 | #-------------------------- 430 | # clear go mod cache 431 | 432 | clear_go_mod_cache: 433 | sudo rm -rf /home/das/go/pkg/mod/ 434 | 435 | go_glean: 436 | go clean -modcache 437 | 438 | #-------------------------- 439 | # flake commands 440 | 441 | flake_metadata: 442 | nix flake metadata 443 | 444 | flake_show: 445 | nix flake show 446 | 447 | 448 | # end 449 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 -------------------------------------------------------------------------------- /build/containers/athens/docker-compose-athens.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Athens docker-compose-athens.yml 3 | # 4 | 5 | name: athens 6 | 7 | # networks: 8 | # net: 9 | # driver: bridge 10 | # enable_ipv6: false 11 | # driver_opts: 12 | # # https://docs.docker.com/network/drivers/bridge/#options 13 | # com.docker.network.bridge.name: br-athens 14 | # # https://docs.docker.com/compose/networking/#use-a-pre-existing-network 15 | # ipam: 16 | # config: 17 | # - subnet: 10.88.88.0/24 18 | # gateway: 10.88.88.1 19 | # # # IPv6 docker compose doesn't really work: https://github.com/docker/compose/issues/4958 20 | # # # https://www.unique-local-ipv6.com/# 21 | # # - subnet: fddc:1218:ef3::/64 22 | # # gateway: fddc:1218:ef3::1 23 | 24 | volumes: 25 | athens: {} 26 | 27 | services: 28 | #---------------------------------------------------------- 29 | # https://docs.gomods.io/install/using-docker/ 30 | athens: 31 | container_name: athens 32 | # https://hub.docker.com/r/gomods/athens/tags 33 | image: gomods/athens:latest 34 | volumes: 35 | - athens:/tmp/athens 36 | environment: 37 | ATHENS_HOST: 0.0.0.0 38 | ATHENS_PORT: 8888 39 | ATHENS_LOG_LEVEL: debug 40 | ATHENS_DISK_STORAGE_ROOT: /tmp/athens 41 | ATHENS_STORAGE_TYPE: disk 42 | # networks: 43 | # net: 44 | # ipv4_address: 10.88.88.88 45 | # ports: 46 | # - 8888:8888 47 | network_mode: host 48 | 49 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | RUN --mount=type=cache,target=/go/pkg/mod \ 36 | --mount=type=cache,target=/root/.cache/go-build \ 37 | CGO_ENABLED=0 go build \ 38 | -trimpath \ 39 | -tags=netgo,osusergo \ 40 | -ldflags="-s -w" \ 41 | -o /go/bin/go_nix_simple \ 42 | ./cmd/go_nix_simple/go_nix_simple.go 43 | 44 | # # GOPROXY=http://10.88.88.88:8888 \ 45 | # RUN GOPROXY=http://localhost:8888 \ 46 | # CGO_ENABLED=0 go build \ 47 | # -o /go/bin/go_nix_simple \ 48 | # ./cmd/go_nix_simple/go_nix_simple.go 49 | 50 | # https://github.com/docker-archive/compose-cli/blob/main/Dockerfile#L31 51 | 52 | FROM scratch AS arrange 53 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 54 | COPY --from=build --chmod=444 /go/src/VERSION / 55 | 56 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available 57 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#debug-images 58 | #FROM gcr.io/distroless/static-debian12:nonroot 59 | FROM gcr.io/distroless/static-debian12 60 | #FROM gcr.io/distroless/static-debian12:debug 61 | #FROM scratch 62 | 63 | # becomes a single layer 64 | COPY --from=arrange / / 65 | 66 | USER 9999:9999 67 | 68 | # Prometheus 69 | EXPOSE 9108 70 | 71 | ENTRYPOINT ["/go_nix_simple"] 72 | 73 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_athens: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile_athens 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | # RUN --mount=type=cache,target=/go/pkg/mod \ 36 | # --mount=type=cache,target=/root/.cache/go-build \ 37 | # CGO_ENABLED=0 go build \ 38 | # -o /go/bin/go_nix_simple \ 39 | # ./cmd/go_nix_simple/go_nix_simple.go 40 | 41 | # https://go.dev/ref/mod 42 | # https://go.dev/ref/mod#module-proxy 43 | # https://go.dev/ref/mod#private-module-proxy-private 44 | #RUN GOPROXY=http://localhost:8888,https://proxy.golang.org,direct \ 45 | RUN GOPROXY=http://hp4.home:8888,https://proxy.golang.org,direct \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | 53 | # https://github.com/docker-archive/compose-cli/blob/main/Dockerfile#L31 54 | 55 | FROM scratch AS arrange 56 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 57 | COPY --from=build --chmod=444 /go/src/VERSION / 58 | 59 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available 60 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#debug-images 61 | #FROM gcr.io/distroless/static-debian12:nonroot 62 | FROM gcr.io/distroless/static-debian12 63 | #FROM gcr.io/distroless/static-debian12:debug 64 | 65 | # becomes a single layer 66 | COPY --from=arrange / / 67 | 68 | USER 9999:9999 69 | 70 | # Prometheus 71 | EXPOSE 9108 72 | 73 | ENTRYPOINT ["/go_nix_simple"] 74 | 75 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_http_cache: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | # RUN --mount=type=cache,target=/go/pkg/mod \ 36 | # --mount=type=cache,target=/root/.cache/go-build \ 37 | RUN HTTP_PROXY=http://hp4.home:3128 \ 38 | HTTPs_PROXY=http://hp4.home:3128 \ 39 | CGO_ENABLED=0 go build \ 40 | -trimpath \ 41 | -tags=netgo,osusergo \ 42 | -ldflags="-s -w" \ 43 | -o /go/bin/go_nix_simple \ 44 | ./cmd/go_nix_simple/go_nix_simple.go 45 | 46 | # # GOPROXY=http://10.88.88.88:8888 \ 47 | # RUN GOPROXY=http://localhost:8888 \ 48 | # CGO_ENABLED=0 go build \ 49 | # -o /go/bin/go_nix_simple \ 50 | # ./cmd/go_nix_simple/go_nix_simple.go 51 | 52 | # https://github.com/docker-archive/compose-cli/blob/main/Dockerfile#L31 53 | 54 | FROM scratch AS arrange 55 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 56 | COPY --from=build --chmod=444 /go/src/VERSION / 57 | 58 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available 59 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#debug-images 60 | #FROM gcr.io/distroless/static-debian12:nonroot 61 | #FROM gcr.io/distroless/static-debian12 62 | #FROM gcr.io/distroless/static-debian12:debug 63 | FROM scratch 64 | 65 | # becomes a single layer 66 | COPY --from=arrange / / 67 | 68 | USER 9999:9999 69 | 70 | # Prometheus 71 | EXPOSE 9108 72 | 73 | ENTRYPOINT ["/go_nix_simple"] 74 | 75 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_nix: -------------------------------------------------------------------------------- 1 | 2 | 3 | FROM nixos/nix AS build 4 | 5 | # Install nginx 6 | RUN mkdir -p /output/store 7 | RUN nix-env --profile /output/profile -i nginx 8 | RUN cp -va $(nix-store -qR /output/profile) /output/store 9 | 10 | # Create empty directories needed by nginx 11 | RUN mkdir -p /to_add/var/log/nginx \ 12 | /to_add/var/cache/nginx \ 13 | /to_add/var/conf/ \ 14 | /to_add/var/www 15 | 16 | # Create user and group for nginx 17 | RUN addgroup --system nginx 18 | RUN adduser --system -G nginx --uid 31337 nginx 19 | 20 | # Make sure nginx can write to required directories 21 | RUN chown -R 31337 /to_add/ 22 | 23 | FROM scratch 24 | 25 | # Copy over nginx files and dependencies 26 | COPY --from=build /output/store /nix/store 27 | COPY --from=build /output/profile/ /usr/local/ 28 | COPY --from=build /to_add / 29 | 30 | # Copy required user information 31 | COPY --from=build /etc/passwd /etc/passwd 32 | COPY --from=build /etc/group /etc/group 33 | 34 | # Add user specific content and config 35 | COPY ./index.html /var/www/ 36 | COPY ./nginx.conf /var/conf/nginx.conf 37 | EXPOSE 80 38 | CMD ["nginx", "-p", "/var/"] -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_no_cache: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | # RUN --mount=type=cache,target=/go/pkg/mod \ 36 | # --mount=type=cache,target=/root/.cache/go-build \ 37 | RUN CGO_ENABLED=0 go build \ 38 | -trimpath \ 39 | -tags=netgo,osusergo \ 40 | -ldflags="-s -w" \ 41 | -o /go/bin/go_nix_simple \ 42 | ./cmd/go_nix_simple/go_nix_simple.go 43 | 44 | # # GOPROXY=http://10.88.88.88:8888 \ 45 | # RUN GOPROXY=http://localhost:8888 \ 46 | # CGO_ENABLED=0 go build \ 47 | # -o /go/bin/go_nix_simple \ 48 | # ./cmd/go_nix_simple/go_nix_simple.go 49 | 50 | # https://github.com/docker-archive/compose-cli/blob/main/Dockerfile#L31 51 | 52 | FROM scratch AS arrange 53 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 54 | COPY --from=build --chmod=444 /go/src/VERSION / 55 | 56 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available 57 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#debug-images 58 | #FROM gcr.io/distroless/static-debian12:nonroot 59 | #FROM gcr.io/distroless/static-debian12 60 | #FROM gcr.io/distroless/static-debian12:debug 61 | FROM scratch 62 | 63 | # becomes a single layer 64 | COPY --from=arrange / / 65 | 66 | USER 9999:9999 67 | 68 | # Prometheus 69 | EXPOSE 9108 70 | 71 | ENTRYPOINT ["/go_nix_simple"] 72 | 73 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_scratch: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile_scratch 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | RUN --mount=type=cache,target=/go/pkg/mod \ 36 | --mount=type=cache,target=/root/.cache/go-build \ 37 | CGO_ENABLED=0 go build \ 38 | -trimpath \ 39 | -tags=netgo,osusergo \ 40 | -ldflags="-s -w" \ 41 | -o /go/bin/go_nix_simple \ 42 | ./cmd/go_nix_simple/go_nix_simple.go 43 | 44 | ADD --chmod=444 https://curl.haxx.se/ca/cacert.pem /certs.crt 45 | 46 | FROM scratch AS arrange 47 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 48 | COPY --from=build --chmod=444 /go/src/VERSION / 49 | COPY --from=build --chmod=444 /certs.crt /etc/ssl/certs/ca-certificates.crt 50 | 51 | FROM scratch 52 | # becomes a single layer 53 | COPY --from=arrange / / 54 | 55 | USER 9999:9999 56 | 57 | # Prometheus 58 | EXPOSE 9108 59 | 60 | ENTRYPOINT ["/go_nix_simple"] 61 | 62 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple/Containerfile_upx: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/go_nix_simple/Containerfile 3 | # 4 | 5 | # Passed in variables 6 | ARG MYPATH 7 | ARG COMMIT 8 | ARG DATE 9 | ARG VERSION 10 | 11 | ARG TARGETOS 12 | ARG TARGETARCH 13 | ARG TARGETPLATFORM 14 | 15 | ARG GO_VERSION=1.24.2 16 | 17 | #https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#examples-with-docker 18 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 19 | 20 | ARG MYPATH 21 | ARG COMMIT 22 | ARG DATE 23 | ARG VERSION 24 | 25 | ARG TARGETOS 26 | ARG TARGETARCH 27 | ARG TARGETPLATFORM 28 | 29 | RUN echo MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} \ 30 | BUILDPLATFORM:${BUILDPLATFORM} TARGETPLATFORM:${TARGETPLATFORM} 31 | 32 | WORKDIR /go/src 33 | COPY . . 34 | 35 | RUN --mount=type=cache,target=/go/pkg/mod \ 36 | --mount=type=cache,target=/root/.cache/go-build \ 37 | CGO_ENABLED=0 go build \ 38 | -trimpath \ 39 | -tags=netgo,osusergo \ 40 | -ldflags="-s -w" \ 41 | -o /go/bin/go_nix_simple \ 42 | ./cmd/go_nix_simple/go_nix_simple.go 43 | 44 | # # GOPROXY=http://10.88.88.88:8888 \ 45 | # RUN GOPROXY=http://localhost:8888 \ 46 | # CGO_ENABLED=0 go build \ 47 | # -o /go/bin/go_nix_simple \ 48 | # ./cmd/go_nix_simple/go_nix_simple.go 49 | 50 | # https://github.com/docker-archive/compose-cli/blob/main/Dockerfile#L31 51 | 52 | #-------------------- 53 | # COMPRESS 54 | # https://hub.docker.com/_/debian/tags 55 | FROM debian:bullseye-slim AS compress 56 | RUN --mount=type=cache,target=/var/cache/apt \ 57 | --mount=type=cache,target=/var/lib/apt/lists \ 58 | apt-get update && \ 59 | apt-get install -y --no-install-recommends upx-ucl 60 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 61 | #RUN ls -lh /go_nix_simple 62 | RUN upx --best --lzma /go_nix_simple 63 | #RUN ls -lh /go_nix_simple 64 | 65 | # WARNING!! Don't do this!! Nix store is empty! 66 | # #-------------------- 67 | # # COMPRESS Nix 68 | # FROM nixos/nix:latest AS compress 69 | # COPY --from=build /go/bin/go_nix_simple /go_nix_simple 70 | # RUN --mount=type=cache,target=/nix/store \ 71 | # nix-shell -p upx --run "upx --best --lzma /go_nix_simple" 72 | 73 | FROM scratch AS arrange 74 | COPY --from=compress --chmod=544 /go_nix_simple / 75 | COPY --from=build --chmod=444 /go/src/VERSION / 76 | 77 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#what-images-are-available 78 | # https://github.com/GoogleContainerTools/distroless?tab=readme-ov-file#debug-images 79 | #FROM gcr.io/distroless/static-debian12:nonroot 80 | FROM gcr.io/distroless/static-debian12 81 | #FROM gcr.io/distroless/static-debian12:debug 82 | #FROM scratch 83 | 84 | # becomes a single layer 85 | COPY --from=arrange / / 86 | 87 | USER 9999:9999 88 | 89 | # Prometheus 90 | EXPOSE 9108 91 | 92 | ENTRYPOINT ["/go_nix_simple"] 93 | 94 | # end -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.athens.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=athens, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN GOPROXY=http://localhost:8888,https://proxy.golang.org,direct \ 45 | CGO_ENABLED=0 go build \ 46 | -trimpath \ 47 | -tags=netgo,osusergo \ 48 | -ldflags="-s -w" \ 49 | -o /go/bin/go_nix_simple \ 50 | ./cmd/go_nix_simple/go_nix_simple.go 51 | # --- End Go Build Step --- 52 | 53 | # --- UPX Stage (Conditional) --- 54 | 55 | # --- End UPX Stage --- 56 | 57 | # --- Arrange Stage --- 58 | # Consolidates artifacts needed for the final image 59 | FROM scratch AS arrange 60 | 61 | # Copy the executable (either original or UPX'd) 62 | 63 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 64 | 65 | 66 | # Copy the VERSION file 67 | COPY --from=build --chmod=444 /go/src/VERSION / 68 | 69 | # Copy CA certs only if the final base image is scratch 70 | 71 | # --- End Arrange Stage --- 72 | 73 | 74 | # --- Final Stage --- 75 | FROM gcr.io/distroless/static-debian12 76 | COPY --from=arrange / / 77 | USER 9999:9999 78 | EXPOSE 9108 79 | ENTRYPOINT ["/go_nix_simple"] 80 | # --- End Final Stage --- 81 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.athens.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=athens, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN GOPROXY=http://localhost:8888,https://proxy.golang.org,direct \ 45 | CGO_ENABLED=0 go build \ 46 | -trimpath \ 47 | -tags=netgo,osusergo \ 48 | -ldflags="-s -w" \ 49 | -o /go/bin/go_nix_simple \ 50 | ./cmd/go_nix_simple/go_nix_simple.go 51 | # --- End Go Build Step --- 52 | 53 | # --- UPX Stage (Conditional) --- 54 | 55 | FROM debian:bullseye-slim AS compress 56 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 57 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 58 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 59 | RUN upx --best --lzma /go_nix_simple 60 | 61 | # --- End UPX Stage --- 62 | 63 | # --- Arrange Stage --- 64 | # Consolidates artifacts needed for the final image 65 | FROM scratch AS arrange 66 | 67 | # Copy the executable (either original or UPX'd) 68 | 69 | COPY --from=compress --chmod=544 /go_nix_simple / 70 | 71 | 72 | # Copy the VERSION file 73 | COPY --from=build --chmod=444 /go/src/VERSION / 74 | 75 | # Copy CA certs only if the final base image is scratch 76 | 77 | # --- End Arrange Stage --- 78 | 79 | 80 | # --- Final Stage --- 81 | FROM gcr.io/distroless/static-debian12 82 | COPY --from=arrange / / 83 | USER 9999:9999 84 | EXPOSE 9108 85 | ENTRYPOINT ["/go_nix_simple"] 86 | # --- End Final Stage --- 87 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.docker.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=docker, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN --mount=type=cache,target=/go/pkg/mod \ 45 | --mount=type=cache,target=/root/.cache/go-build \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | # --- End UPX Stage --- 57 | 58 | # --- Arrange Stage --- 59 | # Consolidates artifacts needed for the final image 60 | FROM scratch AS arrange 61 | 62 | # Copy the executable (either original or UPX'd) 63 | 64 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 65 | 66 | 67 | # Copy the VERSION file 68 | COPY --from=build --chmod=444 /go/src/VERSION / 69 | 70 | # Copy CA certs only if the final base image is scratch 71 | 72 | # --- End Arrange Stage --- 73 | 74 | 75 | # --- Final Stage --- 76 | FROM gcr.io/distroless/static-debian12 77 | COPY --from=arrange / / 78 | USER 9999:9999 79 | EXPOSE 9108 80 | ENTRYPOINT ["/go_nix_simple"] 81 | # --- End Final Stage --- 82 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.docker.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=docker, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN --mount=type=cache,target=/go/pkg/mod \ 45 | --mount=type=cache,target=/root/.cache/go-build \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | FROM debian:bullseye-slim AS compress 57 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 58 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 59 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 60 | RUN upx --best --lzma /go_nix_simple 61 | 62 | # --- End UPX Stage --- 63 | 64 | # --- Arrange Stage --- 65 | # Consolidates artifacts needed for the final image 66 | FROM scratch AS arrange 67 | 68 | # Copy the executable (either original or UPX'd) 69 | 70 | COPY --from=compress --chmod=544 /go_nix_simple / 71 | 72 | 73 | # Copy the VERSION file 74 | COPY --from=build --chmod=444 /go/src/VERSION / 75 | 76 | # Copy CA certs only if the final base image is scratch 77 | 78 | # --- End Arrange Stage --- 79 | 80 | 81 | # --- Final Stage --- 82 | FROM gcr.io/distroless/static-debian12 83 | COPY --from=arrange / / 84 | USER 9999:9999 85 | EXPOSE 9108 86 | ENTRYPOINT ["/go_nix_simple"] 87 | # --- End Final Stage --- 88 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.http.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=http, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN HTTP_PROXY=http://localhost:3128 \ 45 | HTTPS_PROXY=http://localhost:3128 \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | # --- End UPX Stage --- 57 | 58 | # --- Arrange Stage --- 59 | # Consolidates artifacts needed for the final image 60 | FROM scratch AS arrange 61 | 62 | # Copy the executable (either original or UPX'd) 63 | 64 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 65 | 66 | 67 | # Copy the VERSION file 68 | COPY --from=build --chmod=444 /go/src/VERSION / 69 | 70 | # Copy CA certs only if the final base image is scratch 71 | 72 | # --- End Arrange Stage --- 73 | 74 | 75 | # --- Final Stage --- 76 | FROM gcr.io/distroless/static-debian12 77 | COPY --from=arrange / / 78 | USER 9999:9999 79 | EXPOSE 9108 80 | ENTRYPOINT ["/go_nix_simple"] 81 | # --- End Final Stage --- 82 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.http.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=http, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN HTTP_PROXY=http://localhost:3128 \ 45 | HTTPS_PROXY=http://localhost:3128 \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | FROM debian:bullseye-slim AS compress 57 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 58 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 59 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 60 | RUN upx --best --lzma /go_nix_simple 61 | 62 | # --- End UPX Stage --- 63 | 64 | # --- Arrange Stage --- 65 | # Consolidates artifacts needed for the final image 66 | FROM scratch AS arrange 67 | 68 | # Copy the executable (either original or UPX'd) 69 | 70 | COPY --from=compress --chmod=544 /go_nix_simple / 71 | 72 | 73 | # Copy the VERSION file 74 | COPY --from=build --chmod=444 /go/src/VERSION / 75 | 76 | # Copy CA certs only if the final base image is scratch 77 | 78 | # --- End Arrange Stage --- 79 | 80 | 81 | # --- Final Stage --- 82 | FROM gcr.io/distroless/static-debian12 83 | COPY --from=arrange / / 84 | USER 9999:9999 85 | EXPOSE 9108 86 | ENTRYPOINT ["/go_nix_simple"] 87 | # --- End Final Stage --- 88 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.none.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=none, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN CGO_ENABLED=0 go build \ 45 | -trimpath \ 46 | -tags=netgo,osusergo \ 47 | -ldflags="-s -w" \ 48 | -o /go/bin/go_nix_simple \ 49 | ./cmd/go_nix_simple/go_nix_simple.go 50 | # --- End Go Build Step --- 51 | 52 | # --- UPX Stage (Conditional) --- 53 | 54 | # --- End UPX Stage --- 55 | 56 | # --- Arrange Stage --- 57 | # Consolidates artifacts needed for the final image 58 | FROM scratch AS arrange 59 | 60 | # Copy the executable (either original or UPX'd) 61 | 62 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 63 | 64 | 65 | # Copy the VERSION file 66 | COPY --from=build --chmod=444 /go/src/VERSION / 67 | 68 | # Copy CA certs only if the final base image is scratch 69 | 70 | # --- End Arrange Stage --- 71 | 72 | 73 | # --- Final Stage --- 74 | FROM gcr.io/distroless/static-debian12 75 | COPY --from=arrange / / 76 | USER 9999:9999 77 | EXPOSE 9108 78 | ENTRYPOINT ["/go_nix_simple"] 79 | # --- End Final Stage --- 80 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.distroless.none.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=gcr.io/distroless/static-debian12, Cache=none, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN CGO_ENABLED=0 go build \ 45 | -trimpath \ 46 | -tags=netgo,osusergo \ 47 | -ldflags="-s -w" \ 48 | -o /go/bin/go_nix_simple \ 49 | ./cmd/go_nix_simple/go_nix_simple.go 50 | # --- End Go Build Step --- 51 | 52 | # --- UPX Stage (Conditional) --- 53 | 54 | FROM debian:bullseye-slim AS compress 55 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 56 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 57 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 58 | RUN upx --best --lzma /go_nix_simple 59 | 60 | # --- End UPX Stage --- 61 | 62 | # --- Arrange Stage --- 63 | # Consolidates artifacts needed for the final image 64 | FROM scratch AS arrange 65 | 66 | # Copy the executable (either original or UPX'd) 67 | 68 | COPY --from=compress --chmod=544 /go_nix_simple / 69 | 70 | 71 | # Copy the VERSION file 72 | COPY --from=build --chmod=444 /go/src/VERSION / 73 | 74 | # Copy CA certs only if the final base image is scratch 75 | 76 | # --- End Arrange Stage --- 77 | 78 | 79 | # --- Final Stage --- 80 | FROM gcr.io/distroless/static-debian12 81 | COPY --from=arrange / / 82 | USER 9999:9999 83 | EXPOSE 9108 84 | ENTRYPOINT ["/go_nix_simple"] 85 | # --- End Final Stage --- 86 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.athens.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=athens, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN GOPROXY=http://localhost:8888,https://proxy.golang.org,direct \ 45 | CGO_ENABLED=0 go build \ 46 | -trimpath \ 47 | -tags=netgo,osusergo \ 48 | -ldflags="-s -w" \ 49 | -o /go/bin/go_nix_simple \ 50 | ./cmd/go_nix_simple/go_nix_simple.go 51 | # --- End Go Build Step --- 52 | 53 | # --- UPX Stage (Conditional) --- 54 | 55 | # --- End UPX Stage --- 56 | 57 | # --- Arrange Stage --- 58 | # Consolidates artifacts needed for the final image 59 | FROM scratch AS arrange 60 | 61 | # Copy the executable (either original or UPX'd) 62 | 63 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 64 | 65 | 66 | # Copy the VERSION file 67 | COPY --from=build --chmod=444 /go/src/VERSION / 68 | 69 | # Copy CA certs only if the final base image is scratch 70 | 71 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 72 | 73 | # --- End Arrange Stage --- 74 | 75 | 76 | # --- Final Stage --- 77 | FROM scratch 78 | COPY --from=arrange / / 79 | USER 9999:9999 80 | EXPOSE 9108 81 | ENTRYPOINT ["/go_nix_simple"] 82 | # --- End Final Stage --- 83 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.athens.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=athens, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN GOPROXY=http://localhost:8888,https://proxy.golang.org,direct \ 45 | CGO_ENABLED=0 go build \ 46 | -trimpath \ 47 | -tags=netgo,osusergo \ 48 | -ldflags="-s -w" \ 49 | -o /go/bin/go_nix_simple \ 50 | ./cmd/go_nix_simple/go_nix_simple.go 51 | # --- End Go Build Step --- 52 | 53 | # --- UPX Stage (Conditional) --- 54 | 55 | FROM debian:bullseye-slim AS compress 56 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 57 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 58 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 59 | RUN upx --best --lzma /go_nix_simple 60 | 61 | # --- End UPX Stage --- 62 | 63 | # --- Arrange Stage --- 64 | # Consolidates artifacts needed for the final image 65 | FROM scratch AS arrange 66 | 67 | # Copy the executable (either original or UPX'd) 68 | 69 | COPY --from=compress --chmod=544 /go_nix_simple / 70 | 71 | 72 | # Copy the VERSION file 73 | COPY --from=build --chmod=444 /go/src/VERSION / 74 | 75 | # Copy CA certs only if the final base image is scratch 76 | 77 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 78 | 79 | # --- End Arrange Stage --- 80 | 81 | 82 | # --- Final Stage --- 83 | FROM scratch 84 | COPY --from=arrange / / 85 | USER 9999:9999 86 | EXPOSE 9108 87 | ENTRYPOINT ["/go_nix_simple"] 88 | # --- End Final Stage --- 89 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.docker.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=docker, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN --mount=type=cache,target=/go/pkg/mod \ 45 | --mount=type=cache,target=/root/.cache/go-build \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | # --- End UPX Stage --- 57 | 58 | # --- Arrange Stage --- 59 | # Consolidates artifacts needed for the final image 60 | FROM scratch AS arrange 61 | 62 | # Copy the executable (either original or UPX'd) 63 | 64 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 65 | 66 | 67 | # Copy the VERSION file 68 | COPY --from=build --chmod=444 /go/src/VERSION / 69 | 70 | # Copy CA certs only if the final base image is scratch 71 | 72 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 73 | 74 | # --- End Arrange Stage --- 75 | 76 | 77 | # --- Final Stage --- 78 | FROM scratch 79 | COPY --from=arrange / / 80 | USER 9999:9999 81 | EXPOSE 9108 82 | ENTRYPOINT ["/go_nix_simple"] 83 | # --- End Final Stage --- 84 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.docker.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=docker, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN --mount=type=cache,target=/go/pkg/mod \ 45 | --mount=type=cache,target=/root/.cache/go-build \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | FROM debian:bullseye-slim AS compress 57 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 58 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 59 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 60 | RUN upx --best --lzma /go_nix_simple 61 | 62 | # --- End UPX Stage --- 63 | 64 | # --- Arrange Stage --- 65 | # Consolidates artifacts needed for the final image 66 | FROM scratch AS arrange 67 | 68 | # Copy the executable (either original or UPX'd) 69 | 70 | COPY --from=compress --chmod=544 /go_nix_simple / 71 | 72 | 73 | # Copy the VERSION file 74 | COPY --from=build --chmod=444 /go/src/VERSION / 75 | 76 | # Copy CA certs only if the final base image is scratch 77 | 78 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 79 | 80 | # --- End Arrange Stage --- 81 | 82 | 83 | # --- Final Stage --- 84 | FROM scratch 85 | COPY --from=arrange / / 86 | USER 9999:9999 87 | EXPOSE 9108 88 | ENTRYPOINT ["/go_nix_simple"] 89 | # --- End Final Stage --- 90 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.http.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=http, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN HTTP_PROXY=http://localhost:3128 \ 45 | HTTPS_PROXY=http://localhost:3128 \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | # --- End UPX Stage --- 57 | 58 | # --- Arrange Stage --- 59 | # Consolidates artifacts needed for the final image 60 | FROM scratch AS arrange 61 | 62 | # Copy the executable (either original or UPX'd) 63 | 64 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 65 | 66 | 67 | # Copy the VERSION file 68 | COPY --from=build --chmod=444 /go/src/VERSION / 69 | 70 | # Copy CA certs only if the final base image is scratch 71 | 72 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 73 | 74 | # --- End Arrange Stage --- 75 | 76 | 77 | # --- Final Stage --- 78 | FROM scratch 79 | COPY --from=arrange / / 80 | USER 9999:9999 81 | EXPOSE 9108 82 | ENTRYPOINT ["/go_nix_simple"] 83 | # --- End Final Stage --- 84 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.http.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=http, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN HTTP_PROXY=http://localhost:3128 \ 45 | HTTPS_PROXY=http://localhost:3128 \ 46 | CGO_ENABLED=0 go build \ 47 | -trimpath \ 48 | -tags=netgo,osusergo \ 49 | -ldflags="-s -w" \ 50 | -o /go/bin/go_nix_simple \ 51 | ./cmd/go_nix_simple/go_nix_simple.go 52 | # --- End Go Build Step --- 53 | 54 | # --- UPX Stage (Conditional) --- 55 | 56 | FROM debian:bullseye-slim AS compress 57 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 58 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 59 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 60 | RUN upx --best --lzma /go_nix_simple 61 | 62 | # --- End UPX Stage --- 63 | 64 | # --- Arrange Stage --- 65 | # Consolidates artifacts needed for the final image 66 | FROM scratch AS arrange 67 | 68 | # Copy the executable (either original or UPX'd) 69 | 70 | COPY --from=compress --chmod=544 /go_nix_simple / 71 | 72 | 73 | # Copy the VERSION file 74 | COPY --from=build --chmod=444 /go/src/VERSION / 75 | 76 | # Copy CA certs only if the final base image is scratch 77 | 78 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 79 | 80 | # --- End Arrange Stage --- 81 | 82 | 83 | # --- Final Stage --- 84 | FROM scratch 85 | COPY --from=arrange / / 86 | USER 9999:9999 87 | EXPOSE 9108 88 | ENTRYPOINT ["/go_nix_simple"] 89 | # --- End Final Stage --- 90 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.none.noupx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=none, UPX=false 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN CGO_ENABLED=0 go build \ 45 | -trimpath \ 46 | -tags=netgo,osusergo \ 47 | -ldflags="-s -w" \ 48 | -o /go/bin/go_nix_simple \ 49 | ./cmd/go_nix_simple/go_nix_simple.go 50 | # --- End Go Build Step --- 51 | 52 | # --- UPX Stage (Conditional) --- 53 | 54 | # --- End UPX Stage --- 55 | 56 | # --- Arrange Stage --- 57 | # Consolidates artifacts needed for the final image 58 | FROM scratch AS arrange 59 | 60 | # Copy the executable (either original or UPX'd) 61 | 62 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 63 | 64 | 65 | # Copy the VERSION file 66 | COPY --from=build --chmod=444 /go/src/VERSION / 67 | 68 | # Copy CA certs only if the final base image is scratch 69 | 70 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 71 | 72 | # --- End Arrange Stage --- 73 | 74 | 75 | # --- Final Stage --- 76 | FROM scratch 77 | COPY --from=arrange / / 78 | USER 9999:9999 79 | EXPOSE 9108 80 | ENTRYPOINT ["/go_nix_simple"] 81 | # --- End Final Stage --- 82 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.scratch.none.upx: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base=scratch, Cache=none, UPX=true 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION=1.24.2 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | RUN CGO_ENABLED=0 go build \ 45 | -trimpath \ 46 | -tags=netgo,osusergo \ 47 | -ldflags="-s -w" \ 48 | -o /go/bin/go_nix_simple \ 49 | ./cmd/go_nix_simple/go_nix_simple.go 50 | # --- End Go Build Step --- 51 | 52 | # --- UPX Stage (Conditional) --- 53 | 54 | FROM debian:bullseye-slim AS compress 55 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 56 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 57 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 58 | RUN upx --best --lzma /go_nix_simple 59 | 60 | # --- End UPX Stage --- 61 | 62 | # --- Arrange Stage --- 63 | # Consolidates artifacts needed for the final image 64 | FROM scratch AS arrange 65 | 66 | # Copy the executable (either original or UPX'd) 67 | 68 | COPY --from=compress --chmod=544 /go_nix_simple / 69 | 70 | 71 | # Copy the VERSION file 72 | COPY --from=build --chmod=444 /go/src/VERSION / 73 | 74 | # Copy CA certs only if the final base image is scratch 75 | 76 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 77 | 78 | # --- End Arrange Stage --- 79 | 80 | 81 | # --- Final Stage --- 82 | FROM scratch 83 | COPY --from=arrange / / 84 | USER 9999:9999 85 | EXPOSE 9108 86 | ENTRYPOINT ["/go_nix_simple"] 87 | # --- End Final Stage --- 88 | -------------------------------------------------------------------------------- /build/containers/go_nix_simple_refactor/Containerfile.tmpl: -------------------------------------------------------------------------------- 1 | # Generated Containerfile - DO NOT EDIT MANUALLY 2 | # Variant: Base={{.BaseImage}}, Cache={{.CachingMode}}, UPX={{.UseUPX}} 3 | 4 | # --- Global ARGs --- 5 | # These are available throughout the build 6 | ARG GO_VERSION={{.GoVersion}} 7 | ARG MYPATH=. # Default context path 8 | ARG COMMIT=unknown 9 | ARG DATE=unknown 10 | ARG VERSION=unknown 11 | ARG TARGETOS=linux # Default target OS 12 | ARG TARGETARCH=amd64 # Default target ARCH 13 | ARG TARGETPLATFORM=linux/amd64 # Usually set by Docker automatically 14 | 15 | # --- Build Stage --- 16 | FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS build 17 | 18 | # ARGs repeated here are only necessary if you need to use them 19 | # *within* this stage and want to ensure they override any global defaults 20 | # specifically for this stage (usually not needed if defined globally). 21 | # ARG COMMIT 22 | # ARG DATE 23 | # ARG VERSION 24 | 25 | # Set working directory within the build stage 26 | WORKDIR /go/src 27 | 28 | # Copy application source code 29 | # Consider being more specific if possible, e.g.: 30 | # COPY go.mod go.sum ./ 31 | # COPY cmd/ ./cmd/ 32 | # COPY internal/ ./internal/ # If you have internal packages 33 | # COPY VERSION ./ 34 | COPY . . 35 | 36 | # Optional: Copy CA certs from the builder image itself for later use in scratch 37 | RUN cp /etc/ssl/certs/ca-certificates.crt /ca-certificates.crt 38 | 39 | # Optional: Echo build args for debugging 40 | RUN echo "Building with MYPATH:${MYPATH} COMMIT:${COMMIT} DATE:${DATE} VERSION:${VERSION} TARGETPLATFORM:${TARGETPLATFORM}" 41 | 42 | # --- Go Build Step --- 43 | # This command is generated by the Go program based on CachingMode 44 | {{.GoBuildCommand}} 45 | # --- End Go Build Step --- 46 | 47 | # --- UPX Stage (Conditional) --- 48 | {{ if .UseUPX }} 49 | FROM debian:bullseye-slim AS compress 50 | RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt/lists \ 51 | apt-get update && apt-get install -y --no-install-recommends upx-ucl 52 | COPY --from=build /go/bin/go_nix_simple /go_nix_simple 53 | RUN upx --best --lzma /go_nix_simple 54 | {{ end }} 55 | # --- End UPX Stage --- 56 | 57 | # --- Arrange Stage --- 58 | # Consolidates artifacts needed for the final image 59 | FROM scratch AS arrange 60 | 61 | # Copy the executable (either original or UPX'd) 62 | {{ if .UseUPX }} 63 | COPY --from=compress --chmod=544 /go_nix_simple / 64 | {{ else }} 65 | COPY --from=build --chmod=544 /go/bin/go_nix_simple / 66 | {{ end }} 67 | 68 | # Copy the VERSION file 69 | COPY --from=build --chmod=444 /go/src/VERSION / 70 | 71 | # Copy CA certs only if the final base image is scratch 72 | {{ if eq .BaseImage "scratch" }} 73 | COPY --from=build --chmod=444 /ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 74 | {{ end }} 75 | # --- End Arrange Stage --- 76 | 77 | 78 | # --- Final Stage --- 79 | FROM {{.BaseImage}} 80 | COPY --from=arrange / / 81 | USER 9999:9999 82 | EXPOSE 9108 83 | ENTRYPOINT ["/go_nix_simple"] 84 | # --- End Final Stage --- 85 | -------------------------------------------------------------------------------- /build/containers/squid/Containerfile: -------------------------------------------------------------------------------- 1 | # 2 | # ./build/containers/squid/Containerfile 3 | # 4 | 5 | FROM sameersbn/squid:latest 6 | 7 | COPY squid.conf /etc/squid/squid.conf 8 | 9 | # end -------------------------------------------------------------------------------- /build/containers/squid/docker-compose-squid.yml: -------------------------------------------------------------------------------- 1 | services: 2 | squid: 3 | image: my-custom-squid:latest 4 | #image: sameersbn/squid:latest 5 | container_name: squid 6 | ports: 7 | - "3128:3128" 8 | restart: unless-stopped -------------------------------------------------------------------------------- /cmd/generate-containerfiles/.gitignore: -------------------------------------------------------------------------------- 1 | generate-containerfiles 2 | -------------------------------------------------------------------------------- /cmd/generate-containerfiles/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_library( 4 | name = "generate-containerfiles_lib", 5 | srcs = ["generate-containerfiles.go"], 6 | importpath = "github.com/randomizedcoder/go_nix_simple/cmd/generate-containerfiles", 7 | visibility = ["//visibility:private"], 8 | ) 9 | 10 | go_binary( 11 | name = "generate-containerfiles", 12 | embed = [":generate-containerfiles_lib"], 13 | visibility = ["//visibility:public"], 14 | ) 15 | -------------------------------------------------------------------------------- /cmd/generate-containerfiles/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # /cmd/generate-containerfiles/Makefile 3 | # 4 | 5 | # ldflags variables to update --version 6 | COMMIT := $(shell git describe --always) 7 | DATE := $(shell date -u +"%Y-%m-%d-%H:%M") 8 | VERSION := $(shell cat ../../VERSION) 9 | BINARY := generate-containerfiles 10 | 11 | # Define ldflags string once 12 | LDFLAGS_STR := "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${VERSION}" 13 | 14 | .PHONY: all clean build test 15 | 16 | all: build 17 | 18 | test: 19 | go test 20 | 21 | clean: 22 | rm -f ./${BINARY} 23 | 24 | build: 25 | go build -ldflags ${LDFLAGS_STR} -o ./${BINARY} ./${BINARY}.go 26 | 27 | # Optional: Clearer name if keeping the Athens build variant 28 | # build-athens: 29 | # GOPROXY=http://127.0.0.1:8888 \ 30 | # go build -ldflags ${LDFLAGS_STR} -o ./${BINARY} ./${BINARY}.go 31 | 32 | # end -------------------------------------------------------------------------------- /cmd/generate-containerfiles/generate-containerfiles.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "flag" // Import flag package 6 | "fmt" 7 | "log" 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | "text/template" 12 | ) 13 | 14 | // Variables set by ldflags 15 | var ( 16 | commit string 17 | date string 18 | version string 19 | ) 20 | 21 | type Config struct { 22 | BaseImage string 23 | CachingMode string 24 | UseUPX bool 25 | GoVersion string 26 | AthensProxyURL string 27 | HttpProxyURL string 28 | GoBuildCommand string 29 | // Add fields for ARGs if needed in template 30 | MYPATH string 31 | COMMIT string 32 | DATE string 33 | VERSION string 34 | // etc. 35 | } 36 | 37 | func main() { 38 | // --- Flags --- 39 | tmplPath := flag.String("template", "build/containers/go_nix_simple_refactor/Containerfile.tmpl", "Path to the Containerfile template") 40 | outputPath := flag.String("output", "build/containers/go_nix_simple_refactor", "Directory to save generated Containerfiles") 41 | 42 | athensURL := flag.String("athens-url", "http://localhost:8888", "Athens proxy URL") 43 | httpProxyURL := flag.String("http-proxy-url", "http://localhost:3128", "HTTP proxy URL") 44 | // athensURL := flag.String("athens-url", "http://hp4.home:8888", "Athens proxy URL") 45 | // httpProxyURL := flag.String("http-proxy-url", "http://hp4.home:3128", "HTTP proxy URL") 46 | 47 | goVersion := flag.String("go-version", "1.24.2", "Go version for builder image") 48 | // Add flags for MYPATH, COMMIT, DATE, VERSION if they need to be passed to the template 49 | // Example: 50 | // mypathArg := flag.String("mypath", ".", "Value for MYPATH ARG") 51 | 52 | flag.Parse() 53 | 54 | log.Printf("Generator version: %s, commit: %s, built: %s", version, commit, date) 55 | 56 | // --- Template Parsing --- 57 | tmpl, err := template.ParseFiles(*tmplPath) 58 | if err != nil { 59 | log.Fatalf("Error parsing template %s: %v", *tmplPath, err) 60 | } 61 | 62 | // --- Define Options for Combinations --- 63 | baseImages := []string{"gcr.io/distroless/static-debian12", "scratch"} 64 | cachingModes := []string{"docker", "athens", "http", "none"} 65 | useUPXOptions := []bool{false, true} 66 | 67 | var configs []Config 68 | for _, base := range baseImages { 69 | for _, cache := range cachingModes { 70 | for _, upx := range useUPXOptions { 71 | 72 | // --- Skip invalid or undesired combinations --- 73 | // // Example: UPX might not make sense with certain cache modes, 74 | // // or you might only want UPX for distroless. Adjust as needed. 75 | // if upx && base == "scratch" { 76 | // // Example: Let's say we only want UPX for distroless for now 77 | // // log.Printf("Skipping combination: Base=%s, Cache=%s, UPX=%t", base, cache, upx) 78 | // // continue 79 | // } 80 | // if cache != "default" && upx { 81 | // // Example: Let's say UPX only applies to the 'default' cache build for simplicity 82 | // // log.Printf("Skipping combination: Base=%s, Cache=%s, UPX=%t", base, cache, upx) 83 | // // continue 84 | // } 85 | // // Add any other skipping logic here if necessary 86 | 87 | // --- Create Config for this combination --- 88 | cfg := Config{ 89 | BaseImage: base, 90 | CachingMode: cache, 91 | UseUPX: upx, 92 | GoVersion: *goVersion, 93 | AthensProxyURL: *athensURL, // Set URLs regardless, template/build command logic uses them conditionally 94 | HttpProxyURL: *httpProxyURL, 95 | // Add ARGs if needed: VERSION: version, COMMIT: commit, DATE: date, MYPATH: *mypathArg ... 96 | } 97 | configs = append(configs, cfg) 98 | } 99 | } 100 | } 101 | log.Printf("Generated %d configuration combinations.", len(configs)) 102 | 103 | // --- Generation Loop --- 104 | for i := range configs { // Use index to modify cfg in place 105 | cfg := &configs[i] // Get pointer to modify original config 106 | 107 | // --- Determine Go Build Command --- 108 | var buildCmdBuilder strings.Builder 109 | buildCmdBuilder.WriteString("RUN ") // Start the RUN command 110 | switch cfg.CachingMode { 111 | case "docker": 112 | buildCmdBuilder.WriteString("--mount=type=cache,target=/go/pkg/mod \\\n --mount=type=cache,target=/root/.cache/go-build \\\n ") 113 | case "athens": 114 | buildCmdBuilder.WriteString(fmt.Sprintf("GOPROXY=%s,https://proxy.golang.org,direct \\\n ", cfg.AthensProxyURL)) 115 | case "http": 116 | buildCmdBuilder.WriteString(fmt.Sprintf("HTTP_PROXY=%s \\\n HTTPS_PROXY=%s \\\n ", cfg.HttpProxyURL, cfg.HttpProxyURL)) 117 | case "none": 118 | // No extra flags needed for the RUN line itself 119 | } 120 | // Append the common part of the go build command 121 | buildCmdBuilder.WriteString("CGO_ENABLED=0 go build \\\n") 122 | buildCmdBuilder.WriteString(" -trimpath \\\n") 123 | buildCmdBuilder.WriteString(" -tags=netgo,osusergo \\\n") 124 | buildCmdBuilder.WriteString(" -ldflags=\"-s -w\" \\\n") 125 | buildCmdBuilder.WriteString(" -o /go/bin/go_nix_simple \\\n") 126 | buildCmdBuilder.WriteString(" ./cmd/go_nix_simple/go_nix_simple.go") 127 | cfg.GoBuildCommand = buildCmdBuilder.String() 128 | // --- End Go Build Command Determination --- 129 | 130 | // --- Generate Filename --- 131 | // ***** ADD THESE LINES BACK ***** 132 | baseName := "distroless" 133 | if cfg.BaseImage == "scratch" { 134 | baseName = "scratch" 135 | } 136 | packerName := "noupx" 137 | if cfg.UseUPX { 138 | packerName = "upx" 139 | } 140 | // ******************************** 141 | filename := fmt.Sprintf("Containerfile.%s.%s.%s", baseName, cfg.CachingMode, packerName) 142 | fullPath := filepath.Join(*outputPath, filename) // Use flag value 143 | 144 | // --- Execute Template --- 145 | var buf bytes.Buffer 146 | err = tmpl.Execute(&buf, cfg) // Pass pointer to config 147 | if err != nil { 148 | log.Printf("Error executing template for %s: %v", filename, err) 149 | continue // Skip to next config on template error 150 | } 151 | 152 | // --- Write File --- 153 | err = os.WriteFile(fullPath, buf.Bytes(), 0644) 154 | if err != nil { 155 | log.Printf("Error writing file %s: %v", fullPath, err) 156 | continue // Skip to next config on write error 157 | } 158 | log.Printf("Generated: %s", fullPath) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /cmd/go_nix_simple/.gitignore: -------------------------------------------------------------------------------- 1 | go_nix_simple 2 | 3 | -------------------------------------------------------------------------------- /cmd/go_nix_simple/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@aspect_bazel_lib//lib:testing.bzl", "assert_archive_contains") 2 | load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup") 3 | 4 | # 5 | # cmd/go_nix_simple/BUILD.bazel 6 | # 7 | # I don't understand why this file doesn't look more like this one: 8 | # https://github.com/aspect-build/bazel-examples/blob/main/oci_go_image/BUILD.bazel 9 | # 10 | load("@rules_go//go:def.bzl", "go_binary", "go_library", "go_test") 11 | load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index", "oci_load", "oci_push") 12 | load("@rules_pkg//:pkg.bzl", "pkg_tar") 13 | #load("@rules_python//python:defs.bzl", "py_binary", "py_library") 14 | 15 | # Define the Go library 16 | go_library( 17 | name = "go_nix_simple_lib", 18 | srcs = ["go_nix_simple.go"], 19 | importpath = "github.com/randomizedcoder/go_nix_simple/cmd/go_nix_simple", 20 | visibility = ["//visibility:private"], 21 | deps = [ 22 | "@com_github_clickhouse_clickhouse_go_v2//:clickhouse-go", 23 | "@com_github_grafana_pyroscope_go//:pyroscope-go", 24 | "@com_github_nats_io_nats_go//:nats_go", 25 | "@com_github_pkg_profile//:profile", 26 | "@com_github_prometheus_client_golang//prometheus", 27 | "@com_github_prometheus_client_golang//prometheus/promauto", 28 | "@com_github_prometheus_client_golang//prometheus/promhttp", 29 | "@com_github_redis_go_redis_v9//:go-redis", 30 | ], 31 | cgo = True, 32 | ) 33 | 34 | # Tests!! 35 | # https://github.com/bazel-contrib/rules_go/blob/master/go/private/rules/test.bzl 36 | # Go race detector is linked against these LLVM precompiled binaries 37 | # https://github.com/golang/go/blob/master/src/runtime/race/README 38 | 39 | # Unit tests 40 | go_test( 41 | name = "go_nix_simple_test", 42 | size = "small", 43 | srcs = ["go_nix_simple_test.go"], 44 | embed = [":go_nix_simple_lib"], 45 | pure = "on", 46 | ) 47 | 48 | # Race detection test 49 | go_test( 50 | name = "go_nix_simple_race_test", 51 | size = "medium", 52 | srcs = ["go_nix_simple_test.go"], 53 | embed = [":go_nix_simple_lib"], 54 | pure = "off", 55 | race = "on", 56 | tags = ["requires-cgo"], 57 | ) 58 | 59 | # Fuzzing test for pyroscopeServer URL 60 | # https://go.dev/doc/security/fuzz/ 61 | go_test( 62 | name = "go_nix_simple_fuzz_test", 63 | size = "medium", 64 | srcs = ["go_nix_simple_fuzz_test.go"], 65 | embed = [":go_nix_simple_lib"], 66 | pure = "on", 67 | ) 68 | 69 | # Build binary 70 | go_binary( 71 | name = "go_nix_simple", 72 | embed = [":go_nix_simple_lib"], 73 | pure = "on", 74 | static = "on", 75 | visibility = ["//visibility:public"], 76 | ) 77 | 78 | # Package binary 79 | pkg_tar( 80 | name = "go_nix_simple_layer", 81 | srcs = [":go_nix_simple"], 82 | # If the binary depends on RUNFILES, uncomment the attribute below. 83 | # include_runfiles = True 84 | ) 85 | 86 | # Verify the tar contents 87 | assert_archive_contains( 88 | name = "test_go_nix_simple_layer", 89 | archive = "go_nix_simple_layer.tar", 90 | expected = ["go_nix_simple"], 91 | ) 92 | 93 | # Empty base layer 94 | pkg_tar( 95 | name = "empty_layer", 96 | srcs = [], 97 | ) 98 | 99 | # Empty base image 100 | oci_image( 101 | name = "empty_base", 102 | architecture = select({ 103 | ":platform_linux_amd64": "amd64", 104 | "//conditions:default": "amd64", 105 | }), 106 | os = "linux", 107 | tars = [":empty_layer"], 108 | ) 109 | 110 | config_setting( 111 | name = "platform_linux_arm64", 112 | constraint_values = [ 113 | "@platforms//os:linux", 114 | "@platforms//cpu:arm64", 115 | ], 116 | ) 117 | 118 | config_setting( 119 | name = "platform_linux_amd64", 120 | constraint_values = [ 121 | "@platforms//os:linux", 122 | "@platforms//cpu:x86_64", 123 | ], 124 | ) 125 | 126 | # Distroless image 127 | oci_image( 128 | name = "image_bazel_distroless", 129 | base = "@distroless_static", 130 | entrypoint = ["/go_nix_simple"], 131 | labels = { 132 | "org.opencontainers.image.source": "https://github.com/randomizedcoder/go_nix_simple", 133 | "org.opencontainers.image.description": "Go Nix Simple application", 134 | }, 135 | tars = [":go_nix_simple_layer"], 136 | user = "nonroot", 137 | ) 138 | 139 | # Platform transition for distroless image 140 | platform_transition_filegroup( 141 | name = "transitioned_distroless", 142 | srcs = [":image_bazel_distroless"], 143 | target_platform = select({ 144 | "@platforms//cpu:arm64": "@rules_go//go/toolchain:linux_arm64", 145 | "@platforms//cpu:x86_64": "@rules_go//go/toolchain:linux_amd64", 146 | }), 147 | ) 148 | 149 | oci_image_index( 150 | name = "image_bazel_distroless_index", 151 | images = [":transitioned_distroless"], 152 | ) 153 | 154 | # Scratch image 155 | oci_image( 156 | name = "image_bazel_scratch", 157 | base = ":empty_base", 158 | entrypoint = ["/go_nix_simple"], 159 | labels = { 160 | "org.opencontainers.image.source": "https://github.com/randomizedcoder/go_nix_simple", 161 | "org.opencontainers.image.description": "Go Nix Simple application (scratch)", 162 | }, 163 | tars = [":go_nix_simple_layer"], 164 | user = "nonroot", 165 | ) 166 | 167 | # Platform transition for scratch image 168 | platform_transition_filegroup( 169 | name = "transitioned_scratch", 170 | srcs = [":image_bazel_scratch"], 171 | target_platform = select({ 172 | "@platforms//cpu:arm64": "@rules_go//go/toolchain:linux_arm64", 173 | "@platforms//cpu:x86_64": "@rules_go//go/toolchain:linux_amd64", 174 | }), 175 | ) 176 | 177 | # Local testing targets 178 | oci_load( 179 | name = "load_distroless", 180 | image = ":transitioned_distroless", 181 | repo_tags = ["docker.io/randomizedcoder/go_nix_simple:local"], 182 | ) 183 | 184 | oci_load( 185 | name = "load_scratch", 186 | image = ":transitioned_scratch", 187 | repo_tags = ["docker.io/randomizedcoder/go_nix_simple:local-scratch"], 188 | ) 189 | 190 | # Distroless push target 191 | oci_push( 192 | name = "image_bazel_distroless_tarball", 193 | image = ":image_bazel_distroless_index", 194 | remote_tags = ["latest"], 195 | repository = "docker.io/randomizedcoder/go_nix_simple", 196 | ) 197 | 198 | # Scratch push target 199 | oci_push( 200 | name = "image_bazel_scratch_tarball", 201 | image = ":transitioned_scratch", 202 | remote_tags = ["latest"], 203 | repository = "docker.io/randomizedcoder/go_nix_simple", 204 | ) 205 | -------------------------------------------------------------------------------- /cmd/go_nix_simple/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # /cmd/go_nix_simple/Makefile 3 | # 4 | 5 | # ldflags variables to update --version 6 | # short commit hash 7 | COMMIT := $(shell git describe --always) 8 | DATE := $(shell date -u +"%Y-%m-%d-%H:%M") 9 | VERSION_FILE := $(shell cat ../../VERSION) 10 | LOCAL_MAJOR_VERSION := $(word 1,$(subst ., ,$(VERSION_FILE))) 11 | LOCAL_MINOR_VERSION := $(word 2,$(subst ., ,$(VERSION_FILE))) 12 | LOCAL_PATCH_VERSION := $(word 3,$(subst ., ,$(VERSION_FILE))) 13 | BINARY := go_nix_simple 14 | 15 | all: clean build 16 | 17 | test: 18 | go test 19 | 20 | clean: 21 | [ -f ${BINARY} ] && rm -rf ./${BINARY} || true 22 | 23 | build: 24 | go build -ldflags \ 25 | "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${LOCAL_MAJOR_VERSION}.${LOCAL_MINOR_VERSION}.${LOCAL_PATCH_VERSION}" \ 26 | -o ./${BINARY} \ 27 | ./${BINARY}.go 28 | 29 | builda: 30 | GOPROXY=http://127.0.0.1:8888 \ 31 | go build -ldflags \ 32 | "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${LOCAL_MAJOR_VERSION}.${LOCAL_MINOR_VERSION}.${LOCAL_PATCH_VERSION}" \ 33 | -o ./${BINARY} \ 34 | ./${BINARY}.go 35 | 36 | # end -------------------------------------------------------------------------------- /cmd/go_nix_simple/go_nix_simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "flag" 7 | "fmt" 8 | "log" 9 | "net/http" 10 | "os" 11 | "os/signal" 12 | "sync" 13 | "syscall" 14 | "time" 15 | 16 | // Ensure the ClickHouse driver is imported for side effects when enabled 17 | _ "github.com/ClickHouse/clickhouse-go/v2" 18 | 19 | pyroscope "github.com/grafana/pyroscope-go" 20 | "github.com/nats-io/nats.go" 21 | "github.com/pkg/profile" 22 | "github.com/prometheus/client_golang/prometheus" 23 | "github.com/prometheus/client_golang/prometheus/promauto" 24 | "github.com/prometheus/client_golang/prometheus/promhttp" 25 | "github.com/redis/go-redis/v9" 26 | ) 27 | 28 | const ( 29 | sleepTimeCst = 3 * time.Second 30 | 31 | debugLevelCst = 11 // Default debug level 32 | 33 | //promListenCst = ":9108" 34 | promPathCst = "/metrics" 35 | promMaxRequestsInFlight = 10 36 | promEnableOpenMetrics = true 37 | 38 | signalChannelSizeCst = 10 // Increased buffer size 39 | shutdownTimeoutCst = 5 * time.Second 40 | 41 | // Default connection strings 42 | defaultClickHouseDSN = "clickhouse://user:password@localhost:9000/default?dial_timeout=10s&compress=true" 43 | defaultNatsURL = nats.DefaultURL // "nats://127.0.0.1:4222" 44 | defaultRedisAddr = "localhost:6379" 45 | ) 46 | 47 | var ( 48 | // Passed by "go build -ldflags" for the show version 49 | commit string 50 | date string 51 | version string 52 | 53 | debugLevel uint 54 | 55 | chDB *sql.DB // ClickHouse DB handle 56 | natsC *nats.Conn // NATS connection 57 | redisC *redis.Client // Redis client 58 | 59 | pC = promauto.NewCounterVec( 60 | prometheus.CounterOpts{ 61 | Subsystem: "counters", 62 | Name: "main", 63 | Help: "main counters", 64 | }, 65 | []string{"function", "variable", "type"}, 66 | ) 67 | ) 68 | 69 | // handleVersionFlag checks if the version flag is set and returns true if the program should exit 70 | func handleVersionFlag() bool { 71 | v := flag.Bool("v", false, "show version") 72 | flag.Parse() 73 | 74 | if *v { 75 | // Use fmt.Printf for version output as it's informational, not an error/log event 76 | fmt.Printf("go_nix_simple commit:%s\tdate(UTC):%s\tversion:%s\n", commit, date, version) 77 | return true 78 | } 79 | return false 80 | } 81 | 82 | func main() { 83 | pyroscopeServer := flag.String("pyroscope.server", "", "Pyroscope server address (e.g., http://localhost:4040)") 84 | pyroscopeApp := flag.String("pyroscope.app", "go_nix_simple", "Application name for Pyroscope") 85 | 86 | clickhouseEnable := flag.Bool("clickhouse.enable", false, "Enable ClickHouse connection test") 87 | clickhouseDSN := flag.String("clickhouse.dsn", defaultClickHouseDSN, "ClickHouse DSN (Data Source Name)") 88 | 89 | natsEnable := flag.Bool("nats.enable", false, "Enable NATS connection test") 90 | natsURL := flag.String("nats.url", defaultNatsURL, "NATS server URL(s), comma-separated") 91 | 92 | redisEnable := flag.Bool("redis.enable", false, "Enable Redis connection test") 93 | redisAddr := flag.String("redis.addr", defaultRedisAddr, "Redis server address (host:port)") 94 | redisPassword := flag.String("redis.password", "", "Redis password (optional)") 95 | redisDB := flag.Int("redis.db", 0, "Redis database number") 96 | 97 | // ./gdp --profile.mode cpu 98 | // timeout 1h ./gdp --profile.mode cpu 99 | profileMode := flag.String("profile.mode", "", "enable profiling mode, one of [cpu, mem, memheap, mutex, block, trace, goroutine]") 100 | promPort := flag.Uint("prom.port", 9108, "Prometheus port") 101 | 102 | promListAddr := fmt.Sprintf(":%d", *promPort) 103 | 104 | d := flag.Uint("d", debugLevelCst, "debug level") 105 | 106 | if handleVersionFlag() { 107 | os.Exit(0) 108 | } 109 | 110 | debugLevel = *d 111 | log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.LUTC | log.Lshortfile | log.Lmsgprefix) 112 | log.SetPrefix("go_nix_simple: ") 113 | 114 | if debugLevel > 10 { 115 | log.Printf("Debug level set to: %d", debugLevel) 116 | } 117 | 118 | ctx, cancel := context.WithCancel(context.Background()) 119 | defer cancel() 120 | 121 | complete := make(chan struct{}) 122 | var sigHandlerWg sync.WaitGroup 123 | sigHandlerWg.Add(1) 124 | go initSignalHandler(cancel, complete, &sigHandlerWg) 125 | 126 | go initPromHandler(ctx, promPathCst, promListAddr) 127 | 128 | // "github.com/pkg/profile" 129 | // https://dave.cheney.net/2013/07/07/introducing-profile-super-simple-profiling-for-go-programs 130 | // e.g. ./gdp -profile.mode trace 131 | // go tool trace trace.out 132 | // e.g. ./gdp -profile.mode cpu 133 | // go tool pprof -http=":8081" gdp cpu.pprof 134 | if *profileMode != "" { 135 | log.Printf("Local profiling enabled: %s", *profileMode) 136 | switch *profileMode { 137 | case "cpu": 138 | defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop() 139 | case "mem": 140 | defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop() 141 | case "memheap": 142 | defer profile.Start(profile.MemProfileHeap, profile.ProfilePath(".")).Stop() 143 | case "mutex": 144 | defer profile.Start(profile.MutexProfile, profile.ProfilePath(".")).Stop() 145 | case "block": 146 | defer profile.Start(profile.BlockProfile, profile.ProfilePath(".")).Stop() 147 | case "trace": 148 | defer profile.Start(profile.TraceProfile, profile.ProfilePath(".")).Stop() 149 | case "goroutine": 150 | defer profile.Start(profile.GoroutineProfile, profile.ProfilePath(".")).Stop() 151 | default: 152 | log.Printf("Warning: Unknown profile mode '%s'. No local profiling started.", *profileMode) 153 | } 154 | } 155 | 156 | if *pyroscopeServer != "" { 157 | setupPyroscope(*pyroscopeServer, *pyroscopeApp) 158 | } 159 | 160 | var chErr error 161 | if *clickhouseEnable { 162 | chDB, chErr = setupClickHouse(ctx, *clickhouseDSN) 163 | if chErr != nil { 164 | log.Printf("ClickHouse setup failed: %v. Will not attempt interaction.", chErr) 165 | if chDB != nil { 166 | chDB.Close() 167 | chDB = nil 168 | } 169 | } 170 | } 171 | defer func() { 172 | if chDB != nil { 173 | log.Println("Closing ClickHouse connection...") 174 | if err := chDB.Close(); err != nil { 175 | log.Printf("Error closing ClickHouse connection: %v", err) 176 | } else { 177 | log.Println("ClickHouse connection closed.") 178 | } 179 | } 180 | }() 181 | 182 | var natsErr error 183 | if *natsEnable { 184 | natsC, natsErr = setupNATS(*natsURL) 185 | if natsErr != nil { 186 | log.Printf("NATS setup failed: %v. Will not attempt interaction.", natsErr) 187 | if natsC != nil { 188 | natsC.Close() 189 | natsC = nil 190 | } 191 | } 192 | } 193 | defer func() { 194 | if natsC != nil && natsC.IsConnected() { 195 | log.Println("Draining and closing NATS connection...") 196 | if err := natsC.Drain(); err != nil { 197 | log.Printf("Error draining NATS connection: %v", err) 198 | } 199 | natsC.Close() 200 | log.Println("NATS connection closed.") 201 | } else if natsC != nil { 202 | natsC.Close() 203 | log.Println("NATS connection closed (was not connected).") 204 | } 205 | }() 206 | 207 | var redisErr error 208 | if *redisEnable { 209 | redisC, redisErr = setupRedis(ctx, *redisAddr, *redisPassword, *redisDB) 210 | if redisErr != nil { 211 | log.Printf("Redis setup failed: %v. Will not attempt interaction.", redisErr) 212 | if redisC != nil { 213 | redisC.Close() 214 | redisC = nil 215 | } 216 | } 217 | } 218 | defer func() { 219 | if redisC != nil { 220 | log.Println("Closing Redis connection...") 221 | if err := redisC.Close(); err != nil { 222 | log.Printf("Error closing Redis connection: %v", err) 223 | } else { 224 | log.Println("Redis connection closed.") 225 | } 226 | } 227 | }() 228 | 229 | log.Println("Starting main application loop...") 230 | var wg sync.WaitGroup 231 | wg.Add(1) 232 | go loop(ctx, &wg) 233 | 234 | wg.Wait() 235 | log.Println("Main loop finished.") 236 | 237 | log.Println("Signaling shutdown completion to signal handler.") 238 | close(complete) 239 | 240 | log.Println("Waiting for signal handler to exit...") 241 | sigHandlerWg.Wait() 242 | 243 | log.Println("Exiting main.") 244 | } 245 | 246 | func setupPyroscope(server, appName string) { 247 | log.Printf("Pyroscope profiling enabled: server=%s app=%s", server, appName) 248 | _, err := pyroscope.Start(pyroscope.Config{ 249 | ApplicationName: appName, 250 | ServerAddress: server, 251 | Logger: pyroscope.StandardLogger, 252 | Tags: map[string]string{"commit": commit, "version": version}, 253 | ProfileTypes: []pyroscope.ProfileType{ 254 | pyroscope.ProfileCPU, 255 | pyroscope.ProfileAllocObjects, 256 | pyroscope.ProfileAllocSpace, 257 | pyroscope.ProfileInuseObjects, 258 | pyroscope.ProfileInuseSpace, 259 | }, 260 | }) 261 | if err != nil { 262 | log.Printf("Error starting Pyroscope: %v", err) 263 | } else { 264 | log.Println("Pyroscope profiler started.") 265 | } 266 | } 267 | 268 | func setupClickHouse(ctx context.Context, dsn string) (*sql.DB, error) { 269 | log.Printf("Attempting ClickHouse connection: dsn=%s", dsn) 270 | connectCtx, connectCancel := context.WithTimeout(ctx, 15*time.Second) 271 | defer connectCancel() 272 | 273 | db, err := sql.Open("clickhouse", dsn) 274 | if err != nil { 275 | return nil, fmt.Errorf("sql.Open failed: %w", err) 276 | } 277 | 278 | pingErr := db.PingContext(connectCtx) 279 | if pingErr != nil { 280 | db.Close() 281 | return nil, fmt.Errorf("failed to ping ClickHouse: %w", pingErr) 282 | } 283 | 284 | log.Println("ClickHouse connection successful.") 285 | // Optional: Configure connection pool settings 286 | // db.SetMaxOpenConns(10) 287 | // db.SetMaxIdleConns(5) 288 | // db.SetConnMaxLifetime(time.Hour) 289 | return db, nil 290 | } 291 | 292 | func setupNATS(url string) (*nats.Conn, error) { 293 | log.Printf("Attempting NATS connection: url=%s", url) 294 | nc, err := nats.Connect(url, 295 | nats.Timeout(10*time.Second), 296 | nats.Name("go_nix_simple"), 297 | nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 298 | log.Printf("NATS async error: %v", err) 299 | }), 300 | nats.DisconnectErrHandler(func(nc *nats.Conn, err error) { 301 | log.Printf("NATS disconnected: %v. Will attempt reconnect.", err) 302 | }), 303 | nats.ReconnectHandler(func(nc *nats.Conn) { 304 | log.Printf("NATS reconnected to %s", nc.ConnectedUrl()) 305 | }), 306 | ) 307 | if err != nil { 308 | return nil, fmt.Errorf("nats.Connect failed: %w", err) 309 | } 310 | log.Printf("NATS connection successful to: %s", nc.ConnectedUrl()) 311 | return nc, nil 312 | } 313 | 314 | func setupRedis(ctx context.Context, addr, password string, db int) (*redis.Client, error) { 315 | log.Printf("Attempting Redis connection: addr=%s db=%d", addr, db) 316 | rdb := redis.NewClient(&redis.Options{ 317 | Addr: addr, 318 | Password: password, 319 | DB: db, 320 | }) 321 | 322 | pingCtx, pingCancel := context.WithTimeout(ctx, 10*time.Second) 323 | defer pingCancel() 324 | 325 | _, err := rdb.Ping(pingCtx).Result() 326 | if err != nil { 327 | rdb.Close() 328 | return nil, fmt.Errorf("redis Ping failed: %w", err) 329 | } 330 | 331 | log.Println("Redis connection successful.") 332 | return rdb, nil 333 | } 334 | 335 | func loop(ctx context.Context, wg *sync.WaitGroup) { 336 | defer wg.Done() 337 | log.Println("Loop: starting.") 338 | 339 | ticker := time.NewTicker(sleepTimeCst) 340 | defer ticker.Stop() 341 | 342 | hostname, _ := os.Hostname() 343 | if hostname == "" { 344 | hostname = "unknown" 345 | } 346 | 347 | for i := 0; ; i++ { 348 | select { 349 | case <-ctx.Done(): 350 | log.Printf("Loop: context cancelled (err: %v), exiting.", ctx.Err()) 351 | return 352 | 353 | case tickTime := <-ticker.C: 354 | log.Printf("Loop: Tick %d at %v", i, tickTime.Format(time.RFC3339)) 355 | fmt.Printf("Hello %d from %s\n", i, hostname) 356 | pC.WithLabelValues("loop", "tick", "count").Inc() 357 | 358 | if chDB != nil { 359 | queryCtx, queryCancel := context.WithTimeout(ctx, 5*time.Second) 360 | var number uint64 361 | err := chDB.QueryRowContext(queryCtx, "SELECT 1").Scan(&number) 362 | queryCancel() 363 | if err != nil { 364 | log.Printf("Loop: Error querying ClickHouse: %v", err) 365 | pC.WithLabelValues("loop", "clickhouse_query", "error").Inc() 366 | } else { 367 | pC.WithLabelValues("loop", "clickhouse_query", "success").Inc() 368 | } 369 | } 370 | 371 | if natsC != nil && natsC.IsConnected() { 372 | subject := fmt.Sprintf("go_nix_simple.hello.%s", hostname) 373 | payload := fmt.Sprintf("Hello %d from %s at %s", i, hostname, tickTime.Format(time.RFC3339Nano)) 374 | err := natsC.Publish(subject, []byte(payload)) 375 | if err != nil { 376 | log.Printf("Loop: Error publishing to NATS: %v", err) 377 | pC.WithLabelValues("loop", "nats_publish", "error").Inc() 378 | } else { 379 | pC.WithLabelValues("loop", "nats_publish", "success").Inc() 380 | } 381 | } 382 | 383 | if redisC != nil { 384 | setCtx, setCancel := context.WithTimeout(ctx, 2*time.Second) 385 | key := fmt.Sprintf("go_nix_simple:last_hello:%s", hostname) 386 | val := fmt.Sprintf("%d", i) 387 | err := redisC.Set(setCtx, key, val, sleepTimeCst*2).Err() 388 | setCancel() 389 | if err != nil { 390 | log.Printf("Loop: Error setting Redis key '%s': %v", key, err) 391 | pC.WithLabelValues("loop", "redis_set", "error").Inc() 392 | } else { 393 | pC.WithLabelValues("loop", "redis_set", "success").Inc() 394 | } 395 | } 396 | } 397 | } 398 | } 399 | 400 | func initPromHandler(ctx context.Context, promPath string, promListen string) { 401 | log.Printf("Prometheus: Registering handler on path %s", promPath) 402 | mux := http.NewServeMux() 403 | promHandler := promhttp.HandlerFor( 404 | prometheus.DefaultGatherer, 405 | promhttp.HandlerOpts{ 406 | EnableOpenMetrics: promEnableOpenMetrics, 407 | MaxRequestsInFlight: promMaxRequestsInFlight, 408 | }, 409 | ) 410 | mux.Handle(promPath, promHandler) 411 | 412 | server := &http.Server{ 413 | Addr: promListen, 414 | Handler: mux, 415 | } 416 | 417 | log.Printf("Prometheus: Starting listener on %s", promListen) 418 | go func() { 419 | if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { 420 | log.Printf("Prometheus: Listener error: %v", err) 421 | } else { 422 | log.Println("Prometheus: Listener stopped.") 423 | } 424 | }() 425 | 426 | go func() { 427 | <-ctx.Done() 428 | log.Println("Prometheus: Shutdown signal received, shutting down listener...") 429 | shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 430 | defer cancel() 431 | 432 | if err := server.Shutdown(shutdownCtx); err != nil { 433 | log.Printf("Prometheus: Graceful shutdown error: %v", err) 434 | } else { 435 | log.Println("Prometheus: Listener shut down gracefully.") 436 | } 437 | }() 438 | } 439 | 440 | func initSignalHandler(cancel context.CancelFunc, complete <-chan struct{}, wg *sync.WaitGroup) { 441 | defer wg.Done() 442 | 443 | c := make(chan os.Signal, signalChannelSizeCst) 444 | signal.Notify(c, os.Interrupt, syscall.SIGTERM) 445 | log.Println("Signal: Handler started, waiting for SIGINT or SIGTERM.") 446 | 447 | sig := <-c 448 | log.Printf("Signal: Caught signal '%v', initiating shutdown.", sig) 449 | 450 | log.Println("Signal: Calling cancel() on main context.") 451 | cancel() 452 | 453 | log.Printf("Signal: Waiting up to %s for graceful shutdown completion...", shutdownTimeoutCst) 454 | timer := time.NewTimer(shutdownTimeoutCst) 455 | defer timer.Stop() 456 | 457 | select { 458 | case <-complete: 459 | log.Println("Signal: Shutdown completed gracefully. Exiting process with status 0.") 460 | os.Exit(0) 461 | 462 | case <-timer.C: 463 | log.Printf("Signal: Shutdown timeout (%s) reached. Forcing exit with status 1.", shutdownTimeoutCst) 464 | os.Exit(1) 465 | } 466 | } 467 | -------------------------------------------------------------------------------- /cmd/go_nix_simple/go_nix_simple_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestVersionFlag(t *testing.T) { 10 | // Save original args and restore them after the test 11 | oldArgs := os.Args 12 | defer func() { os.Args = oldArgs }() 13 | 14 | // Set test args 15 | os.Args = []string{"go_nix_simple", "-v"} 16 | 17 | // Reset flag state 18 | flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 19 | 20 | // Set version info for testing 21 | commit = "test-commit" 22 | date = "2024-01-01" 23 | version = "1.0.0" 24 | 25 | // Test version flag handling 26 | if !handleVersionFlag() { 27 | t.Error("handleVersionFlag should return true when -v flag is set") 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cmd/validate-image/.gitignore: -------------------------------------------------------------------------------- 1 | validate-image 2 | -------------------------------------------------------------------------------- /cmd/validate-image/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library") 2 | 3 | go_library( 4 | name = "validate-image_lib", 5 | srcs = ["validate-image.go"], 6 | importpath = "github.com/randomizedcoder/go_nix_simple/cmd/validate-image", 7 | visibility = ["//visibility:private"], 8 | deps = [ 9 | "@com_github_docker_docker//api/types/container", 10 | "@com_github_docker_docker//api/types/image", 11 | "@com_github_docker_docker//client", 12 | "@com_github_docker_go_connections//nat", 13 | "@com_github_prometheus_common//expfmt", 14 | "@com_github_prometheus_common//model", 15 | ], 16 | ) 17 | 18 | go_binary( 19 | name = "validate-image", 20 | embed = [":validate-image_lib"], 21 | visibility = ["//visibility:public"], 22 | ) 23 | -------------------------------------------------------------------------------- /cmd/validate-image/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # /cmd/validate-image/Makefile 3 | # 4 | 5 | # ldflags variables to update --version 6 | # short commit hash 7 | COMMIT := $(shell git describe --always) 8 | DATE := $(shell date -u +"%Y-%m-%d-%H:%M") 9 | VERSION_FILE := $(shell cat ../../VERSION) 10 | LOCAL_MAJOR_VERSION := $(word 1,$(subst ., ,$(VERSION_FILE))) 11 | LOCAL_MINOR_VERSION := $(word 2,$(subst ., ,$(VERSION_FILE))) 12 | LOCAL_PATCH_VERSION := $(word 3,$(subst ., ,$(VERSION_FILE))) 13 | BINARY := validate-image 14 | 15 | all: clean build 16 | 17 | test: 18 | go test 19 | 20 | clean: 21 | [ -f ${BINARY} ] && rm -rf ./${BINARY} || true 22 | 23 | build: 24 | go build -ldflags \ 25 | "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${LOCAL_MAJOR_VERSION}.${LOCAL_MINOR_VERSION}.${LOCAL_PATCH_VERSION}" \ 26 | -o ./${BINARY} \ 27 | ./${BINARY}.go 28 | 29 | builda: 30 | GOPROXY=http://127.0.0.1:8888 \ 31 | go build -ldflags \ 32 | "-X main.commit=${COMMIT} -X main.date=${DATE} -X main.version=${LOCAL_MAJOR_VERSION}.${LOCAL_MINOR_VERSION}.${LOCAL_PATCH_VERSION}" \ 33 | -o ./${BINARY} \ 34 | ./${BINARY}.go 35 | 36 | # end -------------------------------------------------------------------------------- /cmd/validate-image/validate-image: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomizedcoder/go_nix_simple/54afea8567c4bfe23ea3780d20e16c99fff59a92/cmd/validate-image/validate-image -------------------------------------------------------------------------------- /cmd/validate-image/validate-image.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "context" 6 | "errors" 7 | "flag" 8 | "fmt" 9 | "io" 10 | "log" 11 | "net/http" 12 | "os" 13 | "strconv" 14 | "strings" 15 | "sync" 16 | "time" 17 | 18 | "github.com/docker/docker/api/types/container" 19 | "github.com/docker/docker/api/types/image" 20 | "github.com/docker/docker/client" 21 | "github.com/docker/go-connections/nat" 22 | 23 | "github.com/prometheus/common/expfmt" 24 | "github.com/prometheus/common/model" 25 | ) 26 | 27 | // https://pkg.go.dev/github.com/docker/docker/api 28 | // https://pkg.go.dev/github.com/prometheus/common/expfmt 29 | 30 | const ( 31 | defaultTimeout = 30 * time.Second 32 | defaultLogTarget = "Hello 2 from" 33 | defaultMetricTarget = `counters_main{function="loop",type="count",variable="tick"}` 34 | defaultMetricThreshold = 2.0 35 | defaultParallelism = 1 36 | 37 | defaultVersion = "1.0.0" 38 | defaultRepoPrefix = "randomizedcoder" 39 | 40 | nixImagePrefix = "nix-go-nix-simple" 41 | dockerImagePrefix = "docker-go-nix-simple" 42 | ) 43 | 44 | type ValidationResult struct { 45 | ImageTag string 46 | LogCheck CheckResult 47 | MetricCheck CheckResult 48 | OverallError error 49 | Duration time.Duration 50 | LogBuffer strings.Builder 51 | } 52 | 53 | type CheckResult struct { 54 | Success bool 55 | Error error 56 | } 57 | 58 | func (vr ValidationResult) OverallSuccess() bool { 59 | return vr.LogCheck.Success && vr.MetricCheck.Success && vr.OverallError == nil 60 | } 61 | 62 | var ( 63 | mainLogger = log.New(os.Stdout, "", log.LstdFlags|log.Lmicroseconds|log.LUTC) 64 | 65 | nixBases = []string{"distroless", "scratch"} 66 | nixBuilders = []string{"buildgomodule", "gomod2nix"} 67 | nixPackers = []string{"noupx", "upx"} 68 | 69 | dockerBases = []string{"distroless", "scratch"} 70 | dockerCaches = []string{"docker", "athens", "http", "none"} 71 | dockerPackers = []string{"noupx", "upx"} 72 | ) 73 | 74 | func main() { 75 | 76 | log.SetOutput(io.Discard) 77 | 78 | imageTagsRaw := flag.String("images", "all", "Comma-separated list of Docker image tags to validate (required)") 79 | parallelism := flag.Int("parallel", defaultParallelism, "Number of concurrent validation tests to run") 80 | timeout := flag.Duration("timeout", defaultTimeout, "Timeout for each individual image validation") 81 | logTarget := flag.String("log-target", defaultLogTarget, "Log line prefix to wait for") 82 | metricTarget := flag.String("metric-target", defaultMetricTarget, "Prometheus metric name (with labels) to check") 83 | metricThreshold := flag.Float64("metric-threshold", defaultMetricThreshold, "Minimum value for the target metric") 84 | version := flag.String("version", defaultVersion, "Version tag for images (used with -images=all)") 85 | repoPrefix := flag.String("repo-prefix", defaultRepoPrefix, "Repository prefix (e.g., dockerhub username) for images (used with -images=all)") 86 | 87 | flag.Parse() 88 | 89 | var imageTags []string 90 | 91 | if *imageTagsRaw == "" { 92 | log.Fatal("Error: -images flag is required (provide comma-separated list or 'all')") 93 | } else if strings.ToLower(*imageTagsRaw) == "all" { 94 | log.Printf("Generating all known image tags for version %s with prefix %s...", *version, *repoPrefix) 95 | imageTags = generateAllImageTags(*repoPrefix, *version) 96 | if len(imageTags) == 0 { 97 | log.Fatal("Error: Failed to generate any image tags for 'all'") 98 | } 99 | log.Printf("Generated %d image tags.", len(imageTags)) 100 | } else { 101 | 102 | tagsFromFlag := strings.Split(*imageTagsRaw, ",") 103 | 104 | for _, tag := range tagsFromFlag { 105 | trimmedTag := strings.TrimSpace(tag) 106 | if trimmedTag != "" { 107 | imageTags = append(imageTags, trimmedTag) 108 | } 109 | } 110 | if len(imageTags) == 0 { 111 | log.Fatal("Error: No valid image tags provided in the list") 112 | } 113 | } 114 | 115 | mainLogger.Printf("Starting validation for %d image(s) with parallelism %d and timeout %v", len(imageTags), *parallelism, *timeout) 116 | 117 | ctx := context.Background() 118 | validationStartTime := time.Now() 119 | 120 | // --- Setup Worker Pool --- 121 | jobs := make(chan string, len(imageTags)) 122 | results := make(chan ValidationResult, len(imageTags)) 123 | var wg sync.WaitGroup 124 | 125 | numWorkers := *parallelism 126 | if numWorkers <= 0 { 127 | numWorkers = 1 128 | } 129 | if numWorkers > len(imageTags) { 130 | numWorkers = len(imageTags) 131 | } 132 | 133 | log.Printf("Starting %d worker(s)", numWorkers) 134 | for w := 1; w <= numWorkers; w++ { 135 | wg.Add(1) 136 | go worker(ctx, w, jobs, results, &wg, *timeout, *logTarget, *metricTarget, *metricThreshold, mainLogger) 137 | } 138 | 139 | // --- Send Jobs --- 140 | for _, tag := range imageTags { 141 | trimmedTag := strings.TrimSpace(tag) 142 | if trimmedTag != "" { 143 | jobs <- trimmedTag 144 | } 145 | } 146 | close(jobs) 147 | 148 | // --- Wait for Workers and Collect Results --- 149 | wg.Wait() 150 | close(results) 151 | totalValidationDuration := time.Since(validationStartTime) // Calculate total duration 152 | 153 | // --- Store results for summary --- 154 | var processedResults []ValidationResult 155 | allSuccessOverall := true 156 | 157 | for res := range results { 158 | processedResults = append(processedResults, res) 159 | if !res.OverallSuccess() { 160 | allSuccessOverall = false 161 | } 162 | } 163 | 164 | // --- Report Results --- 165 | mainLogger.Println("--- Validation Summary ---") 166 | 167 | // Sort results alphabetically (optional) 168 | // sort.Slice(processedResults, func(i, j int) bool { 169 | // return processedResults[i].ImageTag < processedResults[j].ImageTag 170 | // }) 171 | 172 | // --- Print Table Header --- 173 | // Adjust column widths as needed 174 | mainLogger.Printf("%-80s %-8s %-8s %-18s %s", "Image Tag", "Log", "Metric", "Duration", "Overall Error") 175 | mainLogger.Println(strings.Repeat("-", 120)) // Separator line 176 | 177 | totalChecks := 0 178 | passedChecks := 0 179 | var failedLogsOutput strings.Builder 180 | 181 | // --- Print Table Rows --- 182 | for _, res := range processedResults { 183 | totalChecks += 2 // Log + Metric 184 | 185 | logStatus := "FAIL" 186 | if res.LogCheck.Success { 187 | logStatus = "PASS" 188 | passedChecks++ 189 | } 190 | 191 | metricStatus := "FAIL" 192 | if res.MetricCheck.Success { 193 | metricStatus = "PASS" 194 | passedChecks++ 195 | } 196 | 197 | overallErrorStr := "" 198 | if res.OverallError != nil { 199 | overallErrorStr = res.OverallError.Error() 200 | // Optionally truncate long errors 201 | // if len(overallErrorStr) > 50 { 202 | // overallErrorStr = overallErrorStr[:47] + "..." 203 | // } 204 | } 205 | 206 | // Print formatted row 207 | mainLogger.Printf("%-80s %-8s %-8s %-18s %s", 208 | res.ImageTag, 209 | logStatus, 210 | metricStatus, 211 | res.Duration.Round(time.Millisecond).String(), // Format duration 212 | overallErrorStr, 213 | ) 214 | 215 | // Store logs if this image failed overall 216 | if !res.OverallSuccess() { 217 | failedLogsOutput.WriteString(fmt.Sprintf("\n--- Logs for FAILED image: %s ---\n", res.ImageTag)) 218 | failedLogsOutput.WriteString(res.LogBuffer.String()) 219 | failedLogsOutput.WriteString("--- End Logs ---\n") 220 | } 221 | } 222 | 223 | // --- Print Footer --- 224 | mainLogger.Println(strings.Repeat("-", 120)) // Separator line 225 | failedChecks := totalChecks - passedChecks 226 | mainLogger.Printf("Total Images: %d | Total Checks: %d | Passed Checks: %d | Failed Checks: %d", 227 | len(processedResults), totalChecks, passedChecks, failedChecks) 228 | mainLogger.Printf("Total Validation Duration: %v", totalValidationDuration.Round(time.Second)) // Print total duration 229 | mainLogger.Println("--------------------------") 230 | 231 | // Print logs for failed tests if any occurred 232 | if failedLogsOutput.Len() > 0 { 233 | mainLogger.Printf("\n--- Details for Failed Validations ---") 234 | os.Stdout.WriteString(failedLogsOutput.String()) 235 | } 236 | 237 | // Exit based on overall success 238 | if !allSuccessOverall { 239 | mainLogger.Println("\nOne or more image validations failed.") 240 | os.Exit(1) 241 | } 242 | mainLogger.Println("\nAll image validations passed.") 243 | } 244 | 245 | func generateAllImageTags(repoPrefix, version string) []string { 246 | var allTags []string 247 | 248 | for _, base := range nixBases { 249 | for _, builder := range nixBuilders { 250 | for _, packer := range nixPackers { 251 | tag := fmt.Sprintf("%s/%s-%s-%s-%s:%s", 252 | repoPrefix, nixImagePrefix, base, builder, packer, version) 253 | allTags = append(allTags, tag) 254 | } 255 | } 256 | } 257 | 258 | for _, base := range dockerBases { 259 | for _, cache := range dockerCaches { 260 | for _, packer := range dockerPackers { 261 | // // --- Apply filtering logic --- 262 | // if cache != "docker" && packer == "upx" { 263 | // log.Printf("Skipping Docker tag generation for: base=%s, cache=%s, packer=%s (UPX only with 'docker' cache)", base, cache, packer) 264 | // continue 265 | // } 266 | 267 | tag := fmt.Sprintf("%s/%s-%s-%s-%s:%s", 268 | repoPrefix, dockerImagePrefix, base, cache, packer, version) 269 | allTags = append(allTags, tag) 270 | } 271 | } 272 | } 273 | 274 | return allTags 275 | } 276 | 277 | // worker executes validation jobs received from the jobs channel. 278 | func worker(ctxIn context.Context, 279 | id int, jobs <-chan string, 280 | results chan<- ValidationResult, 281 | wg *sync.WaitGroup, 282 | timeout time.Duration, 283 | logTarget, metricTarget string, 284 | metricThreshold float64, 285 | workerLogger *log.Logger) { 286 | 287 | defer wg.Done() 288 | 289 | workerLogger.Printf("Worker %d started", id) 290 | 291 | for imageTag := range jobs { 292 | 293 | log.Printf("Worker %d: Validating image %s", id, imageTag) 294 | startTime := time.Now() 295 | 296 | ctx, cancel := context.WithTimeout(ctxIn, timeout) 297 | 298 | var logBuf strings.Builder 299 | jobLogger := log.New(io.MultiWriter(&logBuf, io.Discard), fmt.Sprintf("W%d [%s]: ", id, imageTag[:min(15, len(imageTag))]), log.Ltime|log.Lmicroseconds) 300 | 301 | res := validateImage(ctx, imageTag, logTarget, metricTarget, metricThreshold, jobLogger, &logBuf) 302 | res.Duration = time.Since(startTime) 303 | res.LogBuffer = logBuf 304 | 305 | cancel() 306 | 307 | results <- res 308 | 309 | workerLogger.Printf("Worker %d: Finished validating %s (Overall Success: %t, Duration: %v)", id, imageTag, res.OverallSuccess(), res.Duration) 310 | } 311 | workerLogger.Printf("Worker %d finished", id) 312 | } 313 | 314 | // validateImage performs the actual validation steps for a single image. 315 | func validateImage( 316 | ctx context.Context, 317 | imageTag, logTarget, metricTarget string, 318 | metricThreshold float64, 319 | jobLogger *log.Logger, 320 | logBuf *strings.Builder) ValidationResult { 321 | 322 | // Initialize result struct 323 | result := ValidationResult{ 324 | ImageTag: imageTag, 325 | // Checks default to failure until proven successful 326 | LogCheck: CheckResult{Success: false}, 327 | MetricCheck: CheckResult{Success: false}, 328 | } 329 | 330 | // --- 1. Create Docker Client --- 331 | cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) 332 | if err != nil { 333 | result.OverallError = fmt.Errorf("failed to create docker client: %w", err) 334 | jobLogger.Printf("ERROR: %v", result.OverallError) 335 | return result 336 | } 337 | defer cli.Close() 338 | 339 | // --- 2. Pull Image --- 340 | jobLogger.Printf("Pulling image (best effort)...") 341 | pullCtx, pullCancel := context.WithTimeout(ctx, 2*time.Minute) 342 | pullReader, err := cli.ImagePull(pullCtx, imageTag, image.PullOptions{}) 343 | if err == nil { 344 | _, copyErr := io.Copy(logBuf, pullReader) 345 | pullReader.Close() 346 | if copyErr != nil { 347 | jobLogger.Printf("Warning: Error reading image pull output: %v", copyErr) 348 | } 349 | } 350 | pullCancel() 351 | if err != nil { 352 | jobLogger.Printf("Warning: Failed to pull image (will try to run anyway): %v", err) 353 | } 354 | 355 | // --- 3. Create and Start Container --- 356 | containerPortStr := "9108/tcp" 357 | //hostPortStr := "9108" 358 | exposedPortsSet := nat.PortSet{nat.Port(containerPortStr): {}} 359 | portBindingsMap := nat.PortMap{ 360 | nat.Port(containerPortStr): []nat.PortBinding{ 361 | { 362 | HostIP: "0.0.0.0", 363 | HostPort: "", 364 | }, 365 | }, 366 | } 367 | 368 | resp, err := cli.ContainerCreate( 369 | ctx, 370 | &container.Config{ 371 | Image: imageTag, 372 | ExposedPorts: exposedPortsSet, 373 | }, 374 | &container.HostConfig{ 375 | PortBindings: portBindingsMap, 376 | AutoRemove: true, 377 | }, nil, nil, "") 378 | if err != nil { 379 | result.OverallError = fmt.Errorf("failed to create container: %w", err) 380 | return result // Return early 381 | } 382 | containerID := resp.ID 383 | log.Printf("Created container %s", containerID[:12]) 384 | 385 | defer func() { 386 | log.Printf("Stopping container %s...", containerID[:12]) 387 | stopCtx, stopCancel := context.WithTimeout(context.Background(), 10*time.Second) 388 | defer stopCancel() 389 | if err := cli.ContainerStop(stopCtx, containerID, container.StopOptions{}); err != nil { 390 | log.Printf("Warning: Failed to stop container %s: %v", containerID[:12], err) 391 | } else { 392 | log.Printf("Stopped container %s", containerID[:12]) 393 | } 394 | }() 395 | 396 | if err := cli.ContainerStart(ctx, containerID, container.StartOptions{}); err != nil { 397 | result.OverallError = fmt.Errorf("failed to start container: %w", err) 398 | return result 399 | } 400 | log.Printf("Started container %s", containerID[:12]) 401 | 402 | // --- 3.5 Inspect Container to Get Assigned Port --- 403 | var assignedHostPort string // Variable to store the dynamic port 404 | inspectResp, err := cli.ContainerInspect(ctx, containerID) 405 | if err != nil { 406 | result.OverallError = fmt.Errorf("failed to inspect container %s: %w", containerID[:12], err) 407 | return result 408 | } 409 | 410 | // Find the port mapping 411 | if portMap, ok := inspectResp.NetworkSettings.Ports[nat.Port(containerPortStr)]; ok && len(portMap) > 0 { 412 | assignedHostPort = portMap[0].HostPort // Get the first assigned host port 413 | log.Printf("Container %s assigned host port %s for container port %s", containerID[:12], assignedHostPort, containerPortStr) 414 | } else { 415 | result.OverallError = fmt.Errorf("could not find assigned host port for %s in container %s", containerPortStr, containerID[:12]) 416 | return result 417 | } 418 | if assignedHostPort == "" { 419 | result.OverallError = fmt.Errorf("assigned host port for %s is empty in container %s", containerPortStr, containerID[:12]) 420 | return result 421 | } 422 | 423 | // --- 4. Check Logs --- 424 | logCheckCtx, logCheckCancel := context.WithCancel(ctx) 425 | defer logCheckCancel() 426 | logFoundChan := make(chan error, 1) 427 | go func() { 428 | defer func() { jobLogger.Printf("Log check routine finished.") }() 429 | logReader, err := cli.ContainerLogs(logCheckCtx, containerID, container.LogsOptions{ShowStdout: true, ShowStderr: true, Follow: true, Timestamps: false}) 430 | if err != nil { 431 | jobLogger.Printf("Error getting container logs: %v", err) 432 | logFoundChan <- err 433 | return 434 | } 435 | defer logReader.Close() 436 | 437 | logTee := io.TeeReader(logReader, logBuf) 438 | scanner := bufio.NewScanner(logTee) 439 | jobLogger.Printf("Watching logs for '%s'...", logTarget) 440 | for scanner.Scan() { 441 | line := scanner.Text() 442 | 443 | if strings.Contains(line, logTarget) { 444 | jobLogger.Printf("Found target log line: %s", line) 445 | logFoundChan <- nil 446 | return 447 | } 448 | } 449 | scanErr := scanner.Err() 450 | if scanErr != nil && !errors.Is(scanErr, context.Canceled) { 451 | jobLogger.Printf("Error reading container logs: %v", scanErr) 452 | logFoundChan <- scanErr 453 | } else { 454 | logFoundChan <- fmt.Errorf("target log line not found before log stream ended") 455 | } 456 | }() 457 | 458 | select { 459 | case logErr := <-logFoundChan: 460 | if logErr == nil { 461 | result.LogCheck.Success = true 462 | jobLogger.Printf("Log check successful.") 463 | } else { 464 | result.LogCheck.Error = logErr 465 | jobLogger.Printf("Log check failed: %v", logErr) 466 | } 467 | case <-ctx.Done(): 468 | result.LogCheck.Error = fmt.Errorf("timeout waiting for log line '%s': %w", logTarget, ctx.Err()) 469 | jobLogger.Printf("Log check failed: %v", result.LogCheck.Error) 470 | // default: // non-blocking 471 | } 472 | 473 | if !result.LogCheck.Success { 474 | jobLogger.Printf("Skipping metric check because log check failed.") 475 | return result 476 | } 477 | 478 | // --- 5. Check Metrics --- 479 | time.Sleep(1 * time.Second) 480 | metricURL := fmt.Sprintf("http://localhost:%s/metrics", assignedHostPort) 481 | jobLogger.Printf("Checking metrics at %s for '%s' >= %.1f", metricURL, metricTarget, metricThreshold) 482 | 483 | req, err := http.NewRequestWithContext(ctx, "GET", metricURL, nil) 484 | if err != nil { 485 | result.MetricCheck.Error = fmt.Errorf("failed to create metrics request: %w", err) 486 | jobLogger.Printf("Metric check failed: %v", result.MetricCheck.Error) 487 | return result 488 | } 489 | respHttp, err := http.DefaultClient.Do(req) 490 | if err != nil { 491 | result.MetricCheck.Error = fmt.Errorf("failed to get metrics: %w", err) 492 | jobLogger.Printf("Metric check failed: %v", result.MetricCheck.Error) 493 | return result 494 | } 495 | defer respHttp.Body.Close() 496 | if respHttp.StatusCode != http.StatusOK { 497 | result.MetricCheck.Error = fmt.Errorf("metrics endpoint returned status %d", respHttp.StatusCode) 498 | jobLogger.Printf("Metric check failed: %v", result.MetricCheck.Error) 499 | return result 500 | } 501 | var parser expfmt.TextParser 502 | metricFamilies, err := parser.TextToMetricFamilies(respHttp.Body) 503 | if err != nil { 504 | result.MetricCheck.Error = fmt.Errorf("failed to parse metrics: %w", err) 505 | jobLogger.Printf("Metric check failed: %v", result.MetricCheck.Error) 506 | return result 507 | } 508 | 509 | // ... (metric finding logic remains the same) ... 510 | metricName := metricTarget 511 | labels := model.LabelSet{} 512 | if idx := strings.Index(metricTarget, "{"); idx != -1 && strings.HasSuffix(metricTarget, "}") { 513 | metricName = metricTarget[:idx] 514 | labelStr := metricTarget[idx+1 : len(metricTarget)-1] 515 | pairs := strings.Split(labelStr, ",") 516 | for _, pair := range pairs { 517 | parts := strings.SplitN(pair, "=", 2) 518 | if len(parts) == 2 { 519 | key := strings.TrimSpace(parts[0]) 520 | val, err := strconv.Unquote(strings.TrimSpace(parts[1])) 521 | if err != nil { 522 | result.MetricCheck.Error = fmt.Errorf("failed to parse label value in '%s': %w", pair, err) 523 | return result 524 | } 525 | labels[model.LabelName(key)] = model.LabelValue(val) 526 | } 527 | } 528 | } 529 | mf, found := metricFamilies[metricName] 530 | if !found { 531 | result.MetricCheck.Error = fmt.Errorf("metric '%s' not found", metricName) 532 | return result 533 | } 534 | var metricValue float64 = -1 535 | for _, m := range mf.GetMetric() { 536 | match := true 537 | if len(labels) != len(m.GetLabel()) { 538 | match = false 539 | } else { 540 | for ln, lv := range labels { 541 | foundLabel := false 542 | for _, lp := range m.GetLabel() { 543 | if lp.GetName() == string(ln) && lp.GetValue() == string(lv) { 544 | foundLabel = true 545 | break 546 | } 547 | } 548 | if !foundLabel { 549 | match = false 550 | break 551 | } 552 | } 553 | } 554 | if match { 555 | if m.GetCounter() != nil { 556 | metricValue = m.GetCounter().GetValue() 557 | } else if m.GetGauge() != nil { 558 | metricValue = m.GetGauge().GetValue() 559 | } 560 | break 561 | } 562 | } 563 | if metricValue < 0 { 564 | result.MetricCheck.Error = fmt.Errorf("metric '%s' with specified labels not found", metricTarget) 565 | return result 566 | } 567 | if metricValue < metricThreshold { 568 | result.MetricCheck.Error = fmt.Errorf("metric '%s' value %.1f is below threshold %.1f", metricTarget, metricValue, metricThreshold) 569 | return result 570 | } 571 | 572 | // If we reach here, metric check passed 573 | result.MetricCheck.Success = true 574 | log.Printf("Metric check successful ('%s' value %.1f >= %.1f).", metricTarget, metricValue, metricThreshold) 575 | 576 | // --- 6. Return Detailed Result --- 577 | return result 578 | } 579 | 580 | func min(a, b int) int { 581 | if a < b { 582 | return a 583 | } 584 | return b 585 | } 586 | -------------------------------------------------------------------------------- /deps.bzl: -------------------------------------------------------------------------------- 1 | load("@bazel_gazelle//:deps.bzl", "go_repository") 2 | 3 | def go_dependencies(): 4 | """A function that declares the external Go dependencies.""" 5 | pass -------------------------------------------------------------------------------- /docs/example/BUILD.bazel.example: -------------------------------------------------------------------------------- 1 | load("@aspect_bazel_lib//lib:testing.bzl", "assert_archive_contains") 2 | load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup") 3 | load("@container_structure_test//:defs.bzl", "container_structure_test") 4 | load("@rules_go//go:def.bzl", "go_binary", "go_library", "go_test") 5 | load("@rules_oci//oci:defs.bzl", "oci_image", "oci_load", "oci_push") 6 | load("@rules_pkg//:pkg.bzl", "pkg_tar") 7 | 8 | go_library( 9 | name = "app_lib", 10 | srcs = ["main.go"], 11 | importpath = "github.com/aspect-build/bazel-examples/oci_go_image", 12 | visibility = ["//visibility:private"], 13 | deps = ["@com_github_google_go_cmp//cmp"], 14 | ) 15 | 16 | go_test( 17 | name = "app_test", 18 | size = "small", 19 | srcs = ["main_test.go"], 20 | embed = [":app_lib"], 21 | ) 22 | 23 | go_binary( 24 | name = "app", 25 | embed = [":app_lib"], 26 | visibility = ["//visibility:public"], 27 | ) 28 | 29 | # Put app go_binary into a tar layer. 30 | pkg_tar( 31 | name = "app_layer", 32 | srcs = [":app"], 33 | # If the binary depends on RUNFILES, uncomment the attribute below. 34 | # include_runfiles = True 35 | ) 36 | 37 | # Prove that the application is at the path we expect in that tar. 38 | assert_archive_contains( 39 | name = "test_app_layer", 40 | archive = "app_layer.tar", 41 | expected = ["app"], 42 | ) 43 | 44 | oci_image( 45 | name = "image", 46 | # This is defined by an oci.pull() call in /MODULE.bazel 47 | base = "@distroless_base", 48 | entrypoint = ["/app"], 49 | # Link the resulting image back to the repository where the build is defined. 50 | labels = { 51 | "org.opencontainers.image.source": "https://github.com/aspect-build/bazel-examples", 52 | }, 53 | tars = [":app_layer"], 54 | ) 55 | 56 | # This is the target that should be released to the target platform 57 | platform_transition_filegroup( 58 | name = "transitioned_image", 59 | srcs = [":image"], 60 | target_platform = select({ 61 | "@platforms//cpu:arm64": "@rules_go//go/toolchain:linux_arm64", 62 | "@platforms//cpu:x86_64": "@rules_go//go/toolchain:linux_amd64", 63 | }), 64 | ) 65 | 66 | # $ bazel run //oci_go_image:load 67 | # $ docker run --rm gcr.io/example:latest 68 | # string( 69 | # - "Hello World", 70 | # + "Hello Go", 71 | # ) 72 | oci_load( 73 | name = "load", 74 | # Use the image built for the target platform 75 | image = ":transitioned_image", 76 | repo_tags = ["gcr.io/example:latest"], 77 | ) 78 | 79 | container_structure_test( 80 | name = "test", 81 | configs = ["test.yaml"], 82 | # Use the image built for the target platform as it runs through docker 83 | image = ":transitioned_image", 84 | tags = [ 85 | "no-remote-exec", 86 | "requires-docker", 87 | ], 88 | ) 89 | 90 | oci_push( 91 | name = "push", 92 | image = ":transitioned_image", 93 | remote_tags = ["latest"], 94 | repository = "ghcr.io/aspect-build/oci_go_image_example", 95 | ) -------------------------------------------------------------------------------- /docs/example/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/aspect-build/bazel-examples/blob/main/oci_go_image/BUILD.bazel 2 | -------------------------------------------------------------------------------- /docs/images/Screenshot From 2025-04-15 10-23-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomizedcoder/go_nix_simple/54afea8567c4bfe23ea3780d20e16c99fff59a92/docs/images/Screenshot From 2025-04-15 10-23-13.png -------------------------------------------------------------------------------- /docs/images/Screenshot From 2025-04-15 10-27-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomizedcoder/go_nix_simple/54afea8567c4bfe23ea3780d20e16c99fff59a92/docs/images/Screenshot From 2025-04-15 10-27-00.png -------------------------------------------------------------------------------- /docs/images/Screenshot From 2025-04-15 10-27-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomizedcoder/go_nix_simple/54afea8567c4bfe23ea3780d20e16c99fff59a92/docs/images/Screenshot From 2025-04-15 10-27-36.png -------------------------------------------------------------------------------- /docs/images/Screenshot From 2025-04-15 10-27-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randomizedcoder/go_nix_simple/54afea8567c4bfe23ea3780d20e16c99fff59a92/docs/images/Screenshot From 2025-04-15 10-27-44.png -------------------------------------------------------------------------------- /docs/nix_on_ubuntu.md: -------------------------------------------------------------------------------- 1 | # Instructions for installing Nix on Ubuntu 2 | 3 | Taken from: 4 | https://nixos.wiki/wiki/Nix_Installation_Guide#Stable_Nix 5 | 6 | 7 | ## Install Nix 8 | 9 | ``` 10 | sudo install -d -m755 -o $(id -u) -g $(id -g) /nix 11 | curl -L https://nixos.org/nix/install | sh 12 | . /home/das/.nix-profile/etc/profile.d/nix.sh <--- change username 13 | nix --extra-experimental-features nix-command --extra-experimental-features flakes run "nixpkgs#hello" 14 | ``` 15 | 16 | ``` 17 | das@chromebox2:~$ sudo install -d -m755 -o $(id -u) -g $(id -g) /nix 18 | das@chromebox2:~$ curl -L https://nixos.org/nix/install | sh 19 | % Total % Received % Xferd Average Speed Time Time Time Current 20 | Dload Upload Total Spent Left Speed 21 | 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 22 | 100 4267 100 4267 0 0 4717 0 --:--:-- --:--:-- --:--:-- 4717 23 | downloading Nix 2.28.3 binary tarball for x86_64-linux from 'https://releases.nixos.org/nix/nix-2.28.3/nix-2.28.3-x86_64-linux.tar.xz' to '/tmp/nix-binary-tarball-unpack.G46iRyEPM2'... 24 | % Total % Received % Xferd Average Speed Time Time Time Current 25 | Dload Upload Total Spent Left Speed 26 | 100 22.9M 100 22.9M 0 0 38.1M 0 --:--:-- --:--:-- --:--:-- 38.1M 27 | Note: a multi-user installation is possible. See https://nixos.org/manual/nix/stable/installation/installing-binary.html#multi-user-installation 28 | performing a single-user installation of Nix... 29 | copying Nix to /nix/store... 30 | 31 | installing 'nix-2.28.3' 32 | building '/nix/store/j8pmzgxnl2zhq2j1fc3j73qrv2i7k48g-user-environment.drv'... 33 | warning: error: unable to download 'https://releases.nixos.org/nixpkgs/nixpkgs-25.05pre792485.3afd19146cac/nixexprs.tar.xz': HTTP error 200 (curl error: Failure when receiving data from the peer); retrying in 309 ms 34 | unpacking 1 channels... 35 | modifying /home/das/.profile... 36 | 37 | Installation finished! To ensure that the necessary environment 38 | variables are set, either log in again, or type 39 | 40 | . /home/das/.nix-profile/etc/profile.d/nix.sh 41 | 42 | in your shell. 43 | das@chromebox2:~$ . /home/das/.nix-profile/etc/profile.d/nix.sh 44 | das@chromebox2:~$ 45 | ``` 46 | 47 | ## Test Nix is working 48 | 49 | das@chromebox2:~$ nix --extra-experimental-features nix-command --extra-experimental-features flakes run "nixpkgs#hello" 50 | Hello, world! 51 | 52 | ## Configure Nix 53 | 54 | ``` 55 | mkdir -p ~/.config/nix 56 | echo "experimental-features = nix-command flakes" > ~/.config/nix/nix.conf 57 | ``` 58 | 59 | ``` 60 | das@chromebox2:~$ mkdir -p ~/.config/nix 61 | das@chromebox2:~$ echo "experimental-features = nix-command flakes" > ~/.config/nix/nix.conf 62 | das@chromebox2:~$ cat ~/.config/nix/nix.conf 63 | experimental-features = nix-command flakes 64 | ``` 65 | 66 | ## clone repo 67 | 68 | ``` 69 | git clone https://github.com/randomizedcoder/go_nix_simple 70 | cd go_nix_simple 71 | ``` 72 | 73 | ``` 74 | das@chromebox2:~$ git clone https://github.com/randomizedcoder/go_nix_simple 75 | Cloning into 'go_nix_simple'... 76 | remote: Enumerating objects: 415, done. 77 | remote: Counting objects: 100% (415/415), done. 78 | remote: Compressing objects: 100% (242/242), done. 79 | remote: Total 415 (delta 228), reused 315 (delta 141), pack-reused 0 (from 0) 80 | Receiving objects: 100% (415/415), 33.36 MiB | 16.16 MiB/s, done. 81 | Resolving deltas: 100% (228/228), done. 82 | das@chromebox2:~$ cd go_nix_simple/ 83 | das@chromebox2:~/go_nix_simple$ 84 | ``` 85 | 86 | ## nix develop 87 | 88 | Enter the development shell. 89 | 90 | This will create the new development shell and enter it. This will be slow the first time, because it is using the unstable branch (which is pinned into the flake.lock file). 91 | 92 | ``` 93 | nix develop 94 | ``` 95 | 96 | 97 | ``` 98 | das@chromebox2:~/go_nix_simple$ nix develop 99 | Entered Nix development shell for go-nix-simple. 100 | (nix-dev) ~/go_nix_simple$ 101 | ``` 102 | 103 | If ~/.config/nix/nix.conf was not updated: 104 | ``` 105 | das@chromebox2:~/go_nix_simple$ nix --extra-experimental-features nix-command --extra-experimental-features flakes develop 106 | warning: download buffer is full; consider increasing the 'download-buffer-size' setting 107 | Entered Nix development shell for go-nix-simple. 108 | (nix-dev) ~/go_nix_simple$ 109 | ``` 110 | 111 | ## Build the oci containers using bazel 112 | 113 | This will use bazel to build the go_nix_simple go binary into a container based on scratch and distroless. 114 | 115 | ``` 116 | make bazel-build-all 117 | ``` 118 | 119 | ``` 120 | (nix-dev) ~/go_nix_simple$ make bazel-build-all 121 | for platform in //platforms:linux_amd64; do \ 122 | bazel build --platforms=$platform \ 123 | //cmd/go_nix_simple:image_bazel_distroless_tarball \ 124 | --define REPO_PREFIX=docker.io/randomizedcoder \ 125 | --define VERSION=latest; \ 126 | done 127 | Extracting Bazel installation... 128 | Starting local Bazel server and connecting to it... 129 | WARNING: /home/das/go_nix_simple/MODULE.bazel:48:20: The module extension oci defined in @rules_oci//oci:extensions.bzl reported incorrect imports of repositories via use_repo(): 130 | 131 | Not imported, but reported as direct dependencies by the extension (may cause the build to fail): 132 | distroless_base_amd64_linux_amd64 133 | 134 | Fix the use_repo calls by running 'bazel mod tidy'. 135 | INFO: Analyzed target //cmd/go_nix_simple:image_bazel_distroless_tarball (257 packages loaded, 15482 targets configured). 136 | INFO: Found 1 target... 137 | Target //cmd/go_nix_simple:image_bazel_distroless_tarball up-to-date: 138 | bazel-bin/cmd/go_nix_simple/push_image_bazel_distroless_tarball.sh 139 | INFO: Elapsed time: 409.948s, Critical Path: 211.10s 140 | INFO: 159 processes: 21 internal, 1 local, 137 processwrapper-sandbox. 141 | INFO: Build completed successfully, 159 total actions 142 | for platform in //platforms:linux_amd64; do \ 143 | bazel build --platforms=$platform \ 144 | //cmd/go_nix_simple:image_bazel_scratch_tarball \ 145 | --define REPO_PREFIX=docker.io/randomizedcoder \ 146 | --define VERSION=latest; \ 147 | done 148 | INFO: Analyzed target //cmd/go_nix_simple:image_bazel_scratch_tarball (0 packages loaded, 7 targets configured). 149 | INFO: Found 1 target... 150 | Target //cmd/go_nix_simple:image_bazel_scratch_tarball up-to-date: 151 | bazel-bin/cmd/go_nix_simple/push_image_bazel_scratch_tarball.sh 152 | INFO: Elapsed time: 4.111s, Critical Path: 2.63s 153 | INFO: 15 processes: 10 internal, 5 processwrapper-sandbox. 154 | INFO: Build completed successfully, 15 total actions 155 | (nix-dev) ~/go_nix_simple$ 156 | ``` -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "gomod2nix": { 22 | "inputs": { 23 | "flake-utils": [ 24 | "flake-utils" 25 | ], 26 | "nixpkgs": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1745875161, 32 | "narHash": "sha256-0YkWCS13jpoo3+sX/3kcgdxBNt1VZTmvF+FhZb4rFKI=", 33 | "owner": "tweag", 34 | "repo": "gomod2nix", 35 | "rev": "2cbd7fdd6eeab65c494cc426e18f4e4d2a5e35c0", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "tweag", 40 | "repo": "gomod2nix", 41 | "type": "github" 42 | } 43 | }, 44 | "nixpkgs": { 45 | "locked": { 46 | "lastModified": 1746141548, 47 | "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=", 48 | "owner": "NixOS", 49 | "repo": "nixpkgs", 50 | "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78", 51 | "type": "github" 52 | }, 53 | "original": { 54 | "owner": "NixOS", 55 | "ref": "nixos-unstable", 56 | "repo": "nixpkgs", 57 | "type": "github" 58 | } 59 | }, 60 | "root": { 61 | "inputs": { 62 | "flake-utils": "flake-utils", 63 | "gomod2nix": "gomod2nix", 64 | "nixpkgs": "nixpkgs" 65 | } 66 | }, 67 | "systems": { 68 | "locked": { 69 | "lastModified": 1681028828, 70 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 71 | "owner": "nix-systems", 72 | "repo": "default", 73 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 74 | "type": "github" 75 | }, 76 | "original": { 77 | "owner": "nix-systems", 78 | "repo": "default", 79 | "type": "github" 80 | } 81 | } 82 | }, 83 | "root": "root", 84 | "version": 7 85 | } 86 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | # 2 | # https://github.com/randomizedcoder/go_nix_simple 3 | # 4 | # flake.nix 5 | # 6 | { 7 | description = "A simple Go application packaged with Nix and Docker"; 8 | 9 | inputs = { 10 | #nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; 11 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 12 | flake-utils.url = "github:numtide/flake-utils"; 13 | 14 | gomod2nix = { 15 | url = "github:tweag/gomod2nix"; 16 | inputs.nixpkgs.follows = "nixpkgs"; 17 | inputs.flake-utils.follows = "flake-utils"; 18 | }; 19 | 20 | }; 21 | 22 | outputs = { self, nixpkgs, flake-utils, gomod2nix }: 23 | flake-utils.lib.eachDefaultSystem (system: 24 | let 25 | pkgs = import nixpkgs { 26 | inherit system; 27 | overlays = [ gomod2nix.overlays.default ]; 28 | config = { 29 | allowUnfree = true; 30 | }; 31 | }; 32 | 33 | appVersion = builtins.readFile ./VERSION; 34 | 35 | # Common ldflags for Go builds 36 | commonLdflags = [ "-s" "-w" "-X main.version=${appVersion}" "-X main.commit=nix-build" "-X main.date=unknown" ]; 37 | # Common buildFlags for Go builds 38 | commonBuildFlags = [ "-tags=netgo,osusergo" "-trimpath" ]; 39 | 40 | # --- Base Binary Derivations --- 41 | 42 | # Binary built using Nixpkgs buildGoModule 43 | binaryNixBuildGoModule = pkgs.buildGoModule { # Renamed from binaryNixDefault 44 | pname = "go-nix-simple-buildgomodule"; # Adjusted pname 45 | version = appVersion; 46 | src = ./.; 47 | subPackages = [ "cmd/go_nix_simple" ]; 48 | # Ensure this hash is updated when go.mod/go.sum changes 49 | # Run: nix build .#binary-nix-buildgomodule --rebuild 50 | #vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; 51 | vendorHash = "sha256-iMUa+OE/Ecb3TDw4PmvRfujo++T/r4g/pW0ZT63zIC4="; 52 | ldflags = commonLdflags; 53 | buildFlags = commonBuildFlags; 54 | env = { CGO_ENABLED = 0; }; 55 | # postInstall = '' 56 | # mv $out/bin/go-nix-simple-buildgomodule $out/bin/go_nix_simple 57 | # ''; 58 | }; 59 | 60 | # Binary built using gomod2nix buildGoApplication 61 | binaryNixGomod2nix = pkgs.buildGoApplication { 62 | pname = "go-nix-simple-gomod2nix"; 63 | version = appVersion; 64 | modules = ./gomod2nix.toml; 65 | src = ./.; 66 | ldflags = commonLdflags; 67 | buildFlags = commonBuildFlags; 68 | #env = { CGO_ENABLED = 0; }; 69 | CGO_ENABLED = 0; 70 | # postInstall = '' 71 | # mv $out/bin/go-nix-simple-gomod2nix $out/bin/go_nix_simple 72 | # ''; 73 | }; 74 | 75 | # --- UPX Packed Binary Derivations --- 76 | 77 | # UPX version of the buildGoModule binary 78 | binaryNixBuildGoModuleUpx = pkgs.runCommand "go-nix-simple-buildgomodule-upx" { # Renamed 79 | nativeBuildInputs = [ pkgs.upx ]; 80 | src = binaryNixBuildGoModule; # Depend on the renamed binary derivation 81 | } '' 82 | mkdir -p $out/bin 83 | local orig_bin="$src/bin/go_nix_simple" 84 | echo "Original size ($(basename $orig_bin)): $(ls -lh $orig_bin | awk '{print $5}')" 85 | upx --best --lzma -o $out/bin/go_nix_simple "$orig_bin" 86 | echo "Compressed size ($(basename $out/bin/go_nix_simple)): $(ls -lh $out/bin/go_nix_simple | awk '{print $5}')" 87 | chmod +x $out/bin/go_nix_simple 88 | ''; 89 | 90 | # UPX version of the gomod2nix binary 91 | binaryNixGomod2nixUpx = pkgs.runCommand "go-nix-simple-gomod2nix-upx" { 92 | nativeBuildInputs = [ pkgs.upx ]; 93 | src = binaryNixGomod2nix; 94 | } '' 95 | mkdir -p $out/bin 96 | local orig_bin="$src/bin/go_nix_simple" # Assumes postInstall worked 97 | echo "Original size ($(basename $orig_bin)): $(ls -lh $orig_bin | awk '{print $5}')" 98 | upx --best --lzma -o $out/bin/go_nix_simple "$orig_bin" 99 | echo "Compressed size ($(basename $out/bin/go_nix_simple)): $(ls -lh $out/bin/go_nix_simple | awk '{print $5}')" 100 | chmod +x $out/bin/go_nix_simple 101 | ''; 102 | 103 | 104 | # --- Common Image Components --- 105 | 106 | etcFiles = pkgs.runCommand "etc-files" {} '' 107 | mkdir -p $out/etc 108 | echo 'nogroup:x:65534:' > $out/etc/group 109 | echo 'nobody:x:65534:65534:Nobody:/:/sbin/nologin' > $out/etc/passwd 110 | ''; 111 | 112 | versionFilePkg = pkgs.runCommand "version-file" {} '' 113 | mkdir -p $out 114 | cp ${./VERSION} $out/VERSION 115 | ''; 116 | 117 | distrolessBase = pkgs.dockerTools.pullImage { 118 | imageName = "gcr.io/distroless/static-debian12"; 119 | imageDigest = "sha256:3d0f463de06b7ddff27684ec3bfd0b54a425149d0f8685308b1fdf297b0265e9"; 120 | sha256 = "0ajgz5slpdv42xqrildx850vp4cy6x44yj0hfz53raz3r971ikcf"; 121 | finalImageTag = "latest"; 122 | }; 123 | 124 | # Helper function to build layered images 125 | buildImage = { name, tag ? "latest", baseImage ? null, binaryPkg, extraContents ? [] }: 126 | pkgs.dockerTools.buildLayeredImage { 127 | inherit name tag; 128 | fromImage = baseImage; 129 | contents = [ binaryPkg versionFilePkg etcFiles ] ++ extraContents; 130 | config = { 131 | User = "nobody"; 132 | WorkingDir = "/"; 133 | ExposedPorts = { "9108/tcp" = {}; }; 134 | Cmd = [ "${binaryPkg}/bin/go_nix_simple" ]; 135 | }; 136 | }; 137 | 138 | # --- Image Derivations (All Combinations) --- 139 | 140 | # Distroless + BuildGoModule + NoUPX 141 | imageNixDistrolessBuildGoModuleNoupx = buildImage { # Renamed 142 | name = "randomizedcoder/nix-go-nix-simple-distroless-buildgomodule-noupx"; # Renamed 143 | baseImage = distrolessBase; 144 | binaryPkg = binaryNixBuildGoModule; # Use renamed binary 145 | }; 146 | 147 | # Distroless + BuildGoModule + UPX 148 | imageNixDistrolessBuildGoModuleUpx = buildImage { # Renamed 149 | name = "randomizedcoder/nix-go-nix-simple-distroless-buildgomodule-upx"; # Renamed 150 | baseImage = distrolessBase; 151 | binaryPkg = binaryNixBuildGoModuleUpx; # Use renamed binary 152 | }; 153 | 154 | # Distroless + Gomod2nix + NoUPX 155 | imageNixDistrolessGomod2nixNoupx = buildImage { 156 | name = "randomizedcoder/nix-go-nix-simple-distroless-gomod2nix-noupx"; 157 | baseImage = distrolessBase; 158 | binaryPkg = binaryNixGomod2nix; 159 | }; 160 | 161 | # Distroless + Gomod2nix + UPX 162 | imageNixDistrolessGomod2nixUpx = buildImage { 163 | name = "randomizedcoder/nix-go-nix-simple-distroless-gomod2nix-upx"; 164 | baseImage = distrolessBase; 165 | binaryPkg = binaryNixGomod2nixUpx; 166 | }; 167 | 168 | # Scratch + BuildGoModule + NoUPX 169 | imageNixScratchBuildGoModuleNoupx = buildImage { # Renamed 170 | name = "randomizedcoder/nix-go-nix-simple-scratch-buildgomodule-noupx"; # Renamed 171 | binaryPkg = binaryNixBuildGoModule; # Use renamed binary 172 | }; 173 | 174 | # Scratch + BuildGoModule + UPX 175 | imageNixScratchBuildGoModuleUpx = buildImage { # Renamed 176 | name = "randomizedcoder/nix-go-nix-simple-scratch-buildgomodule-upx"; # Renamed 177 | binaryPkg = binaryNixBuildGoModuleUpx; # Use renamed binary 178 | }; 179 | 180 | # Scratch + Gomod2nix + NoUPX 181 | imageNixScratchGomod2nixNoupx = buildImage { 182 | name = "randomizedcoder/nix-go-nix-simple-scratch-gomod2nix-noupx"; 183 | binaryPkg = binaryNixGomod2nix; 184 | }; 185 | 186 | # Scratch + Gomod2nix + UPX 187 | imageNixScratchGomod2nixUpx = buildImage { 188 | name = "randomizedcoder/nix-go-nix-simple-scratch-gomod2nix-upx"; 189 | binaryPkg = binaryNixGomod2nixUpx; 190 | }; 191 | 192 | # --- Utility Images (Example: Athens) --- 193 | athensNixImage = pkgs.dockerTools.buildLayeredImage { 194 | name = "randomizedcoder/athens-nix"; 195 | tag = "latest"; 196 | fromImage = distrolessBase; 197 | contents = [ pkgs.athens etcFiles ]; 198 | config = { 199 | User = "nobody"; 200 | WorkingDir = "/data"; 201 | ExposedPorts = { "8888/tcp" = {}; }; 202 | Volumes = { "/data/athens" = {}; }; 203 | Env = [ 204 | "ATHENS_HOST=0.0.0.0" 205 | "ATHENS_PORT=8888" 206 | "ATHENS_STORAGE_TYPE=disk" 207 | "ATHENS_DISK_STORAGE_ROOT=/data/athens" 208 | "ATHENS_LOG_LEVEL=info" 209 | ]; 210 | Cmd = [ "${pkgs.athens}/bin/athens" ]; 211 | }; 212 | }; 213 | 214 | in 215 | { 216 | # --- Consistent Package Naming --- 217 | packages = { 218 | # Binaries 219 | binary-nix-buildgomodule = binaryNixBuildGoModule; # Renamed key 220 | binary-nix-buildgomodule-upx = binaryNixBuildGoModuleUpx; # Renamed key 221 | binary-nix-gomod2nix = binaryNixGomod2nix; 222 | binary-nix-gomod2nix-upx = binaryNixGomod2nixUpx; 223 | 224 | # Images (All 8 combinations) 225 | image-nix-distroless-buildgomodule-noupx = imageNixDistrolessBuildGoModuleNoupx; # Renamed key 226 | image-nix-distroless-buildgomodule-upx = imageNixDistrolessBuildGoModuleUpx; # Renamed key 227 | image-nix-distroless-gomod2nix-noupx = imageNixDistrolessGomod2nixNoupx; 228 | image-nix-distroless-gomod2nix-upx = imageNixDistrolessGomod2nixUpx; 229 | image-nix-scratch-buildgomodule-noupx = imageNixScratchBuildGoModuleNoupx; # Renamed key 230 | image-nix-scratch-buildgomodule-upx = imageNixScratchBuildGoModuleUpx; # Renamed key 231 | image-nix-scratch-gomod2nix-noupx = imageNixScratchGomod2nixNoupx; 232 | image-nix-scratch-gomod2nix-upx = imageNixScratchGomod2nixUpx; 233 | 234 | # Utility Images 235 | athens-nix-image = athensNixImage; 236 | 237 | # Default package for `nix build` 238 | default = self.packages.${system}.image-nix-distroless-buildgomodule-noupx; # Updated default 239 | }; 240 | 241 | # --- Apps --- 242 | apps = { 243 | # Default app for `nix run` 244 | default = flake-utils.lib.mkApp { 245 | drv = self.packages.${system}.binary-nix-buildgomodule; 246 | # Explicitly tell mkApp where the executable is 247 | exePath = "/bin/go_nix_simple"; 248 | }; 249 | gomod2nix = flake-utils.lib.mkApp { 250 | drv = self.packages.${system}.binary-nix-gomod2nix; 251 | # Also specify exePath here for consistency, since postInstall renames it 252 | exePath = "/bin/go_nix_simple"; 253 | }; 254 | 255 | # Apps to output image tarballs (useful for loading into Docker) 256 | # Update keys to match package names 257 | image-distroless-buildgomodule-noupx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-distroless-buildgomodule-noupx; }; 258 | image-distroless-buildgomodule-upx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-distroless-buildgomodule-upx; }; 259 | image-distroless-gomod2nix-noupx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-distroless-gomod2nix-noupx; }; 260 | image-distroless-gomod2nix-upx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-distroless-gomod2nix-upx; }; 261 | image-scratch-buildgomodule-noupx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-scratch-buildgomodule-noupx; }; 262 | image-scratch-buildgomodule-upx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-scratch-buildgomodule-upx; }; 263 | image-scratch-gomod2nix-noupx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-scratch-gomod2nix-noupx; }; 264 | image-scratch-gomod2nix-upx-tarball = flake-utils.lib.mkApp { drv = self.packages.${system}.image-nix-scratch-gomod2nix-upx; }; 265 | }; 266 | 267 | # --- Dev Shell --- 268 | devShells.default = pkgs.mkShell { 269 | buildInputs = with pkgs; [ 270 | go 271 | gopls 272 | gotools 273 | golint 274 | golangci-lint 275 | go-tools 276 | golangci-lint-langserver 277 | gomod2nix.packages.${system}.default 278 | #gomod2nix 279 | upx 280 | # https://github.com/bazelbuild/bazel/tags 281 | # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/development/tools/build-managers/bazel/bazel_7/default.nix#L524 282 | bazel_7 283 | # https://github.com/bazel-contrib/bazel-gazelle/tags 284 | # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/by-name/ba/bazel-gazelle/package.nix#L26 285 | bazel-gazelle 286 | bazel-buildtools 287 | bazelisk 288 | # 289 | curl 290 | jq 291 | # 292 | dive 293 | # 294 | code-cursor 295 | ]; 296 | shellHook = '' 297 | export PS1='(nix-dev) \w\$ ' 298 | echo "Entered Nix development shell for go-nix-simple." 299 | ''; 300 | 301 | # You might have other shell attributes here 302 | # Example: GOPATH = "${pkgs.buildGoModule}/share/go"; 303 | }; 304 | }); 305 | } 306 | # end 307 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/randomizedcoder/go_nix_simple 2 | 3 | go 1.24.1 4 | 5 | require ( 6 | github.com/ClickHouse/clickhouse-go/v2 v2.34.0 7 | github.com/docker/docker v28.0.4+incompatible 8 | github.com/docker/go-connections v0.5.0 9 | github.com/grafana/pyroscope-go v1.2.2 10 | github.com/nats-io/nats.go v1.41.2 11 | github.com/pkg/profile v1.7.0 12 | github.com/prometheus/client_golang v1.22.0 13 | github.com/prometheus/common v0.62.0 14 | github.com/redis/go-redis/v9 v9.7.3 15 | ) 16 | 17 | require ( 18 | github.com/ClickHouse/ch-go v0.65.1 // indirect 19 | github.com/Microsoft/go-winio v0.6.2 // indirect 20 | github.com/andybalholm/brotli v1.1.1 // indirect 21 | github.com/beorn7/perks v1.0.1 // indirect 22 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 23 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 24 | github.com/distribution/reference v0.6.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/felixge/fgprof v0.9.3 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-faster/city v1.0.1 // indirect 29 | github.com/go-faster/errors v0.7.1 // indirect 30 | github.com/go-logr/logr v1.4.2 // indirect 31 | github.com/go-logr/stdr v1.2.2 // indirect 32 | github.com/gogo/protobuf v1.3.2 // indirect 33 | github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect 34 | github.com/google/uuid v1.6.0 // indirect 35 | github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect 36 | github.com/klauspost/compress v1.18.0 // indirect 37 | github.com/moby/docker-image-spec v1.3.1 // indirect 38 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 39 | github.com/nats-io/nkeys v0.4.11 // indirect 40 | github.com/nats-io/nuid v1.0.1 // indirect 41 | github.com/opencontainers/go-digest v1.0.0 // indirect 42 | github.com/opencontainers/image-spec v1.1.0 // indirect 43 | github.com/paulmach/orb v0.11.1 // indirect 44 | github.com/pierrec/lz4/v4 v4.1.22 // indirect 45 | github.com/pkg/errors v0.9.1 // indirect 46 | github.com/prometheus/client_model v0.6.1 // indirect 47 | github.com/prometheus/procfs v0.15.1 // indirect 48 | github.com/segmentio/asm v1.2.0 // indirect 49 | github.com/shopspring/decimal v1.4.0 // indirect 50 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 51 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 52 | go.opentelemetry.io/otel v1.35.0 // indirect 53 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 54 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 55 | go.opentelemetry.io/otel/sdk v1.35.0 // indirect 56 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 57 | go.opentelemetry.io/proto/otlp v1.5.0 // indirect 58 | golang.org/x/crypto v0.37.0 // indirect 59 | golang.org/x/sys v0.32.0 // indirect 60 | google.golang.org/grpc v1.72.0 // indirect 61 | google.golang.org/protobuf v1.36.5 // indirect 62 | gopkg.in/yaml.v3 v3.0.1 // indirect 63 | gotest.tools/v3 v3.5.2 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /gomod2nix.toml: -------------------------------------------------------------------------------- 1 | schema = 3 2 | 3 | [mod] 4 | [mod."github.com/ClickHouse/ch-go"] 5 | version = "v0.65.1" 6 | hash = "sha256-fmJMrpY0q2Z/OA/sCJYFjCtzAAQ3l1KQBwy4toLv12U=" 7 | [mod."github.com/ClickHouse/clickhouse-go/v2"] 8 | version = "v2.34.0" 9 | hash = "sha256-9qdCvIRKX4r0bCmeRIWGNPGIHDkgNARTq2bG8bDtEeA=" 10 | [mod."github.com/Microsoft/go-winio"] 11 | version = "v0.6.2" 12 | hash = "sha256-tVNWDUMILZbJvarcl/E7tpSnkn7urqgSHa2Eaka5vSU=" 13 | [mod."github.com/andybalholm/brotli"] 14 | version = "v1.1.1" 15 | hash = "sha256-kCt+irK1gvz2lGQUeEolYa5+FbLsfWlJMCd5hm+RPgQ=" 16 | [mod."github.com/beorn7/perks"] 17 | version = "v1.0.1" 18 | hash = "sha256-h75GUqfwJKngCJQVE5Ao5wnO3cfKD9lSIteoLp/3xJ4=" 19 | [mod."github.com/cespare/xxhash/v2"] 20 | version = "v2.3.0" 21 | hash = "sha256-7hRlwSR+fos1kx4VZmJ/7snR7zHh8ZFKX+qqqqGcQpY=" 22 | [mod."github.com/dgryski/go-rendezvous"] 23 | version = "v0.0.0-20200823014737-9f7001d12a5f" 24 | hash = "sha256-n/7xo5CQqo4yLaWMSzSN1Muk/oqK6O5dgDOFWapeDUI=" 25 | [mod."github.com/distribution/reference"] 26 | version = "v0.6.0" 27 | hash = "sha256-gr4tL+qz4jKyAtl8LINcxMSanztdt+pybj1T+2ulQv4=" 28 | [mod."github.com/docker/docker"] 29 | version = "v28.0.4+incompatible" 30 | hash = "sha256-nmNJsHr7QVB4GcaaHsrsQlIud/TUXYfieKg7aAmpEhc=" 31 | [mod."github.com/docker/go-connections"] 32 | version = "v0.5.0" 33 | hash = "sha256-aGbMRrguh98DupIHgcpLkVUZpwycx1noQXbtTl5Sbms=" 34 | [mod."github.com/docker/go-units"] 35 | version = "v0.5.0" 36 | hash = "sha256-iK/V/jJc+borzqMeqLY+38Qcts2KhywpsTk95++hImE=" 37 | [mod."github.com/felixge/fgprof"] 38 | version = "v0.9.3" 39 | hash = "sha256-Q0EOEvkwqNbB/yR85MGrbzoahGbWbSw8ISmP0KTdAw8=" 40 | [mod."github.com/felixge/httpsnoop"] 41 | version = "v1.0.4" 42 | hash = "sha256-c1JKoRSndwwOyOxq9ddCe+8qn7mG9uRq2o/822x5O/c=" 43 | [mod."github.com/go-faster/city"] 44 | version = "v1.0.1" 45 | hash = "sha256-D+tg4IMhFgmEObkZBw4qv9OVuBnCkv+Q0BQkbNIWxgk=" 46 | [mod."github.com/go-faster/errors"] 47 | version = "v0.7.1" 48 | hash = "sha256-X+Yp7AiTfEQ0kOoixqOud8nN3XvfGLLB/ijXZ+SXhvc=" 49 | [mod."github.com/go-logr/logr"] 50 | version = "v1.4.2" 51 | hash = "sha256-/W6qGilFlZNTb9Uq48xGZ4IbsVeSwJiAMLw4wiNYHLI=" 52 | [mod."github.com/go-logr/stdr"] 53 | version = "v1.2.2" 54 | hash = "sha256-rRweAP7XIb4egtT1f2gkz4sYOu7LDHmcJ5iNsJUd0sE=" 55 | [mod."github.com/gogo/protobuf"] 56 | version = "v1.3.2" 57 | hash = "sha256-pogILFrrk+cAtb0ulqn9+gRZJ7sGnnLLdtqITvxvG6c=" 58 | [mod."github.com/google/pprof"] 59 | version = "v0.0.0-20211214055906-6f57359322fd" 60 | hash = "sha256-Ju5Ke03QOM0YbubQT8jPPcjJq2mgpua8RmqB1UUSLAw=" 61 | [mod."github.com/google/uuid"] 62 | version = "v1.6.0" 63 | hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw=" 64 | [mod."github.com/grafana/pyroscope-go"] 65 | version = "v1.2.2" 66 | hash = "sha256-kYmqpLDyDZOZiM++Q30MhxoZthYqlcFrz25GBEagqkc=" 67 | [mod."github.com/grafana/pyroscope-go/godeltaprof"] 68 | version = "v0.1.8" 69 | hash = "sha256-NfB5yCKdTc58m//ZeQH/0uFj5BjcDY0VpuwE/IBGJZQ=" 70 | [mod."github.com/klauspost/compress"] 71 | version = "v1.18.0" 72 | hash = "sha256-jc5pMU/HCBFOShMcngVwNMhz9wolxjOb579868LtOuk=" 73 | [mod."github.com/moby/docker-image-spec"] 74 | version = "v1.3.1" 75 | hash = "sha256-xwSNLmMagzywdGJIuhrWl1r7cIWBYCOMNYbuDDT6Jhs=" 76 | [mod."github.com/munnerz/goautoneg"] 77 | version = "v0.0.0-20191010083416-a7dc8b61c822" 78 | hash = "sha256-79URDDFenmGc9JZu+5AXHToMrtTREHb3BC84b/gym9Q=" 79 | [mod."github.com/nats-io/nats.go"] 80 | version = "v1.41.2" 81 | hash = "sha256-79K3UuP/CmD9Rk3sJLrxNk9H7GfJJ/pWVic+C6PtLPw=" 82 | [mod."github.com/nats-io/nkeys"] 83 | version = "v0.4.11" 84 | hash = "sha256-dSkIT+KW+hT/Rk3NSkrb5ABLLiGGz2dppr9rwhjLOnM=" 85 | [mod."github.com/nats-io/nuid"] 86 | version = "v1.0.1" 87 | hash = "sha256-7wddxVz3hnFg/Pf+61+MtQJJL/l8EaC8brHoNsmD64c=" 88 | [mod."github.com/opencontainers/go-digest"] 89 | version = "v1.0.0" 90 | hash = "sha256-cfVDjHyWItmUGZ2dzQhCHgmOmou8v7N+itDkLZVkqkQ=" 91 | [mod."github.com/opencontainers/image-spec"] 92 | version = "v1.1.0" 93 | hash = "sha256-5OxW1ShHypLpzVu+BJivNlFX2JFPh9WKfJcMIgPZf4U=" 94 | [mod."github.com/paulmach/orb"] 95 | version = "v0.11.1" 96 | hash = "sha256-oh5J5jl15FZwNm0jiYvPxNprMbufuSOELtvYHk1LLNs=" 97 | [mod."github.com/pierrec/lz4/v4"] 98 | version = "v4.1.22" 99 | hash = "sha256-mxO2jXM6O2yzZjkJeck+C8ncLZs/5EGoMQU1yQh/row=" 100 | [mod."github.com/pkg/errors"] 101 | version = "v0.9.1" 102 | hash = "sha256-mNfQtcrQmu3sNg/7IwiieKWOgFQOVVe2yXgKBpe/wZw=" 103 | [mod."github.com/pkg/profile"] 104 | version = "v1.7.0" 105 | hash = "sha256-wd8L8WiPoojo/oVUshgiJdM/k367LL1XO5BL5u1L2UU=" 106 | [mod."github.com/prometheus/client_golang"] 107 | version = "v1.22.0" 108 | hash = "sha256-OJ/9rlWG1DIPQJAZUTzjykkX0o+f+4IKLvW8YityaMQ=" 109 | [mod."github.com/prometheus/client_model"] 110 | version = "v0.6.1" 111 | hash = "sha256-rIDyUzNfxRA934PIoySR0EhuBbZVRK/25Jlc/r8WODw=" 112 | [mod."github.com/prometheus/common"] 113 | version = "v0.62.0" 114 | hash = "sha256-UFccvzMJaBrUpnqVgZgohRcgk5SKMi/UJnXNtazCnx8=" 115 | [mod."github.com/prometheus/procfs"] 116 | version = "v0.15.1" 117 | hash = "sha256-H+WXJemFFwdoglmD6p7JRjrJJZmIVAmJwYmLbZ8Q9sw=" 118 | [mod."github.com/redis/go-redis/v9"] 119 | version = "v9.7.3" 120 | hash = "sha256-7ip5Ns/NEnFmVLr5iN8m3gS4RrzVAYJ7pmJeeaTmjjo=" 121 | [mod."github.com/segmentio/asm"] 122 | version = "v1.2.0" 123 | hash = "sha256-zbNuKxNrUDUc6IlmRQNuJQzVe5Ol/mqp7srDg9IMMqs=" 124 | [mod."github.com/shopspring/decimal"] 125 | version = "v1.4.0" 126 | hash = "sha256-U36bC271jQsjuWFF8BfLz4WicxPJUcPHRGxLvTz4Mdw=" 127 | [mod."go.opentelemetry.io/auto/sdk"] 128 | version = "v1.1.0" 129 | hash = "sha256-cA9qCCu8P1NSJRxgmpfkfa5rKyn9X+Y/9FSmSd5xjyo=" 130 | [mod."go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"] 131 | version = "v0.49.0" 132 | hash = "sha256-1/7YxtXZM4i75rXXIO6UN4CTY93nE/v2k2htS0uUOVg=" 133 | [mod."go.opentelemetry.io/otel"] 134 | version = "v1.35.0" 135 | hash = "sha256-LHrBtBnyDtvJGtrXHMPIFe7U53B4bZzpePB4u8Xo4Bg=" 136 | [mod."go.opentelemetry.io/otel/exporters/otlp/otlptrace"] 137 | version = "v1.35.0" 138 | hash = "sha256-MNPc7C2TgrwTQTO/YgJgkbuQ/Rvx/qCTVTB5lQgNFNk=" 139 | [mod."go.opentelemetry.io/otel/metric"] 140 | version = "v1.35.0" 141 | hash = "sha256-K9I0LRZqSLrC09Cuk7tp0VEk3cUVDs8S5MGnu9jw92Q=" 142 | [mod."go.opentelemetry.io/otel/sdk"] 143 | version = "v1.35.0" 144 | hash = "sha256-G1pNX57JVeUVaGD6QQgc6EeNCkAURVDalTnoyhVOK78=" 145 | [mod."go.opentelemetry.io/otel/trace"] 146 | version = "v1.35.0" 147 | hash = "sha256-HC2+OGDe2rg0+E8WymQbUNoc249NXM1gIBJzK4UhcQE=" 148 | [mod."go.opentelemetry.io/proto/otlp"] 149 | version = "v1.5.0" 150 | hash = "sha256-k4jHapACIcAxN1q11TLorvjj6Sdn5P+InEC4sDtoZPY=" 151 | [mod."golang.org/x/crypto"] 152 | version = "v0.37.0" 153 | hash = "sha256-9NwDEcii1e2JYM/+3y1yNzWnt/ChMm27e9OtfuF39OM=" 154 | [mod."golang.org/x/sys"] 155 | version = "v0.32.0" 156 | hash = "sha256-c9RRnyKQy9Kl8hpbtcgkm1O5H7gOdk9Rv925F8fZS6E=" 157 | [mod."google.golang.org/grpc"] 158 | version = "v1.72.0" 159 | hash = "sha256-tqu+ACMfKjhqdCGN3jLEmtaHB5ywgHGaS/eDeDRnf+M=" 160 | [mod."google.golang.org/protobuf"] 161 | version = "v1.36.5" 162 | hash = "sha256-isupBiQUrKPEFzK94k5cgzM3Ab5fMXp352/zcsXV1JU=" 163 | [mod."gopkg.in/yaml.v3"] 164 | version = "v3.0.1" 165 | hash = "sha256-FqL9TKYJ0XkNwJFnq9j0VvJ5ZUU1RvH/52h/f5bkYAU=" 166 | [mod."gotest.tools/v3"] 167 | version = "v3.5.2" 168 | hash = "sha256-eAxnRrF2bQugeFYzGLOr+4sLyCPOpaTWpoZsIKNP1WE=" 169 | -------------------------------------------------------------------------------- /platforms/BUILD.bazel: -------------------------------------------------------------------------------- 1 | # 2 | # platforms/BUILD.bazel 3 | # 4 | package(default_visibility = ["//visibility:public"]) 5 | 6 | platform( 7 | name = "linux_amd64", 8 | constraint_values = [ 9 | "@platforms//os:linux", 10 | "@platforms//cpu:x86_64", 11 | ], 12 | ) 13 | 14 | platform( 15 | name = "linux_arm64", 16 | constraint_values = [ 17 | "@platforms//os:linux", 18 | "@platforms//cpu:arm64", 19 | ], 20 | ) 21 | -------------------------------------------------------------------------------- /scripts/build_docker_image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # scripts/build_docker_image.sh 4 | # Builds a specific Docker image variant for go-nix-simple 5 | 6 | # Exit on error, treat unset variables as errors, disable globbing, pipefail 7 | set -euo pipefail 8 | 9 | # # --- Debug Arguments --- 10 | # echo "DEBUG: Received $# arguments:" >&2 11 | # arg_index=1 12 | # for arg in "$@"; do 13 | # echo "DEBUG: Arg ${arg_index}: '${arg}'" >&2 14 | # ((arg_index++)) 15 | # done 16 | 17 | # --- Arguments --- 18 | if [[ "$#" -ne 11 ]]; then 19 | echo "Usage: $0 " 20 | exit 1 21 | fi 22 | 23 | # Assign arguments to variables 24 | BASE_RAW="$1" 25 | CACHE_RAW="$2" 26 | PACKER_RAW="$3" 27 | VERSION_RAW="$4" 28 | COMMIT_RAW="$5" 29 | DATE_RAW="$6" 30 | REPO_PREFIX_RAW="$7" 31 | DOCKER_IMAGE_PREFIX_RAW="$8" 32 | CONTAINERFILE_DIR_RAW="$9" 33 | CONTEXT_PATH_RAW="${10}" 34 | OUTPUT_DIR_RAW="${11}" 35 | 36 | # --- Trim Whitespace --- 37 | # Use xargs to remove leading/trailing whitespace from relevant variables 38 | BASE=$(echo "${BASE_RAW}" | xargs) 39 | CACHE=$(echo "${CACHE_RAW}" | xargs) 40 | PACKER=$(echo "${PACKER_RAW}" | xargs) 41 | VERSION=$(echo "${VERSION_RAW}" | xargs) 42 | COMMIT=$(echo "${COMMIT_RAW}" | xargs) 43 | DATE=$(echo "${DATE_RAW}" | xargs) 44 | REPO_PREFIX=$(echo "${REPO_PREFIX_RAW}" | xargs) 45 | DOCKER_IMAGE_PREFIX=$(echo "${DOCKER_IMAGE_PREFIX_RAW}" | xargs) 46 | CONTAINERFILE_DIR=$(echo "${CONTAINERFILE_DIR_RAW}" | xargs) 47 | CONTEXT_PATH=$(echo "${CONTEXT_PATH_RAW}" | xargs) 48 | OUTPUT_DIR=$(echo "${OUTPUT_DIR_RAW}" | xargs) 49 | 50 | # --- Variables --- 51 | TARGET_NAME="build-image-docker-${BASE}-${CACHE}-${PACKER}" 52 | CONTAINERFILE="${CONTAINERFILE_DIR}/Containerfile.${BASE}.${CACHE}.${PACKER}" 53 | IMAGE_TAG="${REPO_PREFIX}/${DOCKER_IMAGE_PREFIX}-${BASE}-${CACHE}-${PACKER}:${VERSION}" 54 | LATEST_TAG="${REPO_PREFIX}/${DOCKER_IMAGE_PREFIX}-${BASE}-${CACHE}-${PACKER}:latest" 55 | TIMESTAMP_CMD='date +"%Y-%m-%d %H:%M:%S.%3N"' 56 | METRIC_FILE="${OUTPUT_DIR}/${TARGET_NAME}.csv" 57 | 58 | # --- Validation --- 59 | if [[ ! -f "${CONTAINERFILE}" ]]; then 60 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Containerfile not found at ${CONTAINERFILE}" >&2 61 | exit 1 62 | fi 63 | if [[ ! -d "${OUTPUT_DIR}" ]]; then 64 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Output directory not found at ${OUTPUT_DIR}" >&2 65 | exit 1 66 | fi 67 | 68 | # --- Construct Docker Command Array --- 69 | # Using an array is safer for handling arguments with spaces or special chars 70 | declare -a docker_build_cmd 71 | docker_build_cmd=( 72 | "docker" "build" 73 | "--network=host" 74 | "--build-arg" "MYPATH=${CONTEXT_PATH}" 75 | "--build-arg" "COMMIT=${COMMIT}" 76 | "--build-arg" "DATE=${DATE}" 77 | "--build-arg" "VERSION=${VERSION}" 78 | "--file" "${CONTAINERFILE}" 79 | "--tag" "${IMAGE_TAG}" 80 | "--tag" "${LATEST_TAG}" 81 | "${CONTEXT_PATH}" 82 | ) 83 | 84 | # --- Build --- 85 | echo "[$(eval "$TIMESTAMP_CMD")] Starting ${TARGET_NAME}..." 86 | # Print the command before executing (using printf for better quoting visibility) 87 | printf "Executing command: " 88 | printf "%q " "${docker_build_cmd[@]}" 89 | printf "\n" 90 | 91 | start_time_ns=$(date +%s%N) 92 | 93 | # Execute the command from the array, capture potential errors 94 | if ! "${docker_build_cmd[@]}"; then 95 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Docker build failed for ${TARGET_NAME}" >&2 96 | exit 1 # Exit if build fails 97 | fi 98 | 99 | # --- Timing --- 100 | end_time_ns=$(date +%s%N) 101 | duration_ms=$(( (end_time_ns - start_time_ns) / 1000000 )) 102 | echo "[$(eval "$TIMESTAMP_CMD")] Finished ${TARGET_NAME}. Duration: ${duration_ms} ms." 103 | 104 | # --- Collect Metrics --- 105 | echo "[$(eval "$TIMESTAMP_CMD")] Collecting metrics for ${IMAGE_TAG}..." 106 | # Use temporary variables to store inspect results, handle potential errors 107 | image_size_bytes_raw=$(docker image inspect --format='{{.Size}}' "${IMAGE_TAG}" 2>/dev/null) 108 | layer_count_raw=$(docker image inspect --format='{{len .RootFS.Layers}}' "${IMAGE_TAG}" 2>/dev/null) 109 | 110 | # Assign default value 0 if inspect failed or returned empty 111 | image_size_bytes=${image_size_bytes_raw:-0} 112 | layer_count=${layer_count_raw:-0} 113 | 114 | if [[ "${image_size_bytes}" == 0 || "${layer_count}" == 0 ]]; then 115 | echo "[$(eval "$TIMESTAMP_CMD")] WARNING: Could not inspect image ${IMAGE_TAG}. Size/Layers set to 0." >&2 116 | fi 117 | 118 | # --- Write Metrics File --- 119 | # Format: target_name,duration_ms,size_bytes,layer_count 120 | echo "${TARGET_NAME},${duration_ms},${image_size_bytes},${layer_count}" > "${METRIC_FILE}" 121 | echo "[$(eval "$TIMESTAMP_CMD")] Metrics saved to ${METRIC_FILE}" 122 | 123 | exit 0 # Explicitly exit successfully 124 | -------------------------------------------------------------------------------- /scripts/build_nix_image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # scripts/build_nix_image.sh 4 | # Builds a specific Nix flake image output, loads it into Docker, 5 | # inspects it, and saves build metrics to a file. 6 | 7 | # Exit on error, treat unset variables as errors, disable globbing, pipefail 8 | set -euo pipefail 9 | 10 | # --- Arguments --- 11 | if [[ "$#" -ne 4 ]]; then 12 | echo "Usage: $0 " >&2 13 | exit 1 14 | fi 15 | 16 | TARGET_NAME="$1" 17 | FLAKE_OUTPUT_KEY="$2" 18 | EXPECTED_DOCKER_TAG_VERSIONED="$3" # e.g., repo/img:1.0.0 19 | OUTPUT_DIR="$4" 20 | 21 | # --- Variables --- 22 | TIMESTAMP_CMD='date +"%Y-%m-%d %H:%M:%S.%3N"' 23 | METRIC_FILE="${OUTPUT_DIR}/${TARGET_NAME}.csv" 24 | NIX_BUILD_RESULT_LINK="./result" 25 | # Derive the :latest tag from the versioned tag 26 | EXPECTED_DOCKER_TAG_LATEST="${EXPECTED_DOCKER_TAG_VERSIONED%:*}:latest" 27 | 28 | # --- Validation --- 29 | if [[ ! -d "${OUTPUT_DIR}" ]]; then 30 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Output directory not found at ${OUTPUT_DIR}" >&2 31 | exit 1 32 | fi 33 | 34 | # --- Build Phase --- 35 | echo "[$(eval "$TIMESTAMP_CMD")] Starting ${TARGET_NAME} (Nix Build)..." 36 | start_time_ns=$(date +%s%N) 37 | 38 | if ! nix build ".#${FLAKE_OUTPUT_KEY}" --out-link "${NIX_BUILD_RESULT_LINK}"; then 39 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Nix build failed for ${FLAKE_OUTPUT_KEY}" >&2 40 | exit 1 41 | fi 42 | 43 | nix_build_end_time_ns=$(date +%s%N) 44 | nix_build_duration_ms=$(( (nix_build_end_time_ns - start_time_ns) / 1000000 )) 45 | echo "[$(eval "$TIMESTAMP_CMD")] Finished Nix build for ${TARGET_NAME}. Duration: ${nix_build_duration_ms} ms." 46 | 47 | # --- Docker Load Phase --- 48 | echo "[$(eval "$TIMESTAMP_CMD")] Loading Nix result into Docker..." 49 | if ! docker load < "${NIX_BUILD_RESULT_LINK}"; then 50 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: docker load failed for ${TARGET_NAME}" >&2 51 | rm -f "${NIX_BUILD_RESULT_LINK}" 52 | exit 1 53 | fi 54 | echo "[$(eval "$TIMESTAMP_CMD")] Finished loading Nix result (Image tagged as :latest)." 55 | 56 | # --- Docker Tag Phase --- 57 | # Explicitly tag the loaded image (:latest) with the specific version tag 58 | echo "[$(eval "$TIMESTAMP_CMD")] Tagging ${EXPECTED_DOCKER_TAG_LATEST} as ${EXPECTED_DOCKER_TAG_VERSIONED}..." 59 | if ! docker tag "${EXPECTED_DOCKER_TAG_LATEST}" "${EXPECTED_DOCKER_TAG_VERSIONED}"; then 60 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: docker tag failed for ${TARGET_NAME}" >&2 61 | rm -f "${NIX_BUILD_RESULT_LINK}" 62 | exit 1 63 | fi 64 | echo "[$(eval "$TIMESTAMP_CMD")] Finished tagging image." 65 | 66 | 67 | # --- Collect Metrics --- 68 | # Now inspect using the versioned tag, which should exist 69 | echo "[$(eval "$TIMESTAMP_CMD")] Collecting metrics for ${EXPECTED_DOCKER_TAG_VERSIONED}..." 70 | image_size_bytes_raw=$(docker image inspect --format='{{.Size}}' "${EXPECTED_DOCKER_TAG_VERSIONED}" 2>/dev/null) 71 | layer_count_raw=$(docker image inspect --format='{{len .RootFS.Layers}}' "${EXPECTED_DOCKER_TAG_VERSIONED}" 2>/dev/null) 72 | 73 | image_size_bytes=${image_size_bytes_raw:-0} 74 | layer_count=${layer_count_raw:-0} 75 | 76 | if [[ "${image_size_bytes}" == 0 || "${layer_count}" == 0 ]]; then 77 | echo "[$(eval "$TIMESTAMP_CMD")] WARNING: Could not inspect image ${EXPECTED_DOCKER_TAG_VERSIONED}. Size/Layers set to 0." >&2 78 | fi 79 | 80 | # --- Write Metrics File --- 81 | echo "${TARGET_NAME},${nix_build_duration_ms},${image_size_bytes},${layer_count}" > "${METRIC_FILE}" 82 | echo "[$(eval "$TIMESTAMP_CMD")] Metrics saved to ${METRIC_FILE}" 83 | 84 | # --- Cleanup --- 85 | rm -f "${NIX_BUILD_RESULT_LINK}" 86 | 87 | exit 0 88 | -------------------------------------------------------------------------------- /scripts/generate_summary.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # scripts/generate_summary.sh 4 | # Finds the latest build output directory under ./output, reads build metric 5 | # CSV files from it, prints a summary table, and saves it to summary.txt 6 | # within that directory. 7 | 8 | # Exit on error, treat unset variables as errors, disable globbing, pipefail 9 | set -euo pipefail 10 | 11 | # --- Argument --- 12 | # No arguments needed, script finds the latest directory 13 | # if [[ "$#" -ne 1 ]]; then 14 | # echo "Usage: $0 " >&2 15 | # exit 1 16 | # fi 17 | # BUILD_OUTPUT_DIR="$1" # Removed argument handling 18 | 19 | # --- Phase 1: Find Newest Output Directory --- 20 | BASE_OUTPUT_DIR="./output" 21 | 22 | if [[ ! -d "${BASE_OUTPUT_DIR}" ]]; then 23 | echo "ERROR: Base output directory '${BASE_OUTPUT_DIR}' not found." >&2 24 | exit 1 25 | fi 26 | 27 | # Find directories matching the timestamp pattern, sort descending, get the first one 28 | LATEST_OUTPUT_DIR=$(find "${BASE_OUTPUT_DIR}" -mindepth 1 -maxdepth 1 -type d -regextype posix-extended -regex '.*/[0-9]{8}_[0-9]{6}' -print | sort -r | head -n 1) 29 | 30 | if [[ -z "${LATEST_OUTPUT_DIR}" ]]; then 31 | echo "ERROR: No valid output directory found under ${BASE_OUTPUT_DIR}" >&2 32 | exit 1 33 | fi 34 | 35 | echo "DEBUG: Phase 1 - Found latest output directory: '${LATEST_OUTPUT_DIR}'" >&2 36 | SUMMARY_FILE="${LATEST_OUTPUT_DIR}/summary.txt" # Define summary output file path 37 | # --- End Phase 1 --- 38 | 39 | 40 | # --- Phase 2: Find Metric Files in Latest Directory --- 41 | echo "DEBUG: Phase 2 - Searching for 'build-*.csv' files in '${LATEST_OUTPUT_DIR}'" >&2 42 | 43 | # Use mapfile to read null-delimited output from find into the array 44 | declare -a metric_files 45 | mapfile -d $'\0' metric_files < <(find "${LATEST_OUTPUT_DIR}" -maxdepth 1 -name 'build-*.csv' -print0 | sort -z) 46 | 47 | # mapfile might add an empty element if the input ends with a delimiter, remove it. 48 | if [[ ${#metric_files[@]} -gt 0 && -z "${metric_files[-1]}" ]]; then 49 | unset 'metric_files[-1]' # Remove the last empty element 50 | fi 51 | 52 | # Debugging: Print found files 53 | if [[ ${#metric_files[@]} -eq 0 ]]; then 54 | echo "DEBUG: Phase 2 - No 'build-*.csv' files found." >&2 55 | else 56 | echo "DEBUG: Phase 2 - Found ${#metric_files[@]} metric file(s):" >&2 57 | printf " '%s'\n" "${metric_files[@]}" >&2 58 | fi 59 | # --- End Phase 2 --- 60 | 61 | 62 | # --- Phase 3: Generate Summary Content --- 63 | # Use a temporary variable to store the summary content 64 | summary_content="" 65 | header_line_1="=============================================================================================" 66 | header_line_2="Build Summary - From Directory: ${LATEST_OUTPUT_DIR}" 67 | header_line_3="Target | Time (ms) | Size (MB) | Layers" 68 | header_line_4="------------------------------------------------------------|-----------|-----------|--------" 69 | 70 | summary_content+="${header_line_1}\n" 71 | summary_content+="${header_line_2}\n" 72 | summary_content+="${header_line_1}\n" 73 | summary_content+="${header_line_3}\n" 74 | summary_content+="${header_line_4}\n" 75 | 76 | if [[ ${#metric_files[@]} -eq 0 ]]; then 77 | summary_content+="No build data files (*.csv) found in ${LATEST_OUTPUT_DIR}\n" 78 | else 79 | # Process the found files using awk and append to the variable 80 | summary_content+=$(printf '%s\0' "${metric_files[@]}" | xargs -0 awk -F',' '{printf "%-60s| %9d | %9.2f | %6d\n", $1, $2, $3/1024/1024, $4}') 81 | # Add an explicit newline AFTER the awk output, BEFORE the footer separator 82 | summary_content+="\n" 83 | fi 84 | 85 | summary_content+="${header_line_1}\n" # Footer separator 86 | # --- End Phase 3 --- 87 | 88 | 89 | # --- Phase 4: Output Summary --- 90 | # Print to console 91 | echo -e "${summary_content}" 92 | 93 | # Write to file 94 | echo -e "${summary_content}" > "${SUMMARY_FILE}" 95 | echo "INFO: Summary saved to ${SUMMARY_FILE}" 96 | # --- End Phase 4 --- 97 | 98 | exit 0 99 | -------------------------------------------------------------------------------- /scripts/generate_validation_summary.sh: -------------------------------------------------------------------------------- 1 | # --- Print Summary --- 2 | echo "========================================================================" 3 | echo "Aggregated Validation Summary - From Directory: ${LATEST_VALIDATION_DIR}" 4 | echo "========================================================================" 5 | 6 | # Print PASSED section if any passed 7 | if [[ ${passed_count} -gt 0 ]]; then 8 | echo "PASSED (${passed_count}):" 9 | # Sort alphabetically before printing (optional but nice) 10 | mapfile -t sorted_passed < <(printf '%s\n' "${passed_targets[@]}" | sort) 11 | printf " %s\n" "${sorted_passed[@]}" # Print sorted list 12 | fi 13 | 14 | # Print FAILED section if any failed 15 | if [[ ${failed_count} -gt 0 ]]; then 16 | # Add a blank line if PASSED section was also printed 17 | [[ ${passed_count} -gt 0 ]] && echo "" 18 | echo "FAILED (${failed_count}):" 19 | # Sort alphabetically before printing (optional but nice) 20 | mapfile -t sorted_failed < <(printf '%s\n' "${failed_targets[@]}" | sort) 21 | for target in "${sorted_failed[@]}"; do 22 | # Safely handle potential missing reasons (though unlikely with current logic) 23 | reason="${failed_reasons[${target}]:-Unknown Error}" 24 | printf " %s (Reason: %s)\n" "${target}" "${reason}" 25 | done 26 | fi 27 | 28 | # Print Footer 29 | echo "------------------------------------------------------------------------" 30 | echo "Total Validations: ${total_count} | Passed: ${passed_count} | Failed: ${failed_count}" 31 | echo "========================================================================" 32 | 33 | # Exit with non-zero status if any tests failed 34 | if [[ ${failed_count} -gt 0 ]]; then 35 | exit 1 36 | fi 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /scripts/remove_docker_images.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to remove Docker images matching a regular expression 4 | # Supports a -f or --force flag to force removal 5 | 6 | # Exit immediately if a command exits with a non-zero status. 7 | # Treat unset variables as an error when substituting. 8 | # Prevent errors in a pipeline from being masked. 9 | set -euo pipefail 10 | 11 | # --- Configuration --- 12 | DEFAULT_REGEX="go-nix-simple" 13 | FORCE_REMOVE="" # Will be set to "--force" if flag is present 14 | REGEX="" 15 | 16 | # --- Argument Parsing --- 17 | while [[ $# -gt 0 ]]; do 18 | case "$1" in 19 | -f|--force) 20 | FORCE_REMOVE="--force" 21 | shift # past argument 22 | ;; 23 | *) 24 | # Assume the first non-flag argument is the regex 25 | if [[ -z "$REGEX" ]]; then 26 | REGEX="$1" 27 | else 28 | echo "Error: Unknown argument or multiple regex patterns provided: $1" >&2 29 | exit 1 30 | fi 31 | shift # past argument 32 | ;; 33 | esac 34 | done 35 | 36 | # Use default regex if none was provided via arguments 37 | if [[ -z "$REGEX" ]]; then 38 | REGEX="$DEFAULT_REGEX" 39 | fi 40 | 41 | # --- Main Logic --- 42 | echo "Searching for Docker images matching regex: '${REGEX}'" 43 | if [[ -n "$FORCE_REMOVE" ]]; then 44 | echo "Force removal flag is set." 45 | fi 46 | 47 | # Find image Repo:Tag and ID matching the regex and read into an array 48 | SEPARATOR="#|#" 49 | readarray -t FOUND_IMAGES < <(docker images --format "{{.Repository}}:{{.Tag}}${SEPARATOR}{{.ID}}" | grep -E -- "${REGEX}" || true) # Allow grep to not find anything without exiting 50 | 51 | # Check if the array is empty 52 | if [ ${#FOUND_IMAGES[@]} -eq 0 ]; then 53 | echo "No images found matching the regex." 54 | exit 0 55 | fi 56 | 57 | echo "Found the following images to remove:" 58 | # Prepare arrays for IDs and display strings 59 | declare -a IMAGE_IDS_TO_REMOVE 60 | declare -a DISPLAY_STRINGS 61 | 62 | # Process the found images 63 | for image_info in "${FOUND_IMAGES[@]}"; do 64 | # Split the string by the separator, quoting the separator variable 65 | repo_tag="${image_info%%"${SEPARATOR}"*}" 66 | image_id="${image_info##*"${SEPARATOR}"}" 67 | 68 | # Add ID to the removal list 69 | IMAGE_IDS_TO_REMOVE+=("$image_id") 70 | # Add formatted string to the display list 71 | DISPLAY_STRINGS+=(" ${repo_tag} (ID: ${image_id})") 72 | done 73 | 74 | # Print each display string on a new line safely using printf 75 | printf "%s\n" "${DISPLAY_STRINGS[@]}" 76 | 77 | # Ask for confirmation before removing 78 | read -r -p "Are you sure you want to remove these images? (y/N): " confirm 79 | if ! [[ "$confirm" =~ ^[yY]([eE][sS])?$ ]]; then 80 | echo "Aborting." 81 | exit 1 82 | fi 83 | 84 | echo "Attempting to remove images..." 85 | 86 | # Get unique IDs 87 | mapfile -t UNIQUE_IDS < <(printf "%s\n" "${IMAGE_IDS_TO_REMOVE[@]}" | sort -u) 88 | 89 | # Check if there are any unique IDs left after filtering 90 | if [ ${#UNIQUE_IDS[@]} -gt 0 ]; then 91 | # Conditionally add the force flag 92 | # Note: We expand FORCE_REMOVE which will be empty or "--force" 93 | # shellcheck disable=SC2086 # We want word splitting for $FORCE_REMOVE 94 | docker rmi $FORCE_REMOVE -- "${UNIQUE_IDS[@]}" 95 | else 96 | echo "No unique image IDs found to remove (perhaps they were duplicates)." 97 | fi 98 | 99 | echo "Cleanup attempt finished." 100 | -------------------------------------------------------------------------------- /scripts/validate_image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # scripts/validate_image.sh 4 | # Runs the validation tool against a specified Docker image tag 5 | # and writes a result file to the validation output directory. 6 | 7 | # Exit on error, treat unset variables as errors, disable globbing, pipefail 8 | set -euo pipefail 9 | 10 | # --- Debug Arguments --- 11 | echo "DEBUG: Received $# arguments:" >&2 12 | arg_index=1 13 | for arg in "$@"; do 14 | echo "DEBUG: Arg ${arg_index}: '${arg}'" >&2 15 | ((arg_index++)) 16 | done 17 | 18 | # --- Arguments --- 19 | # Expect 5 arguments now 20 | if [[ "$#" -ne 5 ]]; then 21 | echo "Usage: $0 " >&2 22 | exit 1 23 | fi 24 | 25 | # Assign raw arguments 26 | MAKE_TARGET_NAME_RAW="$1" 27 | VALIDATOR_PATH_RAW="$2" 28 | IMAGE_TAG_TO_VALIDATE_RAW="$3" 29 | TIMEOUT_SECONDS_RAW="$4" 30 | VALIDATION_OUTPUT_DIR_RAW="$5" # New argument 31 | 32 | # Trim whitespace using xargs 33 | MAKE_TARGET_NAME=$(echo "${MAKE_TARGET_NAME_RAW}" | xargs) 34 | VALIDATOR_PATH=$(echo "${VALIDATOR_PATH_RAW}" | xargs) 35 | IMAGE_TAG_TO_VALIDATE=$(echo "${IMAGE_TAG_TO_VALIDATE_RAW}" | xargs) 36 | TIMEOUT_SECONDS=$(echo "${TIMEOUT_SECONDS_RAW}" | xargs) 37 | VALIDATION_OUTPUT_DIR=$(echo "${VALIDATION_OUTPUT_DIR_RAW}" | xargs) # New argument 38 | 39 | # --- Variables --- 40 | TIMESTAMP_CMD='date +"%Y-%m-%d %H:%M:%S.%3N"' 41 | # Define result file path using the Make target name 42 | RESULT_FILE="${VALIDATION_OUTPUT_DIR}/${MAKE_TARGET_NAME}.result" 43 | 44 | # --- Validation --- 45 | if [[ ! -x "${VALIDATOR_PATH}" ]]; then 46 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Validator executable not found or not executable at ${VALIDATOR_PATH}" >&2 47 | exit 1 48 | fi 49 | if ! [[ "${TIMEOUT_SECONDS}" =~ ^[0-9]+$ ]]; then 50 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Timeout value '${TIMEOUT_SECONDS}' is not a valid number." >&2 51 | exit 1 52 | fi 53 | if [[ ! -d "${VALIDATION_OUTPUT_DIR}" ]]; then 54 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Validation output directory '${VALIDATION_OUTPUT_DIR}' does not exist." >&2 55 | exit 1 56 | fi 57 | 58 | # --- Execute Validator --- 59 | echo "[$(eval "$TIMESTAMP_CMD")] Validating image ${IMAGE_TAG_TO_VALIDATE} (from target ${MAKE_TARGET_NAME})..." 60 | 61 | declare -a validator_cmd 62 | validator_cmd=( 63 | "${VALIDATOR_PATH}" 64 | "-images=${IMAGE_TAG_TO_VALIDATE}" 65 | "-timeout=${TIMEOUT_SECONDS}s" 66 | ) 67 | 68 | printf "Executing command: " 69 | printf "%q " "${validator_cmd[@]}" 70 | printf "\n" 71 | 72 | # Execute the validator, capture status and error 73 | validation_error="" 74 | if ! "${validator_cmd[@]}"; then 75 | # Capture a generic error message if the validator exits non-zero 76 | # The validator's own logs will have the specific details. 77 | validation_error="Validator exited with non-zero status" 78 | echo "[$(eval "$TIMESTAMP_CMD")] ERROR: Validation failed for ${IMAGE_TAG_TO_VALIDATE}" >&2 79 | fi 80 | 81 | # --- Write Result File --- 82 | if [[ -z "${validation_error}" ]]; then 83 | echo "PASSED" > "${RESULT_FILE}" 84 | echo "[$(eval "$TIMESTAMP_CMD")] Validation successful for ${IMAGE_TAG_TO_VALIDATE}. Result saved to ${RESULT_FILE}" 85 | exit 0 86 | else 87 | echo "FAILED: ${validation_error}" > "${RESULT_FILE}" 88 | echo "[$(eval "$TIMESTAMP_CMD")] Validation failed for ${IMAGE_TAG_TO_VALIDATE}. Result saved to ${RESULT_FILE}" 89 | exit 1 # Exit with error code 1 if validation failed 90 | fi 91 | -------------------------------------------------------------------------------- /tools/python/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@rules_python//python:defs.bzl", "py_runtime_pair") 2 | load("@rules_python//python:py_runtime.bzl", "py_runtime") 3 | 4 | # Use the default Python runtime from the toolchain 5 | py_runtime( 6 | name = "python_runtime", 7 | # Include all Python files needed for execution 8 | files = ["@python_3_13//:files"], 9 | interpreter = "@python_3_13//:python3", 10 | python_version = "PY3", 11 | # Ensure the runtime is available for all rules 12 | visibility = ["//visibility:public"], 13 | ) 14 | 15 | py_runtime_pair( 16 | name = "python_runtime_pair", 17 | py2_runtime = None, 18 | py3_runtime = ":python_runtime", 19 | visibility = ["//visibility:public"], 20 | ) 21 | 22 | toolchain( 23 | name = "python_toolchain", 24 | # Ensure the toolchain is compatible with remote execution 25 | exec_compatible_with = [ 26 | "@platforms//os:linux", 27 | "@platforms//cpu:x86_64", 28 | ], 29 | toolchain = ":python_runtime_pair", 30 | toolchain_type = "@rules_python//python:toolchain_type", 31 | # Make this toolchain available to all rules 32 | visibility = ["//visibility:public"], 33 | ) 34 | --------------------------------------------------------------------------------