Skip to main content

Command Palette

Search for a command to run...

How to Ensure Your Docker & Harbor Machine Images Are Secure

Published
4 min read

Securing your machine images—whether built with Docker or stored in Harbor—is critical to protecting your infrastructure from attacks, vulnerabilities, and supply-chain risks. This guide covers best practices across the entire lifecycle: image creation, scanning, registry security, and runtime protection.

1. Secure Your Docker Image Build Process

Use Minimal Base Images

Choose images with the smallest attack surface:

  • alpine

  • distroless

  • scratch

Avoid large OS images unless absolutely necessary.

Pin Base Image Versions

Never use latest.
Use explicit versions:

FROM python:3.11.6-alpine

This ensures your image builds are deterministic and secure.

Image Source: Docker Blog – © Docker Inc.
Original article: https://www.docker.com/blog/docker-for-node-js-developers-5-things-you-need-to-know-not-to-fail-your-security/

Avoid Secrets in Images

Do not bake sensitive data into Docker images:

  • No API keys

  • No SSH keys

  • No passwords

Use:

  • environment variables

  • Docker secrets

  • external secret managers (Vault, AWS Secrets Manager, etc.)

Use Multi-Stage Builds

Multi-stage builds remove build-time tools and reduce image size:

FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o app

FROM alpine
COPY --from=builder /app/app /usr/local/bin/app
ENTRYPOINT ["app"]

Run as a Non-Root User

Always drop root privileges:

USER appuser

This prevents privilege escalation attacks.

Prefer Distroless Images

Distroless images contain:

  • no shell

  • no package manager

  • no unnecessary binaries

This dramatically reduces vulnerabilities.

Example:

FROM gcr.io/distroless/python3

Use SBOM (Software Bill of Materials)

Generate an SBOM to track everything inside your image:

syft myimage:1.0 -o cyclonedx-json > sbom.json

SBOMs are essential for supply-chain security.


2. Scan Images with Security Tools

Use vulnerability scanners before pushing.

trivy image myimage:1.0

Docker Scan (Snyk):

docker scan myimage:1.0

Always scan:

  • during local development

  • in CI/CD

  • after pushing to Harbor


3. Use Harbor’s Security Features

Harbor is one of the most secure container registries available. Use its full capabilities.

Enable Vulnerability Scanning

Harbor integrates with:

  • Trivy

  • Clair

Enable:

  • automatic scans on push

  • scheduled periodic scans

Harbor will show:

  • vulnerabilities

  • severity levels

  • fix availability

Block Pulling Vulnerable Images

Enable policy:

“Prevent images with severity ≥ High from being pulled”

This ensures only safe images can be deployed.

Use Image Tag Immutability

Prevent someone from overwriting critical tags (like prod or latest).

In Harbor UI:

Project → Tag Rules → Enable Tag Immutability

This prevents tampering.

Enable Content Signing (Notary)

Use Docker Content Trust or Notary v2:

export DOCKER_CONTENT_TRUST=1
docker push harbor.mycompany.com/app:1.0

Only signed images can be pulled.

RBAC & Access Controls

Use Harbor’s RBAC model:

  • Developers → push-only

  • Ops → pull-only

  • Admin → manage settings

Never allow anonymous pushes.

Enable HTTPS Everywhere

Secure Harbor registry endpoints to prevent MITM attacks.


4. Secure Kubernetes Runtime (Where Your Images Run)

Even if images are secure, your Kubernetes cluster must enforce security policies.

Require Images From Harbor Only

Use Kyverno:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-harbor-images
spec:
  validationFailureAction: enforce
  rules:
  - name: only-harbor
    match:
      resources:
        kinds: ["Pod"]
    validate:
      message: "Only Harbor images are allowed."
      pattern:
        spec:
          containers:
          - image: "harbor.mycompany.com/*"

Block Running as Root

spec:
  rules:
  - name: no-root
    match:
      resources:
        kinds: ["Pod"]
    validate:
      pattern:
        spec:
          containers:
          - securityContext:
              runAsNonRoot: true

Require Signed Images Only

If using Cosign/Notary:

cosign sign harbor.mycompany.com/app:1.0

Admission controllers block unsigned images.

Runtime Threat Detection

Tools like:

  • Falco

  • Sysdig

  • eBPF-based detection

These monitor containers for:

  • unexpected shell access

  • suspicious syscalls

  • privilege escalation attempts


5. CI/CD Pipeline Enforcement

Security must be automated.

Your CI/CD pipeline should:

  1. Lint Dockerfile

  2. Build image

  3. Scan with Trivy

  4. Generate SBOM

  5. Sign image

  6. Push to Harbor

  7. Harbor rescans

  8. Deployment allowed only if image passes

This enforces organization-wide standards.


6. Organizational Security Practices

Use Internal Golden Base Images

Store internal, hardened base images in Harbor:

base-images/

Update them regularly.

Image Retention & Cleanup

Automatically remove:

  • unused images

  • untagged layers

  • images with unfixable CVEs

Harbor supports retention policies.

Audit Logging

Harbor provides logs for:

  • pull/push events

  • tag changes

  • user actions

Use logs for compliance and detection.


7. End-to-End Secure Image Lifecycle (Summary)

1. Developer Stage

  • Uses secure base images

  • Scans locally

  • No secrets in Dockerfile

2. CI/CD Stage

  • Build → Scan → SBOM → Sign → Push

3. Harbor Stage

  • Auto scanning

  • Tag immutability

  • Signed images enforced

4. Kubernetes Stage

  • Only Harbor images

  • Only signed images

  • No root containers

5. Runtime

  • eBPF/Falco monitoring

This creates a fully secure container image supply chain.


Conclusion

Securing Docker and Harbor images requires a layered approach:

  • building secure images

  • enforcing security in Harbor

  • applying strict Kubernetes policies

  • monitoring containers at runtime

By following this guide, you ensure every part of the image lifecycle is protected—from creation to deployment.