Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package daemon // import "github.com/docker/docker/daemon" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "context" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"io" |
| 6 | 7 |
"os" |
| ... | ... |
@@ -10,6 +11,8 @@ import ( |
| 10 | 10 |
"strconv" |
| 11 | 11 |
"strings" |
| 12 | 12 |
|
| 13 |
+ "github.com/containerd/containerd/containers" |
|
| 14 |
+ coci "github.com/containerd/containerd/oci" |
|
| 13 | 15 |
containertypes "github.com/docker/docker/api/types/container" |
| 14 | 16 |
"github.com/docker/docker/container" |
| 15 | 17 |
daemonconfig "github.com/docker/docker/daemon/config" |
| ... | ... |
@@ -34,104 +37,6 @@ const ( |
| 34 | 34 |
inContainerInitPath = "/sbin/" + daemonconfig.DefaultInitBinary |
| 35 | 35 |
) |
| 36 | 36 |
|
| 37 |
-func setResources(s *specs.Spec, r containertypes.Resources) error {
|
|
| 38 |
- weightDevices, err := getBlkioWeightDevices(r) |
|
| 39 |
- if err != nil {
|
|
| 40 |
- return err |
|
| 41 |
- } |
|
| 42 |
- readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps) |
|
| 43 |
- if err != nil {
|
|
| 44 |
- return err |
|
| 45 |
- } |
|
| 46 |
- writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps) |
|
| 47 |
- if err != nil {
|
|
| 48 |
- return err |
|
| 49 |
- } |
|
| 50 |
- readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps) |
|
| 51 |
- if err != nil {
|
|
| 52 |
- return err |
|
| 53 |
- } |
|
| 54 |
- writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps) |
|
| 55 |
- if err != nil {
|
|
| 56 |
- return err |
|
| 57 |
- } |
|
| 58 |
- |
|
| 59 |
- memoryRes := getMemoryResources(r) |
|
| 60 |
- cpuRes, err := getCPUResources(r) |
|
| 61 |
- if err != nil {
|
|
| 62 |
- return err |
|
| 63 |
- } |
|
| 64 |
- blkioWeight := r.BlkioWeight |
|
| 65 |
- |
|
| 66 |
- specResources := &specs.LinuxResources{
|
|
| 67 |
- Memory: memoryRes, |
|
| 68 |
- CPU: cpuRes, |
|
| 69 |
- BlockIO: &specs.LinuxBlockIO{
|
|
| 70 |
- Weight: &blkioWeight, |
|
| 71 |
- WeightDevice: weightDevices, |
|
| 72 |
- ThrottleReadBpsDevice: readBpsDevice, |
|
| 73 |
- ThrottleWriteBpsDevice: writeBpsDevice, |
|
| 74 |
- ThrottleReadIOPSDevice: readIOpsDevice, |
|
| 75 |
- ThrottleWriteIOPSDevice: writeIOpsDevice, |
|
| 76 |
- }, |
|
| 77 |
- Pids: getPidsLimit(r), |
|
| 78 |
- } |
|
| 79 |
- |
|
| 80 |
- if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
|
|
| 81 |
- specResources.Devices = s.Linux.Resources.Devices |
|
| 82 |
- } |
|
| 83 |
- |
|
| 84 |
- s.Linux.Resources = specResources |
|
| 85 |
- return nil |
|
| 86 |
-} |
|
| 87 |
- |
|
| 88 |
-func (daemon *Daemon) setDevices(s *specs.Spec, c *container.Container) error {
|
|
| 89 |
- // Build lists of devices allowed and created within the container. |
|
| 90 |
- var devs []specs.LinuxDevice |
|
| 91 |
- devPermissions := s.Linux.Resources.Devices |
|
| 92 |
- if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
|
|
| 93 |
- hostDevices, err := devices.HostDevices() |
|
| 94 |
- if err != nil {
|
|
| 95 |
- return err |
|
| 96 |
- } |
|
| 97 |
- for _, d := range hostDevices {
|
|
| 98 |
- devs = append(devs, oci.Device(d)) |
|
| 99 |
- } |
|
| 100 |
- devPermissions = []specs.LinuxDeviceCgroup{
|
|
| 101 |
- {
|
|
| 102 |
- Allow: true, |
|
| 103 |
- Access: "rwm", |
|
| 104 |
- }, |
|
| 105 |
- } |
|
| 106 |
- } else {
|
|
| 107 |
- for _, deviceMapping := range c.HostConfig.Devices {
|
|
| 108 |
- d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions) |
|
| 109 |
- if err != nil {
|
|
| 110 |
- return err |
|
| 111 |
- } |
|
| 112 |
- devs = append(devs, d...) |
|
| 113 |
- devPermissions = append(devPermissions, dPermissions...) |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- var err error |
|
| 117 |
- devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules) |
|
| 118 |
- if err != nil {
|
|
| 119 |
- return err |
|
| 120 |
- } |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- s.Linux.Devices = append(s.Linux.Devices, devs...) |
|
| 124 |
- s.Linux.Resources.Devices = devPermissions |
|
| 125 |
- |
|
| 126 |
- for _, req := range c.HostConfig.DeviceRequests {
|
|
| 127 |
- if err := daemon.handleDevice(req, s); err != nil {
|
|
| 128 |
- return err |
|
| 129 |
- } |
|
| 130 |
- } |
|
| 131 |
- |
|
| 132 |
- return nil |
|
| 133 |
-} |
|
| 134 |
- |
|
| 135 | 37 |
func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
|
| 136 | 38 |
var rlimits []specs.POSIXRlimit |
| 137 | 39 |
|
| ... | ... |
@@ -151,17 +56,6 @@ func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
|
| 151 | 151 |
return nil |
| 152 | 152 |
} |
| 153 | 153 |
|
| 154 |
-func setUser(s *specs.Spec, c *container.Container) error {
|
|
| 155 |
- uid, gid, additionalGids, err := getUser(c, c.Config.User) |
|
| 156 |
- if err != nil {
|
|
| 157 |
- return err |
|
| 158 |
- } |
|
| 159 |
- s.Process.User.UID = uid |
|
| 160 |
- s.Process.User.GID = gid |
|
| 161 |
- s.Process.User.AdditionalGids = additionalGids |
|
| 162 |
- return nil |
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 | 154 |
func readUserFile(c *container.Container, p string) (io.ReadCloser, error) {
|
| 166 | 155 |
fp, err := c.GetResourcePath(p) |
| 167 | 156 |
if err != nil {
|
| ... | ... |
@@ -693,74 +587,201 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container) |
| 693 | 693 |
return nil |
| 694 | 694 |
} |
| 695 | 695 |
|
| 696 |
-func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
|
|
| 697 |
- s := oci.DefaultSpec() |
|
| 698 |
- if err := daemon.populateCommonSpec(&s, c); err != nil {
|
|
| 699 |
- return nil, err |
|
| 700 |
- } |
|
| 696 |
+func withCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
|
| 697 |
+ return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 698 |
+ var cgroupsPath string |
|
| 699 |
+ scopePrefix := "docker" |
|
| 700 |
+ parent := "/docker" |
|
| 701 |
+ useSystemd := UsingSystemd(daemon.configStore) |
|
| 702 |
+ if useSystemd {
|
|
| 703 |
+ parent = "system.slice" |
|
| 704 |
+ } |
|
| 701 | 705 |
|
| 702 |
- var cgroupsPath string |
|
| 703 |
- scopePrefix := "docker" |
|
| 704 |
- parent := "/docker" |
|
| 705 |
- useSystemd := UsingSystemd(daemon.configStore) |
|
| 706 |
- if useSystemd {
|
|
| 707 |
- parent = "system.slice" |
|
| 708 |
- } |
|
| 706 |
+ if c.HostConfig.CgroupParent != "" {
|
|
| 707 |
+ parent = c.HostConfig.CgroupParent |
|
| 708 |
+ } else if daemon.configStore.CgroupParent != "" {
|
|
| 709 |
+ parent = daemon.configStore.CgroupParent |
|
| 710 |
+ } |
|
| 709 | 711 |
|
| 710 |
- if c.HostConfig.CgroupParent != "" {
|
|
| 711 |
- parent = c.HostConfig.CgroupParent |
|
| 712 |
- } else if daemon.configStore.CgroupParent != "" {
|
|
| 713 |
- parent = daemon.configStore.CgroupParent |
|
| 714 |
- } |
|
| 712 |
+ if useSystemd {
|
|
| 713 |
+ cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID |
|
| 714 |
+ logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
|
|
| 715 |
+ } else {
|
|
| 716 |
+ cgroupsPath = filepath.Join(parent, c.ID) |
|
| 717 |
+ } |
|
| 718 |
+ s.Linux.CgroupsPath = cgroupsPath |
|
| 719 |
+ p := cgroupsPath |
|
| 720 |
+ if useSystemd {
|
|
| 721 |
+ initPath, err := cgroups.GetInitCgroup("cpu")
|
|
| 722 |
+ if err != nil {
|
|
| 723 |
+ return err |
|
| 724 |
+ } |
|
| 725 |
+ _, err = cgroups.GetOwnCgroup("cpu")
|
|
| 726 |
+ if err != nil {
|
|
| 727 |
+ return err |
|
| 728 |
+ } |
|
| 729 |
+ p = filepath.Join(initPath, s.Linux.CgroupsPath) |
|
| 730 |
+ } |
|
| 715 | 731 |
|
| 716 |
- if useSystemd {
|
|
| 717 |
- cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID |
|
| 718 |
- logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
|
|
| 719 |
- } else {
|
|
| 720 |
- cgroupsPath = filepath.Join(parent, c.ID) |
|
| 721 |
- } |
|
| 722 |
- s.Linux.CgroupsPath = cgroupsPath |
|
| 732 |
+ // Clean path to guard against things like ../../../BAD |
|
| 733 |
+ parentPath := filepath.Dir(p) |
|
| 734 |
+ if !filepath.IsAbs(parentPath) {
|
|
| 735 |
+ parentPath = filepath.Clean("/" + parentPath)
|
|
| 736 |
+ } |
|
| 723 | 737 |
|
| 724 |
- if err := setResources(&s, c.HostConfig.Resources); err != nil {
|
|
| 725 |
- return nil, fmt.Errorf("linux runtime spec resources: %v", err)
|
|
| 738 |
+ if err := daemon.initCgroupsPath(parentPath); err != nil {
|
|
| 739 |
+ return fmt.Errorf("linux init cgroups path: %v", err)
|
|
| 740 |
+ } |
|
| 741 |
+ return nil |
|
| 726 | 742 |
} |
| 727 |
- // We merge the sysctls injected above with the HostConfig (latter takes |
|
| 728 |
- // precedence for backwards-compatibility reasons). |
|
| 729 |
- for k, v := range c.HostConfig.Sysctls {
|
|
| 730 |
- s.Linux.Sysctl[k] = v |
|
| 743 |
+} |
|
| 744 |
+ |
|
| 745 |
+func withContainerDevices(daemon *Daemon, c *container.Container) coci.SpecOpts {
|
|
| 746 |
+ return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 747 |
+ // Build lists of devices allowed and created within the container. |
|
| 748 |
+ var devs []specs.LinuxDevice |
|
| 749 |
+ devPermissions := s.Linux.Resources.Devices |
|
| 750 |
+ if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
|
|
| 751 |
+ hostDevices, err := devices.HostDevices() |
|
| 752 |
+ if err != nil {
|
|
| 753 |
+ return err |
|
| 754 |
+ } |
|
| 755 |
+ for _, d := range hostDevices {
|
|
| 756 |
+ devs = append(devs, oci.Device(d)) |
|
| 757 |
+ } |
|
| 758 |
+ devPermissions = []specs.LinuxDeviceCgroup{
|
|
| 759 |
+ {
|
|
| 760 |
+ Allow: true, |
|
| 761 |
+ Access: "rwm", |
|
| 762 |
+ }, |
|
| 763 |
+ } |
|
| 764 |
+ } else {
|
|
| 765 |
+ for _, deviceMapping := range c.HostConfig.Devices {
|
|
| 766 |
+ d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions) |
|
| 767 |
+ if err != nil {
|
|
| 768 |
+ return err |
|
| 769 |
+ } |
|
| 770 |
+ devs = append(devs, d...) |
|
| 771 |
+ devPermissions = append(devPermissions, dPermissions...) |
|
| 772 |
+ } |
|
| 773 |
+ |
|
| 774 |
+ var err error |
|
| 775 |
+ devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules) |
|
| 776 |
+ if err != nil {
|
|
| 777 |
+ return err |
|
| 778 |
+ } |
|
| 779 |
+ } |
|
| 780 |
+ |
|
| 781 |
+ s.Linux.Devices = append(s.Linux.Devices, devs...) |
|
| 782 |
+ s.Linux.Resources.Devices = devPermissions |
|
| 783 |
+ |
|
| 784 |
+ for _, req := range c.HostConfig.DeviceRequests {
|
|
| 785 |
+ if err := daemon.handleDevice(req, s); err != nil {
|
|
| 786 |
+ return err |
|
| 787 |
+ } |
|
| 788 |
+ } |
|
| 789 |
+ return nil |
|
| 731 | 790 |
} |
| 791 |
+} |
|
| 732 | 792 |
|
| 733 |
- p := s.Linux.CgroupsPath |
|
| 734 |
- if useSystemd {
|
|
| 735 |
- initPath, err := cgroups.GetInitCgroup("cpu")
|
|
| 793 |
+func withResources(c *container.Container) coci.SpecOpts {
|
|
| 794 |
+ return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 795 |
+ r := c.HostConfig.Resources |
|
| 796 |
+ weightDevices, err := getBlkioWeightDevices(r) |
|
| 736 | 797 |
if err != nil {
|
| 737 |
- return nil, err |
|
| 798 |
+ return err |
|
| 738 | 799 |
} |
| 739 |
- _, err = cgroups.GetOwnCgroup("cpu")
|
|
| 800 |
+ readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps) |
|
| 740 | 801 |
if err != nil {
|
| 741 |
- return nil, err |
|
| 802 |
+ return err |
|
| 803 |
+ } |
|
| 804 |
+ writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps) |
|
| 805 |
+ if err != nil {
|
|
| 806 |
+ return err |
|
| 807 |
+ } |
|
| 808 |
+ readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps) |
|
| 809 |
+ if err != nil {
|
|
| 810 |
+ return err |
|
| 811 |
+ } |
|
| 812 |
+ writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps) |
|
| 813 |
+ if err != nil {
|
|
| 814 |
+ return err |
|
| 815 |
+ } |
|
| 816 |
+ |
|
| 817 |
+ memoryRes := getMemoryResources(r) |
|
| 818 |
+ cpuRes, err := getCPUResources(r) |
|
| 819 |
+ if err != nil {
|
|
| 820 |
+ return err |
|
| 821 |
+ } |
|
| 822 |
+ blkioWeight := r.BlkioWeight |
|
| 823 |
+ |
|
| 824 |
+ specResources := &specs.LinuxResources{
|
|
| 825 |
+ Memory: memoryRes, |
|
| 826 |
+ CPU: cpuRes, |
|
| 827 |
+ BlockIO: &specs.LinuxBlockIO{
|
|
| 828 |
+ Weight: &blkioWeight, |
|
| 829 |
+ WeightDevice: weightDevices, |
|
| 830 |
+ ThrottleReadBpsDevice: readBpsDevice, |
|
| 831 |
+ ThrottleWriteBpsDevice: writeBpsDevice, |
|
| 832 |
+ ThrottleReadIOPSDevice: readIOpsDevice, |
|
| 833 |
+ ThrottleWriteIOPSDevice: writeIOpsDevice, |
|
| 834 |
+ }, |
|
| 835 |
+ Pids: getPidsLimit(r), |
|
| 742 | 836 |
} |
| 743 |
- p = filepath.Join(initPath, s.Linux.CgroupsPath) |
|
| 837 |
+ |
|
| 838 |
+ if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
|
|
| 839 |
+ specResources.Devices = s.Linux.Resources.Devices |
|
| 840 |
+ } |
|
| 841 |
+ |
|
| 842 |
+ s.Linux.Resources = specResources |
|
| 843 |
+ return nil |
|
| 744 | 844 |
} |
| 845 |
+} |
|
| 745 | 846 |
|
| 746 |
- // Clean path to guard against things like ../../../BAD |
|
| 747 |
- parentPath := filepath.Dir(p) |
|
| 748 |
- if !filepath.IsAbs(parentPath) {
|
|
| 749 |
- parentPath = filepath.Clean("/" + parentPath)
|
|
| 847 |
+func withSysctls(c *container.Container) coci.SpecOpts {
|
|
| 848 |
+ return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 849 |
+ // We merge the sysctls injected above with the HostConfig (latter takes |
|
| 850 |
+ // precedence for backwards-compatibility reasons). |
|
| 851 |
+ for k, v := range c.HostConfig.Sysctls {
|
|
| 852 |
+ s.Linux.Sysctl[k] = v |
|
| 853 |
+ } |
|
| 854 |
+ return nil |
|
| 750 | 855 |
} |
| 856 |
+} |
|
| 751 | 857 |
|
| 752 |
- if err := daemon.initCgroupsPath(parentPath); err != nil {
|
|
| 753 |
- return nil, fmt.Errorf("linux init cgroups path: %v", err)
|
|
| 858 |
+func withUser(c *container.Container) coci.SpecOpts {
|
|
| 859 |
+ return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
|
|
| 860 |
+ uid, gid, additionalGids, err := getUser(c, c.Config.User) |
|
| 861 |
+ if err != nil {
|
|
| 862 |
+ return err |
|
| 863 |
+ } |
|
| 864 |
+ s.Process.User.UID = uid |
|
| 865 |
+ s.Process.User.GID = gid |
|
| 866 |
+ s.Process.User.AdditionalGids = additionalGids |
|
| 867 |
+ return nil |
|
| 754 | 868 |
} |
| 755 |
- if err := daemon.setDevices(&s, c); err != nil {
|
|
| 756 |
- return nil, fmt.Errorf("linux runtime spec devices: %v", err)
|
|
| 869 |
+} |
|
| 870 |
+ |
|
| 871 |
+func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
|
|
| 872 |
+ var ( |
|
| 873 |
+ opts []coci.SpecOpts |
|
| 874 |
+ s = oci.DefaultSpec() |
|
| 875 |
+ ) |
|
| 876 |
+ if err := daemon.populateCommonSpec(&s, c); err != nil {
|
|
| 877 |
+ return nil, err |
|
| 757 | 878 |
} |
| 879 |
+ |
|
| 880 |
+ opts = append(opts, |
|
| 881 |
+ withCgroups(daemon, c), |
|
| 882 |
+ withResources(c), |
|
| 883 |
+ withSysctls(c), |
|
| 884 |
+ withContainerDevices(daemon, c), |
|
| 885 |
+ withUser(c), |
|
| 886 |
+ ) |
|
| 887 |
+ |
|
| 758 | 888 |
if err := daemon.setRlimits(&s, c); err != nil {
|
| 759 | 889 |
return nil, fmt.Errorf("linux runtime spec rlimits: %v", err)
|
| 760 | 890 |
} |
| 761 |
- if err := setUser(&s, c); err != nil {
|
|
| 762 |
- return nil, fmt.Errorf("linux spec user: %v", err)
|
|
| 763 |
- } |
|
| 764 | 891 |
if err := setNamespaces(daemon, &s, c); err != nil {
|
| 765 | 892 |
return nil, fmt.Errorf("linux spec namespaces: %v", err)
|
| 766 | 893 |
} |
| ... | ... |
@@ -874,7 +895,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e |
| 874 | 874 |
return nil, err |
| 875 | 875 |
} |
| 876 | 876 |
} |
| 877 |
- return &s, nil |
|
| 877 |
+ return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
|
|
| 878 |
+ ID: c.ID, |
|
| 879 |
+ }, &s, opts...) |
|
| 878 | 880 |
} |
| 879 | 881 |
|
| 880 | 882 |
func clearReadOnly(m *specs.Mount) {
|