Merge pull request #203 from tonistiigi/user

Add support for setting user
docker-18.09
Akihiro Suda 2017-12-13 13:06:07 +09:00 committed by GitHub
commit 571e14e003
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 410 additions and 69 deletions

View File

@ -36,6 +36,7 @@ func TestClientIntegration(t *testing.T) {
testBuildHTTPSource,
testBuildPushAndValidate,
testResolveAndHosts,
testUser,
})
}
@ -200,6 +201,59 @@ func testResolveAndHosts(t *testing.T, sb integration.Sandbox) {
}
func testUser(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
t.Parallel()
c, err := New(sb.Address())
require.NoError(t, err)
defer c.Close()
st := llb.Image("busybox:latest").Run(llb.Shlex(`sh -c "mkdir -m 0777 /wd"`))
run := func(user, cmd string) {
st = st.Run(llb.Shlex(cmd), llb.Dir("/wd"), llb.User(user))
}
run("daemon", `sh -c "id -nu > user"`)
run("daemon:daemon", `sh -c "id -ng > group"`)
run("daemon:nogroup", `sh -c "id -ng > nogroup"`)
run("1:1", `sh -c "id -g > userone"`)
st = st.Run(llb.Shlex("cp -a /wd/. /out/"))
out := st.AddMount("/out", llb.Scratch())
def, err := out.Marshal()
require.NoError(t, err)
destDir, err := ioutil.TempDir("", "buildkit")
require.NoError(t, err)
defer os.RemoveAll(destDir)
err = c.Solve(context.TODO(), def, SolveOpt{
Exporter: ExporterLocal,
ExporterAttrs: map[string]string{
"output": destDir,
},
}, nil)
require.NoError(t, err)
dt, err := ioutil.ReadFile(filepath.Join(destDir, "user"))
require.NoError(t, err)
require.Contains(t, string(dt), "daemon")
dt, err = ioutil.ReadFile(filepath.Join(destDir, "group"))
require.NoError(t, err)
require.Contains(t, string(dt), "daemon")
dt, err = ioutil.ReadFile(filepath.Join(destDir, "nogroup"))
require.NoError(t, err)
require.Contains(t, string(dt), "nogroup")
dt, err = ioutil.ReadFile(filepath.Join(destDir, "userone"))
require.NoError(t, err)
require.Contains(t, string(dt), "1")
}
func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) {
requiresLinux(t)
t.Parallel()

View File

@ -12,6 +12,7 @@ type Meta struct {
Args []string
Env EnvList
Cwd string
User string
}
func NewExecOp(root Output, meta Meta, readOnly bool, md OpMetadata) *ExecOp {
@ -110,6 +111,7 @@ func (e *ExecOp) Marshal() ([]byte, *OpMetadata, error) {
Args: e.meta.Args,
Env: e.meta.Env.ToArray(),
Cwd: e.meta.Cwd,
User: e.meta.User,
},
}
@ -271,6 +273,12 @@ func AddEnvf(key, value string, v ...interface{}) RunOption {
})
}
func User(str string) RunOption {
return runOptionFunc(func(ei *ExecInfo) {
ei.State = ei.State.User(str)
})
}
func Dir(str string) RunOption {
return Dirf(str)
}

View File

@ -12,6 +12,7 @@ var (
keyArgs = contextKeyT("llb.exec.args")
keyDir = contextKeyT("llb.exec.dir")
keyEnv = contextKeyT("llb.exec.env")
keyUser = contextKeyT("llb.exec.user")
)
func addEnv(key, value string) StateOption {
@ -42,6 +43,12 @@ func dirf(str string, v ...interface{}) StateOption {
}
}
func user(str string) StateOption {
return func(s State) State {
return s.WithValue(keyUser, str)
}
}
func reset(s_ State) StateOption {
return func(s State) State {
s = NewState(s.Output())
@ -74,6 +81,14 @@ func getArgs(s State) []string {
return nil
}
func getUser(s State) string {
v := s.Value(keyUser)
if v != nil {
return v.(string)
}
return ""
}
func args(args ...string) StateOption {
return func(s State) State {
return s.WithValue(keyArgs, args)

View File

@ -129,6 +129,7 @@ func (s State) Run(ro ...RunOption) ExecState {
Args: getArgs(ei.State),
Cwd: getDir(ei.State),
Env: getEnv(ei.State),
User: getUser(ei.State),
}
exec := NewExecOp(s.Output(), meta, ei.ReadonlyRootFS, ei.Metadata())
@ -173,6 +174,10 @@ func (s State) Reset(s2 State) State {
return reset(s2)(s)
}
func (s State) User(v string) State {
return user(v)(s)
}
func (s State) With(so ...StateOption) State {
for _, o := range so {
s = o(s)

View File

@ -7,10 +7,12 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
containerdoci "github.com/containerd/containerd/oci"
"github.com/moby/buildkit/cache"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/snapshot"
"github.com/pkg/errors"
"golang.org/x/net/context"
)
@ -40,17 +42,32 @@ func (w containerdExecutor) Exec(ctx context.Context, meta executor.Meta, root c
return err
}
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile)
if err != nil {
return err
}
defer cleanup()
rootMounts, err := root.Mount(ctx, false)
if err != nil {
return err
}
uid, gid, err := oci.ParseUser(meta.User)
if err != nil {
lm := snapshot.LocalMounter(rootMounts)
rootfsPath, err := lm.Mount()
if err != nil {
return err
}
uid, gid, err = oci.GetUser(ctx, rootfsPath, meta.User)
if err != nil {
lm.Unmount()
return err
}
lm.Unmount()
}
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, containerdoci.WithUIDGID(uid, gid))
if err != nil {
return err
}
defer cleanup()
container, err := w.client.NewContainer(ctx, id,
containerd.WithSpec(spec),
)

View File

@ -21,7 +21,7 @@ import (
// Ideally we don't have to import whole containerd just for the default spec
// GenerateSpec generates spec using containerd functionality.
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id string, resolvConf, hostsFile string) (*specs.Spec, func(), error) {
func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) {
c := &containers.Container{
ID: id,
}
@ -29,13 +29,16 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou
if !ok {
ctx = namespaces.WithNamespace(ctx, "buildkit")
}
// Note that containerd.GenerateSpec is namespaced so as to make
// specs.Linux.CgroupsPath namespaced
s, err := oci.GenerateSpec(ctx, nil, c,
opts = append(opts,
oci.WithHostNamespace(specs.NetworkNamespace),
withROBind(resolvConf, "/etc/resolv.conf"),
withROBind(hostsFile, "/etc/hosts"),
)
// Note that containerd.GenerateSpec is namespaced so as to make
// specs.Linux.CgroupsPath namespaced
s, err := oci.GenerateSpec(ctx, nil, c, opts...)
if err != nil {
return nil, nil, err
}

86
executor/oci/user.go Normal file
View File

@ -0,0 +1,86 @@
package oci
import (
"context"
"os"
"strconv"
"strings"
"github.com/containerd/containerd/fs"
"github.com/opencontainers/runc/libcontainer/user"
)
func GetUser(ctx context.Context, root, username string) (uint32, uint32, error) {
// fast path from uid/gid
if uid, gid, err := ParseUser(username); err == nil {
return uid, gid, nil
}
passwdPath, err := user.GetPasswdPath()
if err != nil {
return 0, 0, err
}
groupPath, err := user.GetGroupPath()
if err != nil {
return 0, 0, err
}
passwdFile, err := openUserFile(root, passwdPath)
if err == nil {
defer passwdFile.Close()
}
groupFile, err := openUserFile(root, groupPath)
if err == nil {
defer groupFile.Close()
}
execUser, err := user.GetExecUser(username, nil, passwdFile, groupFile)
if err != nil {
return 0, 0, err
}
return uint32(execUser.Uid), uint32(execUser.Gid), nil
}
func ParseUser(str string) (uid uint32, gid uint32, err error) {
if str == "" {
return 0, 0, nil
}
parts := strings.SplitN(str, ":", 2)
for i, v := range parts {
switch i {
case 0:
uid, err = parseUID(v)
if err != nil {
return 0, 0, err
}
if len(parts) == 1 {
gid = uid
}
case 1:
gid, err = parseUID(v)
if err != nil {
return 0, 0, err
}
}
}
return
}
func openUserFile(root, p string) (*os.File, error) {
p, err := fs.RootPath(root, p)
if err != nil {
return nil, err
}
return os.Open(p)
}
func parseUID(str string) (uint32, error) {
if str == "root" {
return 0, nil
}
uid, err := strconv.ParseUint(str, 10, 32)
if err != nil {
return 0, err
}
return uint32(uid), nil
}

View File

@ -9,6 +9,7 @@ import (
"syscall"
"github.com/containerd/containerd/mount"
containerdoci "github.com/containerd/containerd/oci"
runc "github.com/containerd/go-runc"
"github.com/docker/docker/pkg/symlink"
"github.com/moby/buildkit/cache"
@ -82,21 +83,27 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache.
if err := os.Mkdir(rootFSPath, 0700); err != nil {
return err
}
if err := mount.All(rootMount, rootFSPath); err != nil {
return err
}
defer mount.Unmount(rootFSPath, 0)
uid, gid, err := oci.GetUser(ctx, rootFSPath, meta.User)
if err != nil {
return err
}
f, err := os.Create(filepath.Join(bundle, "config.json"))
if err != nil {
return err
}
defer f.Close()
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile)
spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, containerdoci.WithUIDGID(uid, gid))
if err != nil {
return err
}
defer cleanup()
if err := mount.All(rootMount, rootFSPath); err != nil {
return err
}
defer mount.Unmount(rootFSPath, 0)
spec.Root.Path = rootFSPath
if _, ok := root.(cache.ImmutableRef); ok { // TODO: pass in with mount, not ref type
spec.Root.Readonly = true

View File

@ -502,6 +502,7 @@ func dispatchExpose(d *dispatchState, c *instructions.ExposeCommand, shlex *Shel
return commitToHistory(&d.image, fmt.Sprintf("EXPOSE %v", ps), false, nil)
}
func dispatchUser(d *dispatchState, c *instructions.UserCommand, commit bool) error {
d.state = d.state.User(c.User)
d.image.Config.User = c.User
if commit {
return commitToHistory(&d.image, fmt.Sprintf("USER %v", c.User), false, nil)

View File

@ -38,6 +38,7 @@ func TestIntegration(t *testing.T) {
testDockerfileScratchConfig,
testExportedHistory,
testExposeExpansion,
testUser,
})
}
@ -575,6 +576,101 @@ RUN ["ls"]
require.Equal(t, true, ociimg.History[5].EmptyLayer)
}
func testUser(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dockerfile := []byte(`
FROM busybox AS base
RUN mkdir -m 0777 /out
RUN id -un > /out/rootuser
USER daemon
RUN id -un > /out/daemonuser
FROM scratch
COPY --from=base /out /
USER nobody
`)
dir, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)
c, err := client.New(sb.Address())
require.NoError(t, err)
defer c.Close()
destDir, err := ioutil.TempDir("", "buildkit")
require.NoError(t, err)
defer os.RemoveAll(destDir)
err = c.Solve(context.TODO(), nil, client.SolveOpt{
Frontend: "dockerfile.v0",
Exporter: client.ExporterLocal,
ExporterAttrs: map[string]string{
"output": destDir,
},
LocalDirs: map[string]string{
localNameDockerfile: dir,
localNameContext: dir,
},
}, nil)
require.NoError(t, err)
dt, err := ioutil.ReadFile(filepath.Join(destDir, "rootuser"))
require.NoError(t, err)
require.Equal(t, string(dt), "root\n")
dt, err = ioutil.ReadFile(filepath.Join(destDir, "daemonuser"))
require.NoError(t, err)
require.Equal(t, string(dt), "daemon\n")
// test user in exported
target := "example.com/moby/dockerfileuser:test"
err = c.Solve(context.TODO(), nil, client.SolveOpt{
Frontend: "dockerfile.v0",
Exporter: client.ExporterImage,
ExporterAttrs: map[string]string{
"name": target,
},
LocalDirs: map[string]string{
localNameDockerfile: dir,
localNameContext: dir,
},
}, nil)
require.NoError(t, err)
var cdAddress string
if cd, ok := sb.(interface {
ContainerdAddress() string
}); !ok {
return
} else {
cdAddress = cd.ContainerdAddress()
}
client, err := containerd.New(cdAddress)
require.NoError(t, err)
defer client.Close()
ctx := namespaces.WithNamespace(context.Background(), "buildkit")
img, err := client.ImageService().Get(ctx, target)
require.NoError(t, err)
desc, err := img.Config(ctx, client.ContentStore(), platforms.Default())
require.NoError(t, err)
dt, err = content.ReadBlob(ctx, client.ContentStore(), desc.Digest)
require.NoError(t, err)
var ociimg ocispec.Image
err = json.Unmarshal(dt, &ociimg)
require.NoError(t, err)
require.Equal(t, "nobody", ociimg.Config.User)
}
func tmpdir(appliers ...fstest.Applier) (string, error) {
tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile")
if err != nil {

View File

@ -109,6 +109,7 @@ func (e *execOp) Run(ctx context.Context, inputs []Reference) ([]Reference, erro
Args: e.op.Meta.Args,
Env: e.op.Meta.Env,
Cwd: e.op.Meta.Cwd,
User: e.op.Meta.User,
}
stdout, stderr := logs.NewLogStreams(ctx)

View File

@ -277,6 +277,7 @@ type Meta struct {
Args []string `protobuf:"bytes,1,rep,name=args" json:"args,omitempty"`
Env []string `protobuf:"bytes,2,rep,name=env" json:"env,omitempty"`
Cwd string `protobuf:"bytes,3,opt,name=cwd,proto3" json:"cwd,omitempty"`
User string `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
}
func (m *Meta) Reset() { *m = Meta{} }
@ -305,6 +306,13 @@ func (m *Meta) GetCwd() string {
return ""
}
func (m *Meta) GetUser() string {
if m != nil {
return m.User
}
return ""
}
type Mount struct {
Input InputIndex `protobuf:"varint,1,opt,name=input,proto3,customtype=InputIndex" json:"input"`
Selector string `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"`
@ -753,6 +761,12 @@ func (m *Meta) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintOps(dAtA, i, uint64(len(m.Cwd)))
i += copy(dAtA[i:], m.Cwd)
}
if len(m.User) > 0 {
dAtA[i] = 0x22
i++
i = encodeVarintOps(dAtA, i, uint64(len(m.User)))
i += copy(dAtA[i:], m.User)
}
return i, nil
}
@ -1270,6 +1284,10 @@ func (m *Meta) Size() (n int) {
if l > 0 {
n += 1 + l + sovOps(uint64(l))
}
l = len(m.User)
if l > 0 {
n += 1 + l + sovOps(uint64(l))
}
return n
}
@ -1988,6 +2006,35 @@ func (m *Meta) Unmarshal(dAtA []byte) error {
}
m.Cwd = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field User", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowOps
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthOps
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.User = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipOps(dAtA[iNdEx:])
@ -3592,58 +3639,58 @@ var (
func init() { proto.RegisterFile("ops.proto", fileDescriptorOps) }
var fileDescriptorOps = []byte{
// 837 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x8e, 0xe3, 0x44,
0x10, 0x1e, 0x3b, 0x3f, 0x9b, 0x94, 0x07, 0x14, 0x9a, 0x15, 0x44, 0xd1, 0x2a, 0x09, 0x06, 0xa1,
0x00, 0x3b, 0x8e, 0x94, 0x95, 0xd0, 0x8a, 0xc3, 0x48, 0x93, 0x99, 0x95, 0x08, 0x68, 0x15, 0xa9,
0x41, 0xe2, 0xb8, 0x72, 0xec, 0x4e, 0xd6, 0xda, 0xc4, 0xdd, 0xb2, 0xdb, 0x3b, 0x93, 0x0b, 0x07,
0x9e, 0x00, 0x89, 0xb7, 0xe0, 0x1d, 0xe0, 0xbc, 0x47, 0xae, 0x70, 0x58, 0xd0, 0xf0, 0x0c, 0xdc,
0x51, 0x55, 0x77, 0x62, 0xcf, 0x30, 0x48, 0x33, 0x82, 0x53, 0xba, 0xab, 0xaa, 0xbf, 0xaa, 0xfa,
0xea, 0x2b, 0x07, 0xda, 0x52, 0xe5, 0x81, 0xca, 0xa4, 0x96, 0xcc, 0x55, 0x8b, 0xde, 0xd1, 0x2a,
0xd1, 0xcf, 0x8b, 0x45, 0x10, 0xc9, 0xcd, 0x78, 0x25, 0x57, 0x72, 0x4c, 0xae, 0x45, 0xb1, 0xa4,
0x1b, 0x5d, 0xe8, 0x64, 0x9e, 0xf8, 0x3f, 0x3b, 0xe0, 0xce, 0x15, 0x7b, 0x0f, 0x9a, 0x49, 0xaa,
0x0a, 0x9d, 0x77, 0x9d, 0x61, 0x6d, 0xe4, 0x4d, 0xda, 0x81, 0x5a, 0x04, 0x33, 0xb4, 0x70, 0xeb,
0x60, 0x43, 0xa8, 0x8b, 0x0b, 0x11, 0x75, 0xdd, 0xa1, 0x33, 0xf2, 0x26, 0x80, 0x01, 0x4f, 0x2e,
0x44, 0x34, 0x57, 0x9f, 0x1f, 0x70, 0xf2, 0xb0, 0x0f, 0xa1, 0x99, 0xcb, 0x22, 0x8b, 0x44, 0xb7,
0x46, 0x31, 0x87, 0x18, 0xf3, 0x15, 0x59, 0x28, 0xca, 0x7a, 0x11, 0x29, 0x92, 0x6a, 0xdb, 0xad,
0x97, 0x48, 0xa7, 0x52, 0x6d, 0x0d, 0x12, 0x7a, 0xd8, 0xfb, 0xd0, 0x58, 0x14, 0xc9, 0x3a, 0xee,
0x36, 0x28, 0xc4, 0xc3, 0x90, 0x29, 0x1a, 0x28, 0xc6, 0xf8, 0xa6, 0x75, 0x70, 0xa5, 0xf2, 0xbf,
0x85, 0x06, 0xd5, 0xc9, 0xbe, 0x80, 0x66, 0x9c, 0xac, 0x44, 0xae, 0xbb, 0xce, 0xd0, 0x19, 0xb5,
0xa7, 0x93, 0x57, 0xaf, 0x07, 0x07, 0xbf, 0xbd, 0x1e, 0x7c, 0x5c, 0x21, 0x44, 0x2a, 0x91, 0x46,
0x32, 0xd5, 0x61, 0x92, 0x8a, 0x2c, 0x1f, 0xaf, 0xe4, 0x91, 0x79, 0x12, 0x9c, 0xd1, 0x0f, 0xb7,
0x08, 0xec, 0x23, 0x68, 0x24, 0x69, 0x2c, 0x2e, 0xa8, 0xd9, 0xda, 0xf4, 0x6d, 0x0b, 0xe5, 0xcd,
0x0b, 0xad, 0x0a, 0x3d, 0x43, 0x17, 0x37, 0x11, 0xfe, 0x0c, 0x9a, 0x86, 0x06, 0xf6, 0x00, 0xea,
0x1b, 0xa1, 0x43, 0x4a, 0xef, 0x4d, 0x5a, 0x58, 0xf3, 0x53, 0xa1, 0x43, 0x4e, 0x56, 0x64, 0x78,
0x23, 0x8b, 0x54, 0xe7, 0x5d, 0xb7, 0x64, 0xf8, 0x29, 0x5a, 0xb8, 0x75, 0xf8, 0xc7, 0x50, 0xc7,
0x07, 0x8c, 0x41, 0x3d, 0xcc, 0x56, 0x66, 0x14, 0x6d, 0x4e, 0x67, 0xd6, 0x81, 0x9a, 0x48, 0x5f,
0xd2, 0xdb, 0x36, 0xc7, 0x23, 0x5a, 0xa2, 0xf3, 0x98, 0xa8, 0x6e, 0x73, 0x3c, 0xfa, 0x3f, 0x3a,
0xd0, 0x20, 0x44, 0x36, 0xc2, 0xfa, 0x55, 0x61, 0xa8, 0xa8, 0x4d, 0x99, 0xad, 0x1f, 0x88, 0xa9,
0x7d, 0xf9, 0xc8, 0x5a, 0x0f, 0x5a, 0xb9, 0x58, 0x8b, 0x48, 0xcb, 0x8c, 0x9a, 0x6d, 0xf3, 0xfd,
0x1d, 0xeb, 0x88, 0x91, 0x4f, 0x93, 0x82, 0xce, 0xec, 0x13, 0x68, 0x4a, 0x22, 0x81, 0xa6, 0xf7,
0x2f, 0xd4, 0xd8, 0x10, 0x04, 0xcf, 0x44, 0x18, 0xcb, 0x74, 0xbd, 0xa5, 0x49, 0xb6, 0xf8, 0xfe,
0xee, 0x1f, 0x43, 0xd3, 0x0c, 0x9d, 0x0d, 0xa1, 0x96, 0x67, 0x91, 0x15, 0xde, 0x9b, 0x3b, 0x35,
0x18, 0xdd, 0x70, 0x74, 0xed, 0x0b, 0x71, 0xcb, 0x42, 0x7c, 0x0e, 0x50, 0x86, 0xfd, 0x3f, 0x0d,
0xfb, 0x3f, 0x38, 0xd0, 0xda, 0xe9, 0x95, 0xf5, 0x01, 0x92, 0x58, 0xa4, 0x3a, 0x59, 0x26, 0x22,
0x33, 0x9a, 0xe2, 0x15, 0x0b, 0x3b, 0x82, 0x46, 0xa8, 0x75, 0xb6, 0x9b, 0xe7, 0xbb, 0x55, 0xb1,
0x07, 0x27, 0xe8, 0x79, 0x92, 0xea, 0x6c, 0xcb, 0x4d, 0x54, 0xef, 0x31, 0x40, 0x69, 0xc4, 0xe1,
0xbd, 0x10, 0x5b, 0x8b, 0x8a, 0x47, 0x76, 0x1f, 0x1a, 0x2f, 0xc3, 0x75, 0x21, 0x6c, 0x51, 0xe6,
0xf2, 0x99, 0xfb, 0xd8, 0xf1, 0x7f, 0x72, 0xe1, 0x9e, 0x15, 0x3f, 0x7b, 0x08, 0xf7, 0x48, 0xfc,
0xb6, 0xa2, 0x9b, 0x3b, 0xdd, 0x85, 0xb0, 0xf1, 0x7e, 0xab, 0x2b, 0x35, 0x5a, 0x28, 0xb3, 0xdd,
0xb6, 0xc6, 0x72, 0xc7, 0x6b, 0xb1, 0x58, 0xda, 0xf5, 0xa5, 0x51, 0x9c, 0x89, 0x65, 0x92, 0x26,
0x3a, 0x91, 0x29, 0x47, 0x17, 0x7b, 0xb8, 0xeb, 0xba, 0x4e, 0x88, 0xef, 0x54, 0x11, 0xff, 0xd9,
0xf4, 0x0c, 0xbc, 0x4a, 0x9a, 0x1b, 0xba, 0xfe, 0xa0, 0xda, 0xb5, 0x4d, 0x49, 0x70, 0xe6, 0xdb,
0x53, 0xb2, 0xf0, 0x1f, 0xf8, 0xfb, 0x14, 0xa0, 0x84, 0xbc, 0xbd, 0x52, 0xfc, 0xbf, 0x1c, 0x80,
0xb9, 0xc2, 0x8d, 0x8c, 0x43, 0x5a, 0xe0, 0xc3, 0x64, 0x95, 0xca, 0x4c, 0x3c, 0x8b, 0xc2, 0xe8,
0xb9, 0xa0, 0xf7, 0x2d, 0xee, 0x19, 0xdb, 0x29, 0x9a, 0xd8, 0x09, 0x78, 0xb1, 0xc8, 0xa3, 0x2c,
0x51, 0x48, 0x98, 0x25, 0x7d, 0x80, 0x3d, 0x95, 0x38, 0xc1, 0x59, 0x19, 0x61, 0xb8, 0xaa, 0xbe,
0x61, 0x27, 0xf0, 0xd6, 0xb9, 0xcc, 0x5e, 0x88, 0xec, 0x59, 0x24, 0xd3, 0x5c, 0x67, 0x61, 0x92,
0x6a, 0x3b, 0x8f, 0xfb, 0x08, 0xf4, 0x0d, 0x39, 0x4f, 0xf7, 0x3e, 0xde, 0x39, 0xbf, 0x66, 0xe9,
0x1d, 0x43, 0xe7, 0x7a, 0x8e, 0x3b, 0xf1, 0xf5, 0x08, 0x3a, 0xd7, 0xb3, 0xb0, 0x01, 0x78, 0xb6,
0x2c, 0xbd, 0x55, 0x62, 0xb7, 0x0d, 0xc6, 0xf4, 0xf5, 0x56, 0x09, 0xff, 0x57, 0x07, 0xa0, 0xd4,
0x0a, 0xe6, 0x43, 0x21, 0xe1, 0x4e, 0x1f, 0x1a, 0xe1, 0xac, 0xa1, 0xb5, 0xb1, 0x14, 0x58, 0x62,
0x1e, 0x5c, 0xd5, 0x57, 0xb0, 0x63, 0x88, 0x2a, 0x36, 0x9f, 0xef, 0xef, 0x7e, 0xbf, 0xd3, 0xe7,
0x7b, 0x9f, 0xa1, 0xf7, 0x25, 0xbc, 0x71, 0x05, 0xee, 0x96, 0xd2, 0x2b, 0xc7, 0x54, 0x21, 0x64,
0xda, 0x79, 0x75, 0xd9, 0x77, 0x7e, 0xb9, 0xec, 0x3b, 0x7f, 0x5c, 0xf6, 0x9d, 0xef, 0xff, 0xec,
0x1f, 0x2c, 0x9a, 0xf4, 0xe7, 0xf9, 0xe8, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c, 0x43, 0xb9,
0x14, 0x7c, 0x07, 0x00, 0x00,
// 845 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x8e, 0x1b, 0x45,
0x10, 0xde, 0x19, 0xff, 0xc4, 0x53, 0xb3, 0x20, 0xd3, 0x44, 0x60, 0x59, 0x91, 0xd7, 0x0c, 0x08,
0x2d, 0x90, 0x9d, 0x95, 0x36, 0x12, 0x8a, 0x38, 0x44, 0x5a, 0xef, 0x46, 0xc2, 0xa0, 0xc8, 0x52,
0x83, 0xc4, 0x31, 0x1a, 0xcf, 0xb4, 0x9d, 0x51, 0xec, 0xe9, 0x56, 0x4f, 0x4f, 0x76, 0x7d, 0xe1,
0xc0, 0x13, 0x20, 0xf1, 0x16, 0xbc, 0x03, 0x9c, 0x73, 0xe4, 0x0a, 0x87, 0x80, 0x96, 0x67, 0xe0,
0x8e, 0xaa, 0xba, 0xed, 0x99, 0x2c, 0x41, 0xca, 0x0a, 0x4e, 0xae, 0xae, 0x9f, 0xaf, 0xaa, 0xbe,
0xaa, 0x1a, 0x43, 0x20, 0x55, 0x19, 0x2b, 0x2d, 0x8d, 0x64, 0xbe, 0x9a, 0x0f, 0x8f, 0x96, 0xb9,
0x79, 0x52, 0xcd, 0xe3, 0x54, 0xae, 0x8f, 0x97, 0x72, 0x29, 0x8f, 0xc9, 0x34, 0xaf, 0x16, 0xf4,
0xa2, 0x07, 0x49, 0x36, 0x24, 0xfa, 0xd9, 0x03, 0x7f, 0xa6, 0xd8, 0x7b, 0xd0, 0xcd, 0x0b, 0x55,
0x99, 0x72, 0xe0, 0x8d, 0x5b, 0x87, 0xe1, 0x49, 0x10, 0xab, 0x79, 0x3c, 0x45, 0x0d, 0x77, 0x06,
0x36, 0x86, 0xb6, 0xb8, 0x14, 0xe9, 0xc0, 0x1f, 0x7b, 0x87, 0xe1, 0x09, 0xa0, 0xc3, 0xc3, 0x4b,
0x91, 0xce, 0xd4, 0xe7, 0x7b, 0x9c, 0x2c, 0xec, 0x43, 0xe8, 0x96, 0xb2, 0xd2, 0xa9, 0x18, 0xb4,
0xc8, 0x67, 0x1f, 0x7d, 0xbe, 0x22, 0x0d, 0x79, 0x39, 0x2b, 0x22, 0xa5, 0x52, 0x6d, 0x06, 0xed,
0x1a, 0xe9, 0x4c, 0xaa, 0x8d, 0x45, 0x42, 0x0b, 0x7b, 0x1f, 0x3a, 0xf3, 0x2a, 0x5f, 0x65, 0x83,
0x0e, 0xb9, 0x84, 0xe8, 0x32, 0x41, 0x05, 0xf9, 0x58, 0xdb, 0xa4, 0x0d, 0xbe, 0x54, 0xd1, 0xb7,
0xd0, 0xa1, 0x3a, 0xd9, 0x17, 0xd0, 0xcd, 0xf2, 0xa5, 0x28, 0xcd, 0xc0, 0x1b, 0x7b, 0x87, 0xc1,
0xe4, 0xe4, 0xf9, 0x8b, 0x83, 0xbd, 0xdf, 0x5e, 0x1c, 0x7c, 0xdc, 0x20, 0x44, 0x2a, 0x51, 0xa4,
0xb2, 0x30, 0x49, 0x5e, 0x08, 0x5d, 0x1e, 0x2f, 0xe5, 0x91, 0x0d, 0x89, 0xcf, 0xe9, 0x87, 0x3b,
0x04, 0xf6, 0x11, 0x74, 0xf2, 0x22, 0x13, 0x97, 0xd4, 0x6c, 0x6b, 0xf2, 0xb6, 0x83, 0x0a, 0x67,
0x95, 0x51, 0x95, 0x99, 0xa2, 0x89, 0x5b, 0x8f, 0x68, 0x0a, 0x5d, 0x4b, 0x03, 0xbb, 0x03, 0xed,
0xb5, 0x30, 0x09, 0xa5, 0x0f, 0x4f, 0x7a, 0x58, 0xf3, 0x23, 0x61, 0x12, 0x4e, 0x5a, 0x64, 0x78,
0x2d, 0xab, 0xc2, 0x94, 0x03, 0xbf, 0x66, 0xf8, 0x11, 0x6a, 0xb8, 0x33, 0x44, 0x1c, 0xda, 0x18,
0xc0, 0x18, 0xb4, 0x13, 0xbd, 0xb4, 0xa3, 0x08, 0x38, 0xc9, 0xac, 0x0f, 0x2d, 0x51, 0x3c, 0xa3,
0xd8, 0x80, 0xa3, 0x88, 0x9a, 0xf4, 0x22, 0x23, 0xaa, 0x03, 0x8e, 0x22, 0xc6, 0x55, 0xa5, 0xd0,
0xc4, 0x6b, 0xc0, 0x49, 0x8e, 0x7e, 0xf4, 0xa0, 0x43, 0x59, 0xd8, 0x21, 0xf6, 0xa4, 0x2a, 0x4b,
0x4f, 0x6b, 0xc2, 0x5c, 0x4f, 0x40, 0xec, 0xed, 0x5a, 0x42, 0x26, 0x87, 0xd0, 0x2b, 0xc5, 0x4a,
0xa4, 0x46, 0x6a, 0x22, 0x20, 0xe0, 0xbb, 0x37, 0xe6, 0xc8, 0x90, 0x63, 0x9b, 0x96, 0x64, 0xf6,
0x09, 0x74, 0x25, 0x11, 0x43, 0x99, 0xff, 0x85, 0x2e, 0xe7, 0x82, 0xe0, 0x5a, 0x24, 0x99, 0x2c,
0x56, 0x1b, 0x9a, 0x6e, 0x8f, 0xef, 0xde, 0xd1, 0x03, 0xe8, 0xda, 0x45, 0x60, 0x63, 0x68, 0x95,
0x3a, 0x75, 0xcb, 0xf8, 0xe6, 0x76, 0x43, 0xec, 0x2e, 0x71, 0x34, 0xed, 0x0a, 0xf1, 0xeb, 0x42,
0x22, 0x0e, 0x50, 0xbb, 0xfd, 0x3f, 0x0d, 0x47, 0x3f, 0x78, 0xd0, 0xdb, 0xee, 0x30, 0x1b, 0x01,
0xe4, 0x99, 0x28, 0x4c, 0xbe, 0xc8, 0x85, 0xb6, 0x7b, 0xc6, 0x1b, 0x1a, 0x76, 0x04, 0x9d, 0xc4,
0x18, 0xbd, 0x9d, 0xf1, 0xbb, 0xcd, 0x03, 0x88, 0x4f, 0xd1, 0xf2, 0xb0, 0x30, 0x7a, 0xc3, 0xad,
0xd7, 0xf0, 0x3e, 0x40, 0xad, 0xc4, 0x81, 0x3e, 0x15, 0x1b, 0x87, 0x8a, 0x22, 0xbb, 0x0d, 0x9d,
0x67, 0xc9, 0xaa, 0x12, 0xae, 0x28, 0xfb, 0xf8, 0xcc, 0xbf, 0xef, 0x45, 0x3f, 0xf9, 0x70, 0xcb,
0x1d, 0x04, 0xbb, 0x0b, 0xb7, 0xe8, 0x20, 0x5c, 0x45, 0xaf, 0xee, 0x74, 0xeb, 0xc2, 0x8e, 0x77,
0x97, 0xde, 0xa8, 0xd1, 0x41, 0xd9, 0x8b, 0x77, 0x35, 0xd6, 0x77, 0xdf, 0xca, 0xc4, 0xc2, 0x9d,
0x34, 0x8d, 0xe2, 0x5c, 0x2c, 0xf2, 0x22, 0x37, 0xb9, 0x2c, 0x38, 0x9a, 0xd8, 0xdd, 0x6d, 0xd7,
0x6d, 0x42, 0x7c, 0xa7, 0x89, 0xf8, 0xcf, 0xa6, 0xa7, 0x10, 0x36, 0xd2, 0xbc, 0xa2, 0xeb, 0x0f,
0x9a, 0x5d, 0xbb, 0x94, 0x04, 0x67, 0xbf, 0x47, 0x35, 0x0b, 0xff, 0x81, 0xbf, 0x4f, 0x01, 0x6a,
0xc8, 0xd7, 0xdf, 0x94, 0xe8, 0x2f, 0x0f, 0x60, 0xa6, 0xf0, 0x4a, 0xb3, 0x84, 0x8e, 0x7a, 0x3f,
0x5f, 0x16, 0x52, 0x8b, 0xc7, 0x69, 0x92, 0x3e, 0x11, 0x14, 0xdf, 0xe3, 0xa1, 0xd5, 0x9d, 0xa1,
0x8a, 0x9d, 0x42, 0x98, 0x89, 0x32, 0xd5, 0xb9, 0x42, 0xc2, 0x1c, 0xe9, 0x07, 0xd8, 0x53, 0x8d,
0x13, 0x9f, 0xd7, 0x1e, 0x96, 0xab, 0x66, 0x0c, 0x3b, 0x85, 0xb7, 0x2e, 0xa4, 0x7e, 0x2a, 0xf4,
0xe3, 0x54, 0x16, 0xa5, 0xd1, 0x49, 0x5e, 0x18, 0x37, 0x8f, 0xdb, 0x08, 0xf4, 0x0d, 0x19, 0xcf,
0x76, 0x36, 0xde, 0xbf, 0xb8, 0xa6, 0x19, 0x3e, 0x80, 0xfe, 0xf5, 0x1c, 0x37, 0xe2, 0xeb, 0x1e,
0xf4, 0xaf, 0x67, 0x61, 0x07, 0x10, 0xba, 0xb2, 0xcc, 0x46, 0x89, 0xed, 0x35, 0x58, 0xd5, 0xd7,
0x1b, 0x25, 0xa2, 0x5f, 0x3d, 0x80, 0x7a, 0x57, 0x30, 0x1f, 0x2e, 0x12, 0xde, 0xf4, 0xbe, 0x5d,
0x9c, 0x15, 0xf4, 0xd6, 0x8e, 0x02, 0x47, 0xcc, 0x9d, 0x97, 0xf7, 0x2b, 0xde, 0x32, 0x44, 0x15,
0xdb, 0x4f, 0xfa, 0x77, 0xbf, 0xdf, 0xe8, 0x93, 0xbe, 0xcb, 0x30, 0xfc, 0x12, 0xde, 0x78, 0x09,
0xee, 0x35, 0x57, 0xaf, 0x1e, 0x53, 0x83, 0x90, 0x49, 0xff, 0xf9, 0xd5, 0xc8, 0xfb, 0xe5, 0x6a,
0xe4, 0xfd, 0x71, 0x35, 0xf2, 0xbe, 0xff, 0x73, 0xb4, 0x37, 0xef, 0xd2, 0x1f, 0xea, 0xbd, 0xbf,
0x03, 0x00, 0x00, 0xff, 0xff, 0x26, 0xbe, 0xb0, 0x53, 0x90, 0x07, 0x00, 0x00,
}

View File

@ -30,6 +30,7 @@ message Meta {
repeated string args = 1;
repeated string env = 2;
string cwd = 3;
string user = 4;
}
message Mount {