Docker Policy Examples

Apcera provides a Docker-specific policy claim for whitelisting Docker images that can be used to create jobs and packages. You can write policy that restricts Docker image availability by registry location (Docker Hub or a private Quay registry, for example), image repository ("apcerademos", e.g.), and image name and version tag ("nats:latest" or "mysql:5.7.14", e.g.).

Note that Docker policy is always written against the job:: realm, regardless of whether you are creating an application from a Docker image (with apc docker run) or just creating a package from an image (with apc docker pull), as explained below.

Docker image whitelisting

To create an application or package from a Docker image you must define a docker.allow claim on the job:: realm of the target app or package resource. Without docker.allow policy, you cannot deploy Docker jobs or create Docker packages in the system.

Whitelisting for app creation

To create an application from a Docker image using apc docker run <app-name> (or equivalent Web Console menu) policy must be defined that allows access to the specified Docker image in the target namespace or at the target FQN. For example, in the following example the authenticated user does not have the necessary policy permissions to create an app in the current namespace from the latest NATS Docker image:

apc docker run nats1 --image nats:latest --restart always
Error: Docker image "https://registry-1.docker.io/library/nats:latest" not allowed by policy:
missing claim "docker.allow \"https://registry-1.docker.io/library/nats:latest\""
on "job::/sandbox/user::nats1"

As the error message indicates, you must add policy that allows job::/sandbox/user::nats1 to pull the latest NATS image from Docker Hub, as shown below:

job::/sandbox/user::nats1 {
  { docker.allow "https://registry-1.docker.io/nats:latest" }
}

Also see Global and fine-grained whitelisting.

Whitelisting for package creation

The apc docker pull <package-name> command creates a new package from a Docker image. When you run this command Apcera checks if the specified Docker image would be allowed to run as a "hypothetical" job in the same namespace. For example, if the package being created is package::/namespace/pkg::mypackage then the cluster checks job::/namespace/pkg for the necessary docker.allow policy. Note that only the namespace is checked for policy compliance, not including the resource's local name.

For example, consider the following apc docker pull command that fails because the proper policy is not in place:

apc docker pull /mypackages/docker::nats-pkg --image nats:0.9.4
[nats-pkg] -- Pulling Docker image -- checking policy
[error] -- Docker image "https://registry-1.docker.io/library/nats:0.9.4" not allowed by policy: 
missing claim "docker.allow \"https://registry-1.docker.io/library/nats:0.9.4\"" 
on "job::/mypackages/docker::nats-pkg"

The following policy on the job:: realm fixes this error by allowing the authenticated user to pull any tagged version of the NATS image:

job::/mypackages/docker {
  { docker.allow "https://registry-1.docker.io/library/nats" }
}

Note: Despite the wording of the "missing claim" error message shown previously, it's recommended that Docker policy for creating packages be written against the "hypothetical" job's namespace (job::/mypackages/docker) as shown above, rather than it's fully-qualified name (job::/mypackages/docker::nats-pkg) (as the error states).

Global and fine-grained whitelisting

The following policy grants Docker job deployment and package creation globally across the cluster:

job::/ {
  { docker.allow "*" }
}

However, you can also use docker.allow for more fine-grained control over what Docker images can be pulled and deployed to the system. For example, the following policy explicitly allows the mybin/redis Docker image:

job::/sandbox/user {
  { docker.allow "https://registry-1.docker.io/mybin/redis" }
}

The following policy explicitly allows the mybin/redis Docker image (any tagged version) and the nats image, the latter only with the latest tag:

job::/sandbox/user {
  { docker.allow "https://registry-1.docker.io/mybin/redis", "https://registry-1.docker.io/nats:latest" }
}

Note that the policy is permissive from left to right. For example, the following policy would allow any image from Docker Hub:

job::/sandbox/user {
  { docker.allow "https://registry-1.docker.io" }
}

In comparison, the following policy would only allow images from Docker Hub in the /mybin repository.

job::/sandbox/user {
  { docker.allow "https://registry-1.docker.io/mybin" }
}

See also Docker whitelisting.