Published: Apr 16, 2025 by Isaac Johnson
At GCP Next25 I had a great visit with the folks at Chainguard.dev about controlled images. I went to the site a few times (forgetting it ends in dev and getting chain oil).
I decided to try it myself at home.
Setup
Let’s start with their website where we can see a general overview of their offering
They have some libraries and VMs but their initial offering was containers
They have a free tier so let us go to the login/signup page to set that up
I’ll continue with Google for now
I can now see starter images and production images
I searched for Ubuntu and Debian, but no luck.
However, I could find Nginx
Which was available to pull without any auth
$ docker pull cgr.dev/chainguard/nginx
Using default tag: latest
latest: Pulling from chainguard/nginx
306265d7891f: Pull complete
Digest: sha256:23355889c10aa4e960ab8e66f1ba2024bc20ba2bcd87676a6f009329ee969e76
Status: Downloaded newer image for cgr.dev/chainguard/nginx:latest
cgr.dev/chainguard/nginx:latest
However, when I tried to run it
$ docker run -p 8088:80 cgr.dev/chainguard/nginx
2025/04/16 23:52:00 [warn] 1#1: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:2
2025/04/16 23:52:00 [notice] 1#1: using the "epoll" event method
2025/04/16 23:52:00 [notice] 1#1: nginx/1.27.4
2025/04/16 23:52:00 [notice] 1#1: built by gcc 14.2.0 (Wolfi 14.2.0-r11)
2025/04/16 23:52:00 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025/04/16 23:52:00 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/04/16 23:52:00 [notice] 1#1: start worker processes
2025/04/16 23:52:00 [notice] 1#1: start worker process 7
2025/04/16 23:52:00 [notice] 1#1: start worker process 8
2025/04/16 23:52:00 [notice] 1#1: start worker process 9
2025/04/16 23:52:00 [notice] 1#1: start worker process 10
2025/04/16 23:52:00 [notice] 1#1: start worker process 11
2025/04/16 23:52:00 [notice] 1#1: start worker process 12
2025/04/16 23:52:00 [notice] 1#1: start worker process 13
2025/04/16 23:52:00 [notice] 1#1: start worker process 14
2025/04/16 23:52:00 [notice] 1#1: start worker process 15
2025/04/16 23:52:00 [notice] 1#1: start worker process 16
2025/04/16 23:52:00 [notice] 1#1: start worker process 17
2025/04/16 23:52:00 [notice] 1#1: start worker process 18
2025/04/16 23:52:00 [notice] 1#1: start worker process 19
2025/04/16 23:52:00 [notice] 1#1: start worker process 20
2025/04/16 23:52:00 [notice] 1#1: start worker process 21
2025/04/16 23:52:00 [notice] 1#1: start worker process 22
Or I can run it as a daemon
$ docker run -it --rm -d -p 8080:80 --name web cgr.dev/chainguard/nginx
dec0d3ee644f6b04f7c66f5cacf0cf7acc14137dc56e64b2ce25674c83a82026
But neither seemed to load a page
I tried pulling the standard Nginx which worked
Another annoyance is that everytime I would attempt to get to Production images, it would pop up and sign me out
I then made an organization
and tried to pull another web server, which is in the “Public Images” category
Only, it would fail each time
$ docker pull cgr.dev/chainguard/httpd:latest
Error response from daemon: Head "https://cgr.dev/v2/chainguard/httpd/manifests/latest": denied: {"errors":[{"code":"FORBIDDEN","message":"Forbidden"}]}
$ docker pull cgr.dev/freshbrewed.science/httpd:latest
Error response from daemon: Head "https://cgr.dev/v2/freshbrewed.science/httpd/manifests/latest": unknown: {"errors":[{"code":"BAD_REQUEST","message":"rpc error: code = InvalidArgument desc = unable to map \"freshbrewed.science\" to organization UIDP"}]}
$ docker pull cgr.dev/cf11426260ceb2179197746ac9292ef83efed20c/httpd:latest
Error response from daemon: Head "https://cgr.dev/v2/cf11426260ceb2179197746ac9292ef83efed20c/httpd/manifests/latest": denied: {"errors":[{"code":"FORBIDDEN","message":"Forbidden"}]}
It could be that “Production” images are just locked out, regardless of public as there is a “Contact us” section in the org settings
However, in the Chainguard featured starter images, httpd
is clearly listed
It was a bit nutty as you can see
Bitnami
I didn’t want to end on a fail. For years I’ve trusted the “Bitnami” images without really pausing to think about what they are or from where they come.
It started all the way back in 2003 as Bitrock (Bitrock.com just redirects to some installer software now). But we can see the wayback archive cached page to learn about their history or see their site around 2019 before VMware bought them for their “Bitnami” images.
VMWare rolled Bitnami into it’s Tanzu Application Catalog and I have no idea if Tanzu will still be a thing now that Broadcom bought VMWare.
However, at least for now we can browse the catalog for images
For instance, I can search for Nginx
Then see the details for the latest builds
The details won’t actually point to a specific Registry, just “REGISTRY_NAME”
docker run --name nginx REGISTRY_NAME/bitnami/nginx:latest
However, everyone knows they have them on Dockerhub
I even clicked the link to see how much the “Arrow” premium images would be, but it’s just a basic info form for sales calls
Let’s pull the Bitnami Nginx image from Dockerhub
$ docker pull bitnami/nginx:latest
latest: Pulling from bitnami/nginx
982ba1bc1cda: Pull complete
Digest: sha256:fe7f74b7f12b2bf9537a052fd85cadd59b4fb4f343ec4403156443c0f9ff0164
Status: Downloaded newer image for bitnami/nginx:latest
docker.io/bitnami/nginx:latest
I gave that a quick run
$ docker run -it --rm -d -p 8080:80 --name bitnamiweb bitnami/nginx:latest
87c214be343571716a385801a1506db792c4cad1372c3c8e1ad4a5806b41c80a
and it worked great
I’m curious how different these images are with regards to CVEs.
I tagged and pushed all three to my Harbor CR
$ docker tag bitnami/nginx:latest harbor.freshbrewed.science/freshbrewed
private/nginx:bitnami
$ docker push harbor.freshbrewed.science/freshbrewedprivate/nginx:bitnami
The push refers to repository [harbor.freshbrewed.science/freshbrewedprivate/nginx]
be83ddbff14f: Pushed
bitnami: digest: sha256:8dbd774baad9ea46c8e47e3ace2847e04ac48ddab00f6a851505064e8aa1df00 size: 529
$ docker tag nginx harbor.freshbrewed.science/freshbrewedprivate/nginx:base
$ docker push harbor.freshbrewed.science/freshbrewedprivate/nginx:base
The push refers to repository [harbor.freshbrewed.science/freshbrewedprivate/nginx]
33e3df466e11: Pushed
747b7a567071: Pushed
57d3fc88cb3f: Pushed
53ae81198b64: Pushed
58354abe5f0e: Pushed
ad6562704f37: Pushed
base: digest: sha256:25dedae0aceb6b4fe5837a0acbacc6580453717f126a095aa05a3c6fcea14dd4 size: 1570
$ docker tag cgr.dev/chainguard/nginx:latest harbor.freshbrewed.science/freshbrewedprivate/nginx:chainguard
$ docker push harbor.freshbrewed.science/freshbrewedprivate/nginx:chainguard
The push refers to repository [harbor.freshbrewed.science/freshbrewedprivate/nginx]
edac844f9a32: Pushed
chainguard: digest: sha256:535a9096879b16026b288f93f3fcec8d14803c738fe8c1711e5f0b795a22f9e4 size: 528
I have to say, at the very least Chainguard kept it’s word with no CVEs
However, I’m not sure that means much when it doesnt really work, nor can i exec to chck into why
Pricing
Pricing is not public and while I now have general guidance from them in sales, I’m not sure it was intended to be public.
I’ll simply say it’s in the Enterprise category of pricing.
Summary
For now, I’ll have to put Chainguard on the back burner. I was hoping I might find a good site for secure images, but so far they aren’t working.
The website redirects, broken links and Org issues have me thinking it needs some more time to percolate before I come back for more.