Generate smart, cache-friendly multi-stage Dockerfiles for .NET & Go projects β instantly. β¨
- Why?
- Features
- Installation
- CLI Usage
- Examples
- Config File
- Generated Dockerfile (Dotnet)
- Generated Dockerfile (Go)
- .NET Context Discovery
- Autodetection Logic
- Version Output
- Troubleshooting
- Development
- Roadmap
- Contributing
- License
- Disclaimer
Building Docker images often wastes time by copying the full source tree before dependency restore β destroying layer cache efficiency. This tool fixes that:
- π§ Smart dependency staging: Only copies the minimal project graph & shared context before
restore. - β‘ Better build caching: Faster iterative builds locally & in CI.
- π§© Multi-language support: .NET & Go today (extensible design for more).
- π Configurable: Override base images & inject OS packages without editing Dockerfiles.
- π Reproducible: Deterministic layering strategy.
- π Multi-language generators (
dotnet,go). - π΅οΈ Autodetect project language (or force via
--language). - 𧬠Recursive .NET project graph traversal (follows
<ProjectReference>; detects cycles). - π¦ Automatic inclusion of shared files:
nuget.config,Directory.Build.props,Directory.Packages.props. - π§Ύ YAML config (
.dockerbuild) to override base/build images +apkpackage install lists. - π§ͺ Dry-run mode with unified diff output.
- π Optional verbose diagnostic logging (
--verbose) showing detection & generation decisions (logs to stderr, leaving stdout clean). - πͺ Cache-friendly layering for both ecosystems.
- π§± Go builds use mount caches for modules & build output.
go install github.com/n2jsoft-public-org/dockerfile-generator@latestModule path (per
go.mod):github.com/n2jsoft-public-org/dockerfile-generator
By default make install places the binary in the first entry of your GOPATH, i.e. $GOPATH/bin (commonly $HOME/go/bin). Ensure that directory is on your PATH.
git clone https://github.com/n2jsoft-public-org/dockerfile-generator.git
cd dockerfile-generator
make install # installs to $(go env GOPATH)/bin/dockerfile-genOverride destination prefix (installs into <prefix>/bin):
make install PREFIX=$HOME/.local # installs to $HOME/.local/bin/dockerfile-genUninstall (matches the prefix you used to install):
make uninstall # removes $(go env GOPATH)/bin/dockerfile-gen
make uninstall PREFIX=$HOME/.local # removes $HOME/.local/bin/dockerfile-gen- The produced binary name is
dockerfile-gen.exe. - Default install path:
%GOPATH%\bin(e.g.C:\Users\<you>\go\bin). - Make sure that path is added to your
Pathenvironment variable. - PowerShell example:
$env:PATH += ";$HOME\go\bin"go build -o dockerfile-gen .
install -m 0755 dockerfile-gen "$HOME/go/bin/dockerfile-gen" # or another directory on PATH(Use dockerfile-gen.exe on Windows and place it in %GOPATH%\bin.)
General form:
dockerfile-gen [--path <project-or-dir>] [--language dotnet|go] [--dockerfile Dockerfile] [--dry-run] [--verbose]
If --path is omitted it defaults to the current directory (.).
Short flags: -p, -l, -f, -d. Version: -v / -V.
Legacy (deprecated): single-dash long forms (-path, -language, ...).
-p, --path(string, optional, default.):- .NET: path to a
.csprojOR a directory containing exactly one.csproj. - Go: path to a
go.modOR its module root directory.
- .NET: path to a
-l, --language(optional): Force generator (dotnet,go). If omitted, order: flag β config β autodetect.-f, --dockerfile(optional): Output file name (defaultDockerfile).-d, --dry-run(optional): Generate to temp & print unified diff vs existing file (no write).-v, -V, --version(optional): Print version metadata.--verbose(optional): Enable debug logging (prints detection, config, and output path decisions to stderr; safe for piping stdout to files or other tools).
0β success1β validation or processing failure
dockerfile-gendockerfile-gen -p ./src/WebApi/WebApi.csprojdockerfile-gen --path ./src/WebApidockerfile-gen -p ./src/WebApi --language dotnetdockerfile-gen -p ./servicedockerfile-gen -p ./service -l go -f Dockerfile.servicedockerfile-gen -p ./service --verbosePlace .dockerbuild next to your .csproj or go.mod:
language: dotnet
dotnet:
sdk-version: "8.0"
base:
image: mcr.microsoft.com/dotnet/aspnet:9.0-alpine
packages:
- icu-data-full
base-build:
image: mcr.microsoft.com/dotnet/sdk:9.0-alpine
packages:
- gitThen:
dockerfile-gen -p ./src/WebApi/WebApi.csprojlanguage: dotnet|go # optional
dotnet: # dotnet-specific config (optional)
sdk-version: "9.0" # target .NET version (default: "9.0")
base:
image: <string> # runtime stage base image
packages: # apk packages (alpine-based images)
- pkg1
- pkg2
base-build:
image: <string> # build stage base image
packages:
- build-pkgMissing fields are ignored. language falls back to autodetect.
Go example:
language: go
base:
image: alpine:3.20
packages:
- ca-certificates
base-build:
image: golang:1.23-alpine
packages:
- build-baseStages (simplified):
baseβ runtime image (aspnet) + optional packagesbase_buildβ SDK image + optional packagesbuildβ copy project graph & context,dotnet restore, then copy source &dotnet buildpublishβdotnet publishfinalβ runtime image with published output
Supported build args:
TARGET_DOTNET_VERSION(default from configdotnet.sdk-versionor9.0if not specified)BUILD_CONFIGURATION(defaultRelease)APP_VERSION(default0.0.1)NuGetPackageSourceToken_gh(optional for private feed token injection)
To customize the target .NET version, set dotnet.sdk-version in your .dockerbuild file.
Stages:
buildβ (golang:-alpine or override) with module & build cachesfinalβ (alpine or override)
Build arg:
GO_VERSION(defaults in template to1.23unless overridden via base-build image)
Per project (root + referenced):
- Walk upward to repo root adding
Directory.Build.props&Directory.Packages.props. - Add first discovered
nuget.configonce globally. - Ensure unique copy entries (no duplicates).
Order of precedence:
--languageflag (if provided)- Config
languagein.dockerbuild - Heuristics (on
--pathor.default directory):- Path to
.csprojor directory with exactly one.csprojβdotnet - Directory/file containing
go.modβgo
- Path to
If both are present, whichever generator was registered first and detects successfully "wins" (current order: dotnet then go).
dockerfile-gen -vOutputs:
<binary> version <semver> (commit <short>, built <date>)
| Issue | Tip |
|---|---|
| Not detected | Pass -l explicitly. |
Multiple .csproj in directory |
Specify a single file path. |
| Permissions / user mismatch | Provide APP_UID in build args or remove USER $APP_UID line after generation. |
| Private NuGet feeds | Provide NuGetPackageSourceToken_gh build arg; adapt template if feed name differs. |
| Need more insight into what the tool is doing | Re-run with --verbose to see detection & config decisions. |
A Makefile is provided to streamline local workflows (linting, testing, releasing, Docker build, installation).
Common targets:
| Target | Description |
|---|---|
make lint |
Run golangci-lint (auto-installs pinned version into ./bin). |
make test |
Run tests with race detector + coverage profile. |
make coverage |
Run tests (if needed) and enforce coverage threshold (COVERAGE_MIN, default 60%). |
make build |
Build the CLI binary into ./bin/dockerfile-gen. |
make install |
Build (if needed) and install to ${PREFIX}/bin (default first GOPATH entry, e.g. ~/go/bin). |
make uninstall |
Remove previously installed binary from ${PREFIX}/bin. |
make snapshot |
Run GoReleaser in snapshot mode (no publish). |
make release |
Full GoReleaser release (requires tag + GITHUB_TOKEN). |
make docker |
Build a local Docker image dockerfile-gen:dev. |
make tidy |
Ensure go.mod / go.sum are tidy. |
make ci |
Run lint then test (approximate CI pipeline). |
make clean |
Remove build artifacts (bin/, dist/, coverage file). |
Environment overrides:
GOLANGCI_LINT_VERSIONto pin a different golangci-lint version.COVERAGE_MINto raise/lower the required coverage percentage.VERSIONfor custom build version (defaults todev).PREFIXinstall destination root (default first GOPATH entry).
Example:
make lint
make install # installs into $(go env GOPATH)/bin
make install PREFIX=$HOME/.local # alt location
make uninstall PREFIX=$HOME/.local # remove if neededEnsure $(go env GOPATH)/bin or PREFIX/bin is on your PATH.
Tip: Run
make helpto list available targets.
- Fork & clone
- Create a feature branch
- Add / update tests (future harness)
- Open a PR π
Planned: MIT (add LICENSE file). Feel free to use & adapt β but confirm license once added.
Generated Dockerfiles are a strong starting point β always review for security hardening (non-root users, pinned versions, SBOM, vuln scanning) before production deployment.
Made with β€οΈ for fast, reliable container builds.