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

创建容器

  1. // CreateContainer creates a container.
  2. func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) error {
  3. // always make the run dir accessible to the current user so that the PID files can be read without
  4. // being in the rootless user namespace.
  5. if err := makeAccessible(ctr.state.RunDir, 0, 0); err != nil {
  6. return err
  7. }
  8. if !hasCurrentUserMapped(ctr) {
  9. for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.Engine.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.Engine.VolumePath} {
  10. if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil {
  11. return err
  12. }
  13. }
  14. // if we are running a non privileged container, be sure to umount some kernel paths so they are not
  15. // bind mounted inside the container at all.
  16. if !ctr.config.Privileged && !rootless.IsRootless() {
  17. ch := make(chan error)
  18. go func() {
  19. runtime.LockOSThread()
  20. err := func() error {
  21. fd, err := os.Open(fmt.Sprintf("/proc/%d/task/%d/ns/mnt", os.Getpid(), unix.Gettid()))
  22. if err != nil {
  23. return err
  24. }
  25. defer errorhandling.CloseQuiet(fd)
  26. // create a new mountns on the current thread
  27. if err = unix.Unshare(unix.CLONE_NEWNS); err != nil {
  28. return err
  29. }
  30. defer func() {
  31. if err := unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS); err != nil {
  32. logrus.Errorf("unable to clone new namespace: %q", err)
  33. }
  34. }()
  35. // don't spread our mounts around. We are setting only /sys to be slave
  36. // so that the cleanup process is still able to umount the storage and the
  37. // changes are propagated to the host.
  38. err = unix.Mount("/sys", "/sys", "none", unix.MS_REC|unix.MS_SLAVE, "")
  39. if err != nil {
  40. return errors.Wrapf(err, "cannot make /sys slave")
  41. }
  42. mounts, err := pmount.GetMounts()
  43. if err != nil {
  44. return err
  45. }
  46. for _, m := range mounts {
  47. if !strings.HasPrefix(m.Mountpoint, "/sys/kernel") {
  48. continue
  49. }
  50. err = unix.Unmount(m.Mountpoint, 0)
  51. if err != nil && !os.IsNotExist(err) {
  52. return errors.Wrapf(err, "cannot unmount %s", m.Mountpoint)
  53. }
  54. }
  55. return r.createOCIContainer(ctr, restoreOptions)
  56. }()
  57. ch <- err
  58. }()
  59. err := <-ch
  60. return err
  61. }
  62. }
  63. return r.createOCIContainer(ctr, restoreOptions)
  64. }

启动容器

  1. // StartContainer starts the given container.
  2. // Sets time the container was started, but does not save it.
  3. func (r *ConmonOCIRuntime) StartContainer(ctr *Container) error {
  4. // TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers?
  5. runtimeDir, err := util.GetRuntimeDir()
  6. if err != nil {
  7. return err
  8. }
  9. env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
  10. if ctr.config.SdNotifyMode == define.SdNotifyModeContainer {
  11. if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok {
  12. env = append(env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify))
  13. }
  14. }
  15. if path, ok := os.LookupEnv("PATH"); ok {
  16. env = append(env, fmt.Sprintf("PATH=%s", path))
  17. }
  18. if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "start", ctr.ID())...); err != nil {
  19. return err
  20. }
  21. ctr.state.StartedTime = time.Now()
  22. return nil
  23. }