podman run 源码层次
cmd/podman/containers/run.go
pkg/domain/entities/engine_container.go ContainerRun
pkg/domain/infra/abi/containers.go ContainerEngine.ContainerRun
ContainerEngine有两种,一个是abi就是本地调用,一个是tunnel就是podman http服务
创建container
pkg/specgen/generate/container_create.go MakeContainer 准备oci配置 spec.Spec
generate.ExecuteCreate
—> libpod/runtime_ctr.go NewContainer
——> libpod/runtime_ctr.go newContainer 生成container对象
———> initContainerVariables 初始化container对象的基本信息
———> libpod/runtime_ctr.go setupContainer
————> libpod/container_api.go setupStorage
—————> libpod/container_internal.go setupStorage
启动container:
detach模式下:
pkg/domain/infra/abi/containers.go ContainerEngine.ContainerRun
libpod/container_api.go Start
libpod/container_internal.go prepareToStart
libpod/container_internal.go init
libpod/container_internal.go saveSpec 保存OCI的config.json
libpod/oci.go CreateContainer 启动conmon进程
libpod/oci_conmon_linux.go CreateContainer
libpod/oci_conmon_linux.go createOCIContainer
�
libpod/container_internal.go Start
libpod/oci.go StartContainer
libpod/oci_conmon_linux.go StartContainer
attach模式下:
terminal_linux.go
libpod/container_api.go StartAndAttach
libpod/oci_attach_linux.go attach
libpod/container_internal.go start
�
conmon层
libpod/oci.go 定义了OCIRuntime
libpod/oci_conmon_linux.go 启动oci容器的conmon/shim
创建容器
// CreateContainer creates a container.
func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error {
// always make the run dir accessible to the current user so that the PID files can be read without
// being in the rootless user namespace.
if err := makeAccessible(ctr.state.RunDir, 0, 0); err != nil {
return err
}
if !hasCurrentUserMapped(ctr) {
for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.Engine.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.Engine.VolumePath} {
if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil {
return err
}
}
// if we are running a non privileged container, be sure to umount some kernel paths so they are not
// bind mounted inside the container at all.
if !ctr.config.Privileged && !rootless.IsRootless() {
ch := make(chan error)
go func() {
runtime.LockOSThread()
err := func() error {
fd, err := os.Open(fmt.Sprintf("/proc/%d/task/%d/ns/mnt", os.Getpid(), unix.Gettid()))
if err != nil {
return err
}
defer errorhandling.CloseQuiet(fd)
// create a new mountns on the current thread
if err = unix.Unshare(unix.CLONE_NEWNS); err != nil {
return err
}
defer func() {
if err := unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS); err != nil {
logrus.Errorf("unable to clone new namespace: %q", err)
}
}()
// don't spread our mounts around. We are setting only /sys to be slave
// so that the cleanup process is still able to umount the storage and the
// changes are propagated to the host.
err = unix.Mount("/sys", "/sys", "none", unix.MS_REC|unix.MS_SLAVE, "")
if err != nil {
return errors.Wrapf(err, "cannot make /sys slave")
}
mounts, err := pmount.GetMounts()
if err != nil {
return err
}
for _, m := range mounts {
if !strings.HasPrefix(m.Mountpoint, "/sys/kernel") {
continue
}
err = unix.Unmount(m.Mountpoint, 0)
if err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "cannot unmount %s", m.Mountpoint)
}
}
return r.createOCIContainer(ctr, restoreOptions)
}()
ch <- err
}()
err := <-ch
return err
}
}
return r.createOCIContainer(ctr, restoreOptions)
}
启动容器
// StartContainer starts the given container.
// Sets time the container was started, but does not save it.
func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error {
// TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers?
runtimeDir, err := util.GetRuntimeDir()
if err != nil {
return err
}
env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
if ctr.config.SdNotifyMode == define.SdNotifyModeContainer {
if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
env = append(env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
}
}
if path, ok := os.LookupEnv("PATH"); ok {
env = append(env, fmt.Sprintf("PATH=%s", path))
}
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "start", ctr.ID())...); err != nil {
return err
}
ctr.state.StartedTime = time.Now()
return nil
}