github.com/moby/docker@v26.1.3+incompatible/daemon/names.go (about) 1 package daemon // import "github.com/docker/docker/daemon" 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 8 "github.com/containerd/log" 9 "github.com/docker/docker/container" 10 "github.com/docker/docker/daemon/names" 11 "github.com/docker/docker/errdefs" 12 "github.com/docker/docker/pkg/namesgenerator" 13 "github.com/docker/docker/pkg/stringid" 14 "github.com/pkg/errors" 15 ) 16 17 var ( 18 validContainerNameChars = names.RestrictedNameChars 19 validContainerNamePattern = names.RestrictedNamePattern 20 ) 21 22 func (daemon *Daemon) registerName(container *container.Container) error { 23 if daemon.Exists(container.ID) { 24 return fmt.Errorf("Container is already loaded") 25 } 26 if err := validateID(container.ID); err != nil { 27 return err 28 } 29 if container.Name == "" { 30 name, err := daemon.generateAndReserveName(container.ID) 31 if err != nil { 32 return err 33 } 34 container.Name = name 35 return nil 36 } 37 return daemon.containersReplica.ReserveName(container.Name, container.ID) 38 } 39 40 func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { 41 var ( 42 err error 43 id = stringid.GenerateRandomID() 44 ) 45 46 if name == "" { 47 if name, err = daemon.generateAndReserveName(id); err != nil { 48 return "", "", err 49 } 50 return id, name, nil 51 } 52 53 if name, err = daemon.reserveName(id, name); err != nil { 54 return "", "", err 55 } 56 57 return id, name, nil 58 } 59 60 func (daemon *Daemon) reserveName(id, name string) (string, error) { 61 if !validContainerNamePattern.MatchString(strings.TrimPrefix(name, "/")) { 62 return "", errdefs.InvalidParameter(errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)) 63 } 64 if name[0] != '/' { 65 name = "/" + name 66 } 67 68 if err := daemon.containersReplica.ReserveName(name, id); err != nil { 69 if errors.Is(err, container.ErrNameReserved) { 70 id, err := daemon.containersReplica.Snapshot().GetID(name) 71 if err != nil { 72 log.G(context.TODO()).Errorf("got unexpected error while looking up reserved name: %v", err) 73 return "", err 74 } 75 return "", nameConflictError{id: id, name: name} 76 } 77 return "", errors.Wrapf(err, "error reserving name: %q", name) 78 } 79 return name, nil 80 } 81 82 func (daemon *Daemon) releaseName(name string) { 83 daemon.containersReplica.ReleaseName(name) 84 } 85 86 func (daemon *Daemon) generateAndReserveName(id string) (string, error) { 87 var name string 88 for i := 0; i < 6; i++ { 89 name = namesgenerator.GetRandomName(i) 90 if name[0] != '/' { 91 name = "/" + name 92 } 93 94 if err := daemon.containersReplica.ReserveName(name, id); err != nil { 95 if errors.Is(err, container.ErrNameReserved) { 96 continue 97 } 98 return "", err 99 } 100 return name, nil 101 } 102 103 name = "/" + stringid.TruncateID(id) 104 if err := daemon.containersReplica.ReserveName(name, id); err != nil { 105 return "", err 106 } 107 return name, nil 108 } 109 110 func validateID(id string) error { 111 if id == "" { 112 return fmt.Errorf("Invalid empty id") 113 } 114 return nil 115 }