docker.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package worker
  2. import (
  3. "fmt"
  4. "os"
  5. "time"
  6. "github.com/codeskyblue/go-sh"
  7. )
  8. type dockerHook struct {
  9. emptyHook
  10. image string
  11. volumes []string
  12. options []string
  13. }
  14. func newDockerHook(p mirrorProvider, gCfg dockerConfig, mCfg mirrorConfig) *dockerHook {
  15. volumes := []string{}
  16. volumes = append(volumes, gCfg.Volumes...)
  17. volumes = append(volumes, mCfg.DockerVolumes...)
  18. if len(mCfg.ExcludeFile) > 0 {
  19. arg := fmt.Sprintf("%s:%s:ro", mCfg.ExcludeFile, mCfg.ExcludeFile)
  20. volumes = append(volumes, arg)
  21. }
  22. options := []string{}
  23. options = append(options, gCfg.Options...)
  24. options = append(options, mCfg.DockerOptions...)
  25. return &dockerHook{
  26. emptyHook: emptyHook{
  27. provider: p,
  28. },
  29. image: mCfg.DockerImage,
  30. volumes: volumes,
  31. options: options,
  32. }
  33. }
  34. func (d *dockerHook) preExec() error {
  35. p := d.provider
  36. logDir := p.LogDir()
  37. logFile := p.LogFile()
  38. workingDir := p.WorkingDir()
  39. if _, err := os.Stat(workingDir); os.IsNotExist(err) {
  40. logger.Debugf("Making dir %s", workingDir)
  41. if err = os.MkdirAll(workingDir, 0755); err != nil {
  42. return fmt.Errorf("Error making dir %s: %s", workingDir, err.Error())
  43. }
  44. }
  45. // Override workingDir
  46. ctx := p.EnterContext()
  47. ctx.Set(
  48. "volumes", []string{
  49. fmt.Sprintf("%s:%s", logDir, logDir),
  50. fmt.Sprintf("%s:%s", logFile, logFile),
  51. fmt.Sprintf("%s:%s", workingDir, workingDir),
  52. },
  53. )
  54. return nil
  55. }
  56. func (d *dockerHook) postExec() error {
  57. // sh.Command(
  58. // "docker", "rm", "-f", d.Name(),
  59. // ).Run()
  60. name := d.Name()
  61. retry := 10
  62. for ; retry > 0; retry-- {
  63. out, err := sh.Command(
  64. "docker", "ps", "-a",
  65. "--filter", "name=^"+name+"$",
  66. "--format", "{{.Status}}",
  67. ).Output()
  68. if err != nil {
  69. logger.Errorf("docker ps failed: %v", err)
  70. break
  71. }
  72. if len(out) == 0 {
  73. break
  74. }
  75. logger.Debugf("container %s still exists: '%s'", name, string(out))
  76. time.Sleep(1 * time.Second)
  77. }
  78. if retry == 0 {
  79. logger.Warningf("container %s not removed automatically, next sync may fail", name)
  80. }
  81. d.provider.ExitContext()
  82. return nil
  83. }
  84. // Volumes returns the configured volumes and
  85. // runtime-needed volumes, including mirror dirs
  86. // and log files
  87. func (d *dockerHook) Volumes() []string {
  88. vols := make([]string, len(d.volumes))
  89. copy(vols, d.volumes)
  90. p := d.provider
  91. ctx := p.Context()
  92. if ivs, ok := ctx.Get("volumes"); ok {
  93. vs := ivs.([]string)
  94. vols = append(vols, vs...)
  95. }
  96. return vols
  97. }
  98. func (d *dockerHook) LogFile() string {
  99. p := d.provider
  100. ctx := p.Context()
  101. if iv, ok := ctx.Get(_LogFileKey + ":docker"); ok {
  102. v := iv.(string)
  103. return v
  104. }
  105. return p.LogFile()
  106. }
  107. func (d *dockerHook) Name() string {
  108. p := d.provider
  109. return "tunasync-job-" + p.Name()
  110. }