2
0

docker.go 2.7 KB

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