Merge pull request #1994 from AkihiroSuda/fix-user

fix running a container with config.User
This commit is contained in:
Michael Crosby 2018-01-12 12:57:31 -05:00 committed by GitHub
commit 4a6e2975cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 13 deletions

View File

@ -75,7 +75,10 @@ func newContainer(ctx gocontext.Context, client *containerd.Client, context *cli
if context.Bool("net-host") { if context.Bool("net-host") {
opts = append(opts, oci.WithHostNamespace(specs.NetworkNamespace), oci.WithHostHostsFile, oci.WithHostResolvconf) opts = append(opts, oci.WithHostNamespace(specs.NetworkNamespace), oci.WithHostHostsFile, oci.WithHostResolvconf)
} }
cOpts = append([]containerd.NewContainerOpts{containerd.WithNewSpec(opts...)}, cOpts...) // oci.WithImageConfig (WithUsername, WithUserID) depends on rootfs snapshot for resolving /etc/passwd.
// So cOpts needs to have precedence over opts.
// TODO: WithUsername, WithUserID should additionally support non-snapshot rootfs
cOpts = append(cOpts, []containerd.NewContainerOpts{containerd.WithNewSpec(opts...)}...)
return client.NewContainer(ctx, id, cOpts...) return client.NewContainer(ctx, id, cOpts...)
} }

View File

@ -95,22 +95,25 @@ func WithImageConfig(image Image) SpecOpts {
s.Process.Env = append(s.Process.Env, config.Env...) s.Process.Env = append(s.Process.Env, config.Env...)
cmd := config.Cmd cmd := config.Cmd
s.Process.Args = append(config.Entrypoint, cmd...) s.Process.Args = append(config.Entrypoint, cmd...)
cwd := config.WorkingDir
if cwd == "" {
cwd = "/"
}
s.Process.Cwd = cwd
if config.User != "" { if config.User != "" {
// According to OCI Image Spec v1.0.0, the following are valid for Linux:
// user, uid, user:group, uid:gid, uid:group, user:gid
parts := strings.Split(config.User, ":") parts := strings.Split(config.User, ":")
switch len(parts) { switch len(parts) {
case 1: case 1:
v, err := strconv.Atoi(parts[0]) v, err := strconv.Atoi(parts[0])
if err != nil { if err != nil {
// if we cannot parse as a uint they try to see if it is a username // if we cannot parse as a uint they try to see if it is a username
if err := WithUsername(config.User)(ctx, client, c, s); err != nil { return WithUsername(config.User)(ctx, client, c, s)
return err
}
return err
}
if err := WithUserID(uint32(v))(ctx, client, c, s); err != nil {
return err
} }
return WithUserID(uint32(v))(ctx, client, c, s)
case 2: case 2:
// TODO: support username and groupname
v, err := strconv.Atoi(parts[0]) v, err := strconv.Atoi(parts[0])
if err != nil { if err != nil {
return errors.Wrapf(err, "parse uid %s", parts[0]) return errors.Wrapf(err, "parse uid %s", parts[0])
@ -125,11 +128,6 @@ func WithImageConfig(image Image) SpecOpts {
return fmt.Errorf("invalid USER value %s", config.User) return fmt.Errorf("invalid USER value %s", config.User)
} }
} }
cwd := config.WorkingDir
if cwd == "" {
cwd = "/"
}
s.Process.Cwd = cwd
return nil return nil
} }
} }
@ -259,6 +257,7 @@ func WithUIDGID(uid, gid uint32) SpecOpts {
// uid, and not returns error. // uid, and not returns error.
func WithUserID(uid uint32) SpecOpts { func WithUserID(uid uint32) SpecOpts {
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
// TODO: support non-snapshot rootfs
if c.Snapshotter == "" { if c.Snapshotter == "" {
return errors.Errorf("no snapshotter set for container") return errors.Errorf("no snapshotter set for container")
} }
@ -307,6 +306,7 @@ func WithUserID(uid uint32) SpecOpts {
// does not exist, or the username is not found in /etc/passwd, // does not exist, or the username is not found in /etc/passwd,
// it returns error. // it returns error.
func WithUsername(username string) SpecOpts { func WithUsername(username string) SpecOpts {
// TODO: support non-snapshot rootfs
return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) { return func(ctx context.Context, client Client, c *containers.Container, s *specs.Spec) (err error) {
if c.Snapshotter == "" { if c.Snapshotter == "" {
return errors.Errorf("no snapshotter set for container") return errors.Errorf("no snapshotter set for container")