Docker-DCO-1.1-Signed-off-by: Evan Krall <krall@yelp.com> (github: EvanKrall)
| ... | ... |
@@ -1104,10 +1104,34 @@ func ServeFd(addr string, handle http.Handler) error {
|
| 1104 | 1104 |
return nil |
| 1105 | 1105 |
} |
| 1106 | 1106 |
|
| 1107 |
+func lookupGidByName(nameOrGid string) (int, error) {
|
|
| 1108 |
+ groups, err := user.ParseGroupFilter(func(g *user.Group) bool {
|
|
| 1109 |
+ return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid |
|
| 1110 |
+ }) |
|
| 1111 |
+ if err != nil {
|
|
| 1112 |
+ return -1, err |
|
| 1113 |
+ } |
|
| 1114 |
+ if groups != nil && len(groups) > 0 {
|
|
| 1115 |
+ return groups[0].Gid, nil |
|
| 1116 |
+ } |
|
| 1117 |
+ return -1, fmt.Errorf("Group %s not found", nameOrGid)
|
|
| 1118 |
+} |
|
| 1119 |
+ |
|
| 1120 |
+func changeGroup(addr string, nameOrGid string) error {
|
|
| 1121 |
+ gid, err := lookupGidByName(nameOrGid) |
|
| 1122 |
+ if err != nil {
|
|
| 1123 |
+ return err |
|
| 1124 |
+ } |
|
| 1125 |
+ |
|
| 1126 |
+ utils.Debugf("%s group found. gid: %d", nameOrGid, gid)
|
|
| 1127 |
+ return os.Chown(addr, 0, gid) |
|
| 1128 |
+} |
|
| 1129 |
+ |
|
| 1107 | 1130 |
// ListenAndServe sets up the required http.Server and gets it listening for |
| 1108 | 1131 |
// each addr passed in and does protocol specific checking. |
| 1109 |
-func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string) error {
|
|
| 1132 |
+func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string, socketGroup string) error {
|
|
| 1110 | 1133 |
r, err := createRouter(eng, logging, enableCors, dockerVersion) |
| 1134 |
+ |
|
| 1111 | 1135 |
if err != nil {
|
| 1112 | 1136 |
return err |
| 1113 | 1137 |
} |
| ... | ... |
@@ -1138,16 +1162,14 @@ func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors |
| 1138 | 1138 |
return err |
| 1139 | 1139 |
} |
| 1140 | 1140 |
|
| 1141 |
- groups, err := user.ParseGroupFilter(func(g *user.Group) bool {
|
|
| 1142 |
- return g.Name == "docker" |
|
| 1143 |
- }) |
|
| 1144 |
- if err != nil {
|
|
| 1145 |
- return err |
|
| 1146 |
- } |
|
| 1147 |
- if len(groups) > 0 {
|
|
| 1148 |
- utils.Debugf("docker group found. gid: %d", groups[0].Gid)
|
|
| 1149 |
- if err := os.Chown(addr, 0, groups[0].Gid); err != nil {
|
|
| 1150 |
- return err |
|
| 1141 |
+ if socketGroup != "" {
|
|
| 1142 |
+ if err := changeGroup(addr, socketGroup); err != nil {
|
|
| 1143 |
+ if socketGroup == "docker" {
|
|
| 1144 |
+ // if the user hasn't explicitly specified the group ownership, don't fail on errors. |
|
| 1145 |
+ utils.Debugf("Warning: could not chgrp %s to docker: %s", addr, err.Error())
|
|
| 1146 |
+ } else {
|
|
| 1147 |
+ return err |
|
| 1148 |
+ } |
|
| 1151 | 1149 |
} |
| 1152 | 1150 |
} |
| 1153 | 1151 |
default: |
| ... | ... |
@@ -1175,7 +1197,7 @@ func ServeApi(job *engine.Job) engine.Status {
|
| 1175 | 1175 |
protoAddrParts := strings.SplitN(protoAddr, "://", 2) |
| 1176 | 1176 |
go func() {
|
| 1177 | 1177 |
log.Printf("Listening for HTTP on %s (%s)\n", protoAddrParts[0], protoAddrParts[1])
|
| 1178 |
- chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"))
|
|
| 1178 |
+ chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], job.Eng, job.GetenvBool("Logging"), job.GetenvBool("EnableCors"), job.Getenv("Version"), job.Getenv("SocketGroup"))
|
|
| 1179 | 1179 |
}() |
| 1180 | 1180 |
} |
| 1181 | 1181 |
|
| ... | ... |
@@ -32,6 +32,7 @@ func main() {
|
| 32 | 32 |
bridgeIp = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
|
| 33 | 33 |
pidfile = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
|
| 34 | 34 |
flRoot = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the docker runtime")
|
| 35 |
+ flSocketGroup = flag.String([]string{"G", "-group"}, "docker", "Group to assign the unix socket specified by -H when running in daemon mode; use '' (the empty string) to disable setting of a group")
|
|
| 35 | 36 |
flEnableCors = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
|
| 36 | 37 |
flDns = opts.NewListOpts(opts.ValidateIp4Address) |
| 37 | 38 |
flEnableIptables = flag.Bool([]string{"#iptables", "-iptables"}, true, "Disable docker's addition of iptables rules")
|
| ... | ... |
@@ -138,6 +139,7 @@ func main() {
|
| 138 | 138 |
job.SetenvBool("Logging", true)
|
| 139 | 139 |
job.SetenvBool("EnableCors", *flEnableCors)
|
| 140 | 140 |
job.Setenv("Version", dockerversion.VERSION)
|
| 141 |
+ job.Setenv("SocketGroup", *flSocketGroup)
|
|
| 141 | 142 |
if err := job.Run(); err != nil {
|
| 142 | 143 |
log.Fatal(err) |
| 143 | 144 |
} |
| ... | ... |
@@ -182,9 +182,12 @@ daemon will make the ownership of the Unix socket read/writable by the |
| 182 | 182 |
*docker* group when the daemon starts. The ``docker`` daemon must |
| 183 | 183 |
always run as the root user, but if you run the ``docker`` client as a user in |
| 184 | 184 |
the *docker* group then you don't need to add ``sudo`` to all the |
| 185 |
-client commands. |
|
| 185 |
+client commands. As of 0.9.0, you can specify that a group other than ``docker`` |
|
| 186 |
+should own the Unix socket with the ``-G`` option. |
|
| 187 |
+ |
|
| 188 |
+.. warning:: The *docker* group (or the group specified with ``-G``) is |
|
| 189 |
+ root-equivalent. |
|
| 186 | 190 |
|
| 187 |
-.. warning:: The *docker* group is root-equivalent. |
|
| 188 | 191 |
|
| 189 | 192 |
**Example:** |
| 190 | 193 |
|
| ... | ... |
@@ -71,6 +71,7 @@ Commands |
| 71 | 71 |
Usage of docker: |
| 72 | 72 |
-D, --debug=false: Enable debug mode |
| 73 | 73 |
-H, --host=[]: Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise. systemd socket activation can be used with fd://[socketfd]. |
| 74 |
+ -G, --group="docker": Group to assign the unix socket specified by -H when running in daemon mode; use '' (the empty string) to disable setting of a group |
|
| 74 | 75 |
--api-enable-cors=false: Enable CORS headers in the remote API |
| 75 | 76 |
-b, --bridge="": Attach containers to a pre-existing network bridge; use 'none' to disable container networking |
| 76 | 77 |
--bip="": Use this CIDR notation address for the network bridge's IP, not compatible with -b |