Skip to content

Commit 0ffaa6c

Browse files
committed
daemon: add annotations to container HostConfig
Allow clients to set annotations on a container which will applied to the container's OCI spec. Signed-off-by: Cory Snider <[email protected]>
1 parent 50d7164 commit 0ffaa6c

9 files changed

Lines changed: 66 additions & 11 deletions

File tree

api/server/router/container/container_routes.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,11 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
563563
hostConfig.ConsoleSize = [2]uint{0, 0}
564564
}
565565

566+
if hostConfig != nil && versions.LessThan(version, "1.43") {
567+
// Ignore Annotations because it was added in API v1.43.
568+
hostConfig.Annotations = nil
569+
}
570+
566571
var platform *specs.Platform
567572
if versions.GreaterThanOrEqualTo(version, "1.41") {
568573
if v := r.Form.Get("platform"); v != "" {

api/types/container/hostconfig.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -377,16 +377,17 @@ type UpdateConfig struct {
377377
// Portable information *should* appear in Config.
378378
type HostConfig struct {
379379
// Applicable to all platforms
380-
Binds []string // List of volume bindings for this container
381-
ContainerIDFile string // File (path) where the containerId is written
382-
LogConfig LogConfig // Configuration of the logs for this container
383-
NetworkMode NetworkMode // Network mode to use for the container
384-
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
385-
RestartPolicy RestartPolicy // Restart policy to be used for the container
386-
AutoRemove bool // Automatically remove container when it exits
387-
VolumeDriver string // Name of the volume driver used to mount volumes
388-
VolumesFrom []string // List of volumes to take from other container
389-
ConsoleSize [2]uint // Initial console size (height,width)
380+
Binds []string // List of volume bindings for this container
381+
ContainerIDFile string // File (path) where the containerId is written
382+
LogConfig LogConfig // Configuration of the logs for this container
383+
NetworkMode NetworkMode // Network mode to use for the container
384+
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
385+
RestartPolicy RestartPolicy // Restart policy to be used for the container
386+
AutoRemove bool // Automatically remove container when it exits
387+
VolumeDriver string // Name of the volume driver used to mount volumes
388+
VolumesFrom []string // List of volumes to take from other container
389+
ConsoleSize [2]uint // Initial console size (height,width)
390+
Annotations map[string]string `json:",omitempty"` // Arbitrary non-identifying metadata attached to container and provided to the runtime
390391

391392
// Applicable to UNIX platforms
392393
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container

daemon/container.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ func validateHostConfig(hostConfig *containertypes.HostConfig) error {
305305
if !hostConfig.Isolation.IsValid() {
306306
return errors.Errorf("invalid isolation '%s' on %s", hostConfig.Isolation, runtime.GOOS)
307307
}
308+
for k := range hostConfig.Annotations {
309+
if k == "" {
310+
return errors.Errorf("invalid Annotations: the empty string is not permitted as an annotation key")
311+
}
312+
}
308313
return nil
309314
}
310315

daemon/oci_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@ func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (r
10261026
WithApparmor(c),
10271027
WithSelinux(c),
10281028
WithOOMScore(&c.HostConfig.OomScoreAdj),
1029+
coci.WithAnnotations(c.HostConfig.Annotations),
10291030
)
10301031
if daemon.UsesSnapshotter() {
10311032
s.Root = &specs.Root{

daemon/oci_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"path/filepath"
99
"strings"
1010

11+
coci "github.com/containerd/containerd/oci"
1112
containertypes "github.com/docker/docker/api/types/container"
1213
imagetypes "github.com/docker/docker/api/types/image"
1314
"github.com/docker/docker/container"
@@ -37,6 +38,10 @@ func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (*
3738

3839
s := oci.DefaultSpec()
3940

41+
if err := coci.WithAnnotations(c.HostConfig.Annotations)(ctx, nil, nil, &s); err != nil {
42+
return nil, err
43+
}
44+
4045
linkedEnv, err := daemon.setupLinkedContainers(c)
4146
if err != nil {
4247
return nil, err

docs/api/v1.43.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,13 @@ definitions:
976976
items:
977977
type: "integer"
978978
minimum: 0
979+
Annotations:
980+
type: "object"
981+
description: |
982+
Arbitrary non-identifying metadata attached to container and
983+
provided to the runtime when the container is started.
984+
additionalProperties:
985+
type: "string"
979986

980987
# Applicable to UNIX platforms
981988
CapAdd:

docs/api/version-history.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ keywords: "API, Docker, rcli, REST, documentation"
1717

1818
[Docker Engine API v1.43](https://docs.docker.com/engine/api/v1.43/) documentation
1919

20-
* TODO add API changes for v1.43 here when they arrive.
20+
* `POST /containers/create` now accepts `Annotations` as part of `HostConfig`.
21+
Can be used to attach arbitrary metadata to the container, which will also be
22+
passed to the runtime when the container is started.
2123

2224
## v1.42 API changes
2325

integration/container/create_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,11 @@ func TestCreateInvalidHostConfig(t *testing.T) {
561561
hc: containertypes.HostConfig{UTSMode: "invalid"},
562562
expectedErr: "Error response from daemon: invalid UTS mode: invalid",
563563
},
564+
{
565+
doc: "invalid Annotations",
566+
hc: containertypes.HostConfig{Annotations: map[string]string{"": "a"}},
567+
expectedErr: "Error response from daemon: invalid Annotations: the empty string is not permitted as an annotation key",
568+
},
564569
}
565570

566571
for _, tc := range testCases {

integration/container/inspect_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,27 @@ func TestInspectCpusetInConfigPre120(t *testing.T) {
4747
_, ok = cfg["Cpuset"]
4848
assert.Check(t, is.Equal(true, ok), "API version 1.19 expected to include Cpuset in 'Config'")
4949
}
50+
51+
func TestInspectAnnotations(t *testing.T) {
52+
defer setupTest(t)()
53+
client := request.NewAPIClient(t)
54+
ctx := context.Background()
55+
56+
annotations := map[string]string{
57+
"hello": "world",
58+
"foo": "bar",
59+
}
60+
61+
name := strings.ToLower(t.Name())
62+
id := container.Create(ctx, t, client,
63+
container.WithName(name),
64+
container.WithCmd("true"),
65+
func(c *container.TestContainerConfig) {
66+
c.HostConfig.Annotations = annotations
67+
},
68+
)
69+
70+
inspect, err := client.ContainerInspect(ctx, id)
71+
assert.NilError(t, err)
72+
assert.Check(t, is.DeepEqual(inspect.HostConfig.Annotations, annotations))
73+
}

0 commit comments

Comments
 (0)