docker create 源码解读
🥏

docker create 源码解读

 
// 文件位置:/moby-master/daemon/create.go // Create creates a new container from the given configuration with a given name. // 创建一个新的容器,并指定其名称 func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr error) { // 设置基础参数 var ( ctr *container.Container img *image.Image imgID image.ID err error os = runtime.GOOS ) // 判断指定的镜像路径名称是否为空 if opts.params.Config.Image != "" { // 获取镜像和镜像ID img, err = daemon.imageService.GetImage(opts.params.Config.Image, opts.params.Platform) if err != nil { return nil, err } // 获取镜像对应的操作系统,如果为nil则返回主机对应的操作系统 os = img.OperatingSystem() // 确定主机是否支持操作系统。 if !system.IsOSSupported(os) { return nil, system.ErrNotSupportedOperatingSystem } imgID = img.ID() } else if isWindows { // 判断是否为windows系统 os = "linux" // 'scratch' case. } // On WCOW, if are not being invoked by the builder to create this container (where // ignoreImagesArgEscaped will be true) - if the image already has its arguments escaped, // ensure that this is replicated across to the created container to avoid double-escaping // of the arguments/command line when the runtime attempts to run the container. // 在 WCOW 上,如果没有被构建器调用来创建这个容器(其中 ignoreImagesArgEscaped 将为真) // - 如果image已经转义了它的参数,请确保将其复制到创建的容器以避免参数的双重转义/运行时尝试运行容器时的命令行。 if os == "windows" && !opts.ignoreImagesArgsEscaped && img != nil && img.RunConfig().ArgsEscaped { opts.params.Config.ArgsEscaped = true } // 合并并验证配置信息 if err := daemon.mergeAndVerifyConfig(opts.params.Config, img); err != nil { return nil, errdefs.InvalidParameter(err) } // 合并并验证日志配置信息 if err := daemon.mergeAndVerifyLogConfig(&opts.params.HostConfig.LogConfig); err != nil { return nil, errdefs.InvalidParameter(err) } // 初始化一个容器对象 if ctr, err = daemon.newContainer(opts.params.Name, os, opts.params.Config, opts.params.HostConfig, imgID, opts.managed); err != nil { return nil, err } // 函数结束时,清理容器对象 defer func() { if retErr != nil { err = daemon.cleanupContainer(ctr, types.ContainerRmConfig{ ForceRemove: true, RemoveVolume: true, }) if err != nil { logrus.WithError(err).Error("failed to cleanup container on create error") } } }() // 设置安全项 if err := daemon.setSecurityOptions(ctr, opts.params.HostConfig); err != nil { return nil, err } ctr.HostConfig.StorageOpt = opts.params.HostConfig.StorageOpt // Set RWLayer for container after mount labels have been set // 设置挂载标签后为容器设置 读写层 -- 此部分是容器的基础知识 Union FS base镜像为只读层(下层),容器为读写层(上层),合并后就是最终容器的文件系统(上层的内容会覆盖下层内容) rwLayer, err := daemon.imageService.CreateLayer(ctr, setupInitLayer(daemon.idMapping)) if err != nil { return nil, errdefs.System(err) } ctr.RWLayer = rwLayer // 返回当前进程的标识 current := idtools.CurrentIdentity() // 创建目录 if err := idtools.MkdirAndChown(ctr.Root, 0710, idtools.Identity{UID: current.UID, GID: daemon.IdentityMapping().RootPair().GID}); err != nil { return nil, err } // 检查目录 if err := idtools.MkdirAndChown(ctr.CheckpointDir(), 0700, current); err != nil { return nil, err } if err := daemon.setHostConfig(ctr, opts.params.HostConfig); err != nil { return nil, err } if err := daemon.createContainerOSSpecificSettings(ctr, opts.params.Config, opts.params.HostConfig); err != nil { return nil, err } var endpointsConfigs map[string]*networktypes.EndpointSettings if opts.params.NetworkingConfig != nil { endpointsConfigs = opts.params.NetworkingConfig.EndpointsConfig } // Make sure NetworkMode has an acceptable value. We do this to ensure // backwards API compatibility. runconfig.SetDefaultNetModeIfBlank(ctr.HostConfig) daemon.updateContainerNetworkSettings(ctr, endpointsConfigs) if err := daemon.Register(ctr); err != nil { return nil, err } stateCtr.set(ctr.ID, "stopped") daemon.LogContainerEvent(ctr, "create") return ctr, nil }