Bitnami Secure Images (BSI) provides a secure, transparent, robust and reliable solution for deploying applications in containerized environments. By leveraging Bitnami Secure Images, developers and operations teams can deploy applications with confidence and transparency, knowing they are running on a secure, optimized, and well-maintained foundation and reducing NIST Accreditation time up to 80%.
Community-Tier public catalog
While production users should subscribe to Bitnami Secure Images for full version support, a limited community-tier subset of container images are publicly available at Docker Hub for development and trial for potential customer purposes.
Note: only the most recent ‘latest’ tags of the limited community-tier subset of container images are available
Base Images for Golang Apps
In this guide, we will make use of two images from the Bitnami Secure Images community-tier subset to build the containers for our Golang Apps:
-
bitnamisecure/golang: shipping latest Golang version, it’s ideal for building Golang binaries using multi-stage builds.
-
bitnamisecure/static: distroless container, designed to be minimal and secure, making it an ideal choice for running static binaries in a secure way.
A close look at the bitnamisecure/static filesystem reveals its minimal nature, shipped exclusively with:
-
Basic Linux folder structure: Essential system directories such as /var, /tmp, /lib, /usr, and /etc are maintained with correct permissions.
-
Non-root user/group: Adheres to security best practices by avoiding root privileges.
-
ca-certificates-pki: Includes Certificate Authorities for verifying the trustworthiness of services and applications.
-
tzdata: Provides time zone and daylight saving data for accurate time handling.
-
iana-etc: Necessary for network communication within Linux.
Using BSI images to build containers for Golang apps
By utilizing the images from the previous section as foundational elements, we can construct our minimal, distroless-based containers. This is achieved through multi-stage builds, as demonstrated in the Dockerfile provided below:
As the example illustrates, binaries are statically built (CGO_ENABLED=0) and FIPS 140-3 compliance is enabled (GOFIPS140=latest). Additionally, the final image ensures that our Golang applications will generate an error or panic if cryptographic algorithms not compliant with FIPS 140-3 are utilized (GODEBUG=fips140=only).
Golang Apps Examples
Let’s explore the advantage of using this approach to build container images with a couple of Golang apps examples.
FIPS compliant algorithms
We can build a sample application to test that actually non-FIPS compliant cryptographic algorithms like the one below:
package main
import (
"crypto/fips140"
"crypto/md5"
"crypto/sha256"
"fmt"
)
func main() {
data := []byte("hello world")
fmt.Printf("Generating hash for 'hello world'. FIPS mode is %t\n", fips140.Enabled())
// Try a non-FIPS-approved algorithm (MD5)
fmt.Println("Trying MD5...")
if err := panicSandbox(func() {
fmt.Printf("MD5 OK: %x\n", md5.Sum(data))
}); err != nil {
fmt.Println(err)
}
// Try a FIPS-approved algorithm (SHA-256)
fmt.Println("Trying SHA-256...")
if err := panicSandbox(func() {
fmt.Printf("SHA-256 OK: %x\n", sha256.Sum256(data))
}); err != nil {
fmt.Println(err)
}
}
// panicSandbox wraps a function call in a recover block to
// handle panics that may occur during its execution
func panicSandbox(f func()) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic recovered: %v", r)
}
}()
f()
return nil
}
Using the multi-stage Dockerfile, we could build and run a container image to ship our sample application. As we can see, FIPS compliance is enforced:
$ docker build -t myapp:latest .
$ docker run --rm myapp:latest
Generating hash for 'hello world'. FIPS mode is true
Trying MD5...
panic recovered: crypto/md5: use of MD5 is not allowed in FIPS 140-only mode
Trying SHA-256...
SHA-256 OK: b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
The resulting image is very small (10.8MB, compressed is <2MB) and has no reported vulnerabilities:
$ docker images myapp --format "{{.Repository}}:{{.Tag}}\t{{.Size}}"
myapp:latest 10.8MB
$ trivy image -q myapp
myapp (photon 5.0)
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
Using ca-certificates and tzdata
Now, let’s see an example application that makes use of time zone data and CA certificates to make a request to Google and validate the trustworthiness of the response:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"time"
)
func main() {
certPool, err := x509.SystemCertPool()
if err != nil {
fmt.Println("Failed to get system cert pool:", err)
return
}
loc, err := time.LoadLocation("America/New_York")
if err != nil {
fmt.Println("Failed to load timezone:", err)
return
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
// use the system CA certificates
RootCAs: certPool,
// Use FIPS-approved algorithms
// for elliptic curve operation
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{
tls.CurveP256,
tls.CurveP384,
tls.CurveP521,
},
},
},
}
fmt.Printf("Performing HTTPS request to Google at %s\n", time.Now().In(loc))
resp, err := client.Get("https://google.com")
if err != nil {
fmt.Println("Request failed:", err)
return
}
defer resp.Body.Close()
fmt.Println("Request succeeded with status code:", resp.StatusCode)
}
Using again the same Dockerfile, we can ship our app and test it:
$ docker build -t myapp:latest .
$ docker run --rm myapp:latest
Performing HTTPS request to Google at 2025-08-18 06:43:57.454487835 -0400 EDT
Request succeeded with status code: 200
We could try replacing bitnamisecure/static:latest image by scratch as the base image:
--- FROM bitnamisecure/static:latest
+++ FROM scratch
However, our application would not work given there’s no time zone data:
$ docker run --rm myapp:scratch
Failed to load timezone: unknown time zone America/New_York
Even if we simplify our app and stop using time zone data, the container execution fails given there are no CA certs:
$ docker run --rm myapp:scratch-no-tz
Performing HTTPS request to Google
Request failed: Get "https://google.com": tls: failed to verify certificate: x509: certificate signed by unknown authority
Conclusions
This guide has demonstrated the significant advantages of using Bitnami Secure Images as a base for Golang applications. When combined with multi-stage builds, developers can create containers that are extremely minimal, secure, and FIPS 140-3 compliant.
Contact us now and begin leveraging the advantages of Bitnami Secure Images.