diff --git a/pkg/cmd/container/create.go b/pkg/cmd/container/create.go index 77b5656e098..0cd0bfceb91 100644 --- a/pkg/cmd/container/create.go +++ b/pkg/cmd/container/create.go @@ -222,6 +222,7 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa return nil, generateRemoveStateDirFunc(ctx, id, internalLabels), err } internalLabels.logURI = logConfig.LogURI + internalLabels.logConfig = logConfig restartOpts, err := generateRestartOpts(ctx, client, options.Restart, logConfig.LogURI, options.InRun) if err != nil { @@ -641,7 +642,8 @@ type internalLabels struct { // log logURI string // a label to check whether the --rm option is specified. - rm string + rm string + logConfig logging.LogConfig } // WithInternalLabels sets the internal labels for a container. @@ -672,6 +674,11 @@ func withInternalLabels(internalLabels internalLabels) (containerd.NewContainerO } if internalLabels.logURI != "" { m[labels.LogURI] = internalLabels.logURI + logConfigJSON, err := json.Marshal(internalLabels.logConfig) + if err != nil { + return nil, err + } + m[labels.LogConfig] = string(logConfigJSON) } if len(internalLabels.anonVolumes) > 0 { anonVolumeJSON, err := json.Marshal(internalLabels.anonVolumes) diff --git a/pkg/inspecttypes/dockercompat/dockercompat.go b/pkg/inspecttypes/dockercompat/dockercompat.go index aceec3bca3d..79c9c57224c 100644 --- a/pkg/inspecttypes/dockercompat/dockercompat.go +++ b/pkg/inspecttypes/dockercompat/dockercompat.go @@ -46,6 +46,7 @@ import ( "github.com/containerd/nerdctl/v2/pkg/imgutil" "github.com/containerd/nerdctl/v2/pkg/inspecttypes/native" "github.com/containerd/nerdctl/v2/pkg/labels" + "github.com/containerd/nerdctl/v2/pkg/logging" "github.com/containerd/nerdctl/v2/pkg/ocihook/state" ) @@ -94,6 +95,11 @@ type ImageMetadata struct { LastTagTime time.Time `json:",omitempty"` } +type LogConfig struct { + Type string + Config logging.LogConfig +} + // Container mimics a `docker container inspect` object. // From https://github.com/moby/moby/blob/v20.10.1/api/types/types.go#L340-L374 type Container struct { @@ -116,7 +122,7 @@ type Container struct { // TODO: ProcessLabel string AppArmorProfile string // TODO: ExecIDs []string - // TODO: HostConfig *container.HostConfig + HostConfig *HostConfig // TODO: GraphDriver GraphDriverData SizeRw *int64 `json:",omitempty"` SizeRootFs *int64 `json:",omitempty"` @@ -126,6 +132,15 @@ type Container struct { NetworkSettings *NetworkSettings } +// From https://github.com/moby/moby/blob/8dbd90ec00daa26dc45d7da2431c965dec99e8b4/api/types/container/host_config.go#L391 +// HostConfig the non-portable Config structure of a container. +type HostConfig struct { + ExtraHosts []string // List of extra hosts + PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host + LogConfig LogConfig // Configuration of the logs for this container + +} + // From https://github.com/moby/moby/blob/v20.10.1/api/types/types.go#L416-L427 // MountPoint represents a mount point configuration inside the container. // This is used for reporting the mountpoints in use by a container. @@ -282,6 +297,32 @@ func ContainerFromNative(n *native.Container) (*Container, error) { c.Mounts = mounts } + c.HostConfig = new(HostConfig) + if nedctlExtraHosts := n.Labels[labels.ExtraHosts]; nedctlExtraHosts != "" { + c.HostConfig.ExtraHosts = parseExtraHosts(nedctlExtraHosts) + } + + if nerdctlLoguri := n.Labels[labels.LogURI]; nerdctlLoguri != "" { + c.HostConfig.LogConfig.Type = nerdctlLoguri + // c.HostConfig.LogConfig.Config = map[string]string{} + } + if logConfigJSON, ok := n.Labels[labels.LogConfig]; ok { + var logConfig logging.LogConfig + err := json.Unmarshal([]byte(logConfigJSON), &logConfig) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal log config: %v", err) + } + + // Assign the parsed LogConfig to c.HostConfig.LogConfig + c.HostConfig.LogConfig.Config = logConfig + } else { + // If LogConfig label is not present, set default values + c.HostConfig.LogConfig.Config = logging.LogConfig{ + Driver: "json-file", + Opts: make(map[string]string), + } + } + cs := new(ContainerState) cs.Restarting = n.Labels[restart.StatusLabel] == string(containerd.Running) cs.Error = n.Labels[labels.Error] @@ -308,6 +349,7 @@ func ContainerFromNative(n *native.Container) (*Container, error) { return nil, err } c.NetworkSettings = nSettings + c.HostConfig.PortBindings = *nSettings.Ports } c.State = cs c.Config = &Config{ @@ -491,6 +533,15 @@ func convertToNatPort(portMappings []cni.PortMapping) (*nat.PortMap, error) { return &portMap, nil } +func parseExtraHosts(extraHostsJSON string) []string { + var extraHosts []string + if err := json.Unmarshal([]byte(extraHostsJSON), &extraHosts); err != nil { + // Handle error or return empty slice + return []string{} + } + return extraHosts +} + type IPAMConfig struct { Subnet string `json:"Subnet,omitempty"` Gateway string `json:"Gateway,omitempty"` diff --git a/pkg/labels/labels.go b/pkg/labels/labels.go index e2dd6ede16d..620108afb8e 100644 --- a/pkg/labels/labels.go +++ b/pkg/labels/labels.go @@ -101,6 +101,9 @@ const ( // (like "nerdctl/default-network=true" or "nerdctl/default-network=false") NerdctlDefaultNetwork = Prefix + "default-network" + // LogConfig defines the loggin configuration passed to the container + LogConfig = Prefix + "log-config" + // ContainerAutoRemove is to check whether the --rm option is specified. ContainerAutoRemove = Prefix + "auto-remove" )