Auto-update pinned APK package versions in Dockerfiles using Renovate.
The problem: Working with Wolfi or Alpine containers? You pin APK packages for reproducibility — apk add curl=8.11.1-r0 — but Renovate can't auto-update them. It has no built-in APK datasource. This tool fills that gap. See renovatebot/renovate#5422 for context.
- Automated updates — Stop manually tracking APK package versions
- Reproducible builds — Pin exact versions while staying current
- Works with Renovate — Integrates with your existing dependency management workflow
- No server required — Use the public hosted index, or deploy your own (Docker, Helm, GitLab CI, or binary)
- Supports Wolfi & Alpine — Works with both Chainguard Wolfi and Alpine Linux indexes
A public index for Wolfi x86_64 and aarch64 packages is hosted on GitHub Pages and refreshed every 4 hours. Point your Renovate config directly at it — no server to run:
https://cwaits6.github.io/apk-datasource/x86_64/{{packageName}}.json
(Replace {{packageName}} with an actual package name, e.g., curl)
Test it: Fetch the datasource for a package to see the available versions:
curl -s https://cwaits6.github.io/apk-datasource/x86_64/curl.json | jq .Replace curl with any APK package name to test others (e.g., go, git, busybox).
Add the following customDatasources and customManagers blocks to your existing renovate.json. Renovate will start opening PRs to update pinned APK versions (e.g. curl=8.15.0-r2 -> curl=8.19.0-r1):
{
"customDatasources": {
"apk-wolfi": {
"defaultRegistryUrlTemplate": "https://cwaits6.github.io/apk-datasource/x86_64/{{packageName}}.json",
"format": "json"
}
},
"customManagers": [
{
"customType": "regex",
"fileMatch": ["(^|/)Dockerfile[^/]*$"],
"matchStringsStrategy": "recursive",
"matchStrings": [
"apk\\s+add[^\\n\\\\]*(?:\\\\[^\\S\\n]*\\n[^\\n\\\\]*)*",
"(?<depName>[a-zA-Z0-9][a-zA-Z0-9._+-]*)=(?<currentValue>\\d+[^\\s\\\\]+)"
],
"datasourceTemplate": "custom.apk-wolfi",
"versioningTemplate": "loose"
}
]
}Want to self-host instead? See Deployment for Docker, Helm, GitLab CI, or binary options. Replace the defaultRegistryUrlTemplate URL with your server address (e.g. https://apk.example.com/x86_64/{{packageName}}.json)
Download a pre-built binary from GitHub Releases, or install from source:
go install github.com/cwaits6/apk-datasource/cmd/apk-datasource@latestapk-datasource generate --output-dir ./outputapk-datasource serveBoth commands default to the Chainguard Wolfi index for x86_64 and aarch64. Override with --index-url for other indexes (see Available Indexes).
docker compose -f deploy/docker/docker-compose.yml up -dThe server runs on port 3000 with a 4-hour refresh interval. Edit deploy/docker/docker-compose.yml to customize settings.
helm install apk-datasource ./charts/apk-datasourceSee charts/apk-datasource/ for all configurable values.
| Command | Description |
|---|---|
apk-datasource generate |
Fetch indexes and write JSON files to disk |
apk-datasource serve |
Serve JSON over HTTP with periodic refresh |
apk-datasource version |
Print version info |
| Flag | Default | Description |
|---|---|---|
--log-level |
info |
Log level (debug, info, warn, error) |
--log-format |
text |
Log format (text, json) |
| Flag | Default | Description |
|---|---|---|
--index-url |
Chainguard Wolfi x86_64 + aarch64 | APKINDEX.tar.gz URL (repeatable) |
--output-dir |
./output |
Output directory |
--source-url |
(auto-detect) | Override source URL |
--homepage |
(from index) | Override homepage |
| Flag | Default | Description |
|---|---|---|
--index-url |
Chainguard Wolfi x86_64 + aarch64 | APKINDEX.tar.gz URL (repeatable) |
--port |
3000 |
HTTP port |
--refresh-interval |
4h |
Refresh interval |
--source-url |
(auto-detect) | Override source URL |
--homepage |
(from index) | Override homepage |
--metrics |
true |
Enable Prometheus metrics on /metrics |
When --metrics is enabled (the default), the server exposes a Prometheus-compatible /metrics endpoint on the same port. Available metrics:
| Metric | Type | Labels | Description |
|---|---|---|---|
http_requests_total |
Counter | method, path, status_code | Total HTTP requests |
http_request_duration_seconds |
Histogram | method, path, status_code | Request latency |
refresh_total |
Counter | status | Index refresh attempts |
refresh_duration_seconds |
Histogram | status | Refresh latency |
refresh_packages |
Gauge | — | Package count after last refresh |
server_ready |
Gauge | — | Server readiness (0/1) |
Scrape with Prometheus:
scrape_configs:
- job_name: apk-datasource
static_configs:
- targets: ["localhost:3000"]The Helm chart adds prometheus.io/* annotations automatically when metrics.enabled is true.
The --index-url flag accepts any APKINDEX.tar.gz URL. Below are the most common public indexes:
| Architecture | URL |
|---|---|
| x86_64 | https://apk.cgr.dev/chainguard/x86_64/APKINDEX.tar.gz |
| aarch64 | https://apk.cgr.dev/chainguard/aarch64/APKINDEX.tar.gz |
Replace v3.23 with your target version, or use edge for rolling.
| Repository | Architecture | URL |
|---|---|---|
| main | x86_64 | https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/APKINDEX.tar.gz |
| main | aarch64 | https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/APKINDEX.tar.gz |
| community | x86_64 | https://dl-cdn.alpinelinux.org/alpine/v3.23/community/x86_64/APKINDEX.tar.gz |
| community | aarch64 | https://dl-cdn.alpinelinux.org/alpine/v3.23/community/aarch64/APKINDEX.tar.gz |
Alpine also supports armv7, ppc64le, s390x, and riscv64 architectures.
Example — serve Alpine main + community:
apk-datasource serve \
--index-url https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/APKINDEX.tar.gz \
--index-url https://dl-cdn.alpinelinux.org/alpine/v3.23/community/x86_64/APKINDEX.tar.gzapk-datasource fetches APKINDEX.tar.gz archives from Wolfi or Alpine repositories, parses the package metadata, and outputs one JSON file per package conforming to Renovate's custom datasource schema:
{
"releases": [
{ "version": "8.11.1-r0" }
],
"sourceUrl": "https://github.com/wolfi-dev/os",
"homepage": "https://curl.se"
}Two modes: generate writes static JSON files to disk, serve runs an HTTP server with periodic refresh.
- Fork the repo
- Create a feature branch
- Submit a pull request