| ... | ... |
@@ -563,274 +563,270 @@ func (container *Container) Attach(stdin io.ReadCloser, stdinCloser io.Closer, s |
| 563 | 563 |
}) |
| 564 | 564 |
} |
| 565 | 565 |
|
| 566 |
-func (container *Container) Start(hostConfig *HostConfig) error {
|
|
| 566 |
+func (container *Container) Start(hostConfig *HostConfig) (err error) {
|
|
| 567 | 567 |
container.State.Lock() |
| 568 | 568 |
defer container.State.Unlock() |
| 569 |
- |
|
| 570 |
- startFct := func(hostConfig *HostConfig) error {
|
|
| 571 |
- |
|
| 572 |
- if hostConfig == nil { // in docker start of docker restart we want to reuse previous HostConfigFile
|
|
| 573 |
- hostConfig, _ = container.ReadHostConfig() |
|
| 569 |
+ defer func() {
|
|
| 570 |
+ if err != nil {
|
|
| 571 |
+ container.cleanup() |
|
| 574 | 572 |
} |
| 573 |
+ }() |
|
| 575 | 574 |
|
| 576 |
- if container.State.Running {
|
|
| 577 |
- return fmt.Errorf("The container %s is already running.", container.ID)
|
|
| 578 |
- } |
|
| 579 |
- if err := container.EnsureMounted(); err != nil {
|
|
| 575 |
+ if hostConfig == nil { // in docker start of docker restart we want to reuse previous HostConfigFile
|
|
| 576 |
+ hostConfig, _ = container.ReadHostConfig() |
|
| 577 |
+ } |
|
| 578 |
+ |
|
| 579 |
+ if container.State.Running {
|
|
| 580 |
+ return fmt.Errorf("The container %s is already running.", container.ID)
|
|
| 581 |
+ } |
|
| 582 |
+ if err := container.EnsureMounted(); err != nil {
|
|
| 583 |
+ return err |
|
| 584 |
+ } |
|
| 585 |
+ if container.runtime.networkManager.disabled {
|
|
| 586 |
+ container.Config.NetworkDisabled = true |
|
| 587 |
+ } else {
|
|
| 588 |
+ if err := container.allocateNetwork(); err != nil {
|
|
| 580 | 589 |
return err |
| 581 | 590 |
} |
| 582 |
- if container.runtime.networkManager.disabled {
|
|
| 583 |
- container.Config.NetworkDisabled = true |
|
| 584 |
- } else {
|
|
| 585 |
- if err := container.allocateNetwork(); err != nil {
|
|
| 586 |
- return err |
|
| 587 |
- } |
|
| 588 |
- } |
|
| 591 |
+ } |
|
| 589 | 592 |
|
| 590 |
- // Make sure the config is compatible with the current kernel |
|
| 591 |
- if container.Config.Memory > 0 && !container.runtime.capabilities.MemoryLimit {
|
|
| 592 |
- log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
|
| 593 |
- container.Config.Memory = 0 |
|
| 594 |
- } |
|
| 595 |
- if container.Config.Memory > 0 && !container.runtime.capabilities.SwapLimit {
|
|
| 596 |
- log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
| 597 |
- container.Config.MemorySwap = -1 |
|
| 598 |
- } |
|
| 593 |
+ // Make sure the config is compatible with the current kernel |
|
| 594 |
+ if container.Config.Memory > 0 && !container.runtime.capabilities.MemoryLimit {
|
|
| 595 |
+ log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n")
|
|
| 596 |
+ container.Config.Memory = 0 |
|
| 597 |
+ } |
|
| 598 |
+ if container.Config.Memory > 0 && !container.runtime.capabilities.SwapLimit {
|
|
| 599 |
+ log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n")
|
|
| 600 |
+ container.Config.MemorySwap = -1 |
|
| 601 |
+ } |
|
| 599 | 602 |
|
| 600 |
- if container.runtime.capabilities.IPv4ForwardingDisabled {
|
|
| 601 |
- log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work")
|
|
| 602 |
- } |
|
| 603 |
+ if container.runtime.capabilities.IPv4ForwardingDisabled {
|
|
| 604 |
+ log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work")
|
|
| 605 |
+ } |
|
| 603 | 606 |
|
| 604 |
- // Create the requested bind mounts |
|
| 605 |
- binds := make(map[string]BindMap) |
|
| 606 |
- // Define illegal container destinations |
|
| 607 |
- illegalDsts := []string{"/", "."}
|
|
| 608 |
- |
|
| 609 |
- for _, bind := range hostConfig.Binds {
|
|
| 610 |
- // FIXME: factorize bind parsing in parseBind |
|
| 611 |
- var src, dst, mode string |
|
| 612 |
- arr := strings.Split(bind, ":") |
|
| 613 |
- if len(arr) == 2 {
|
|
| 614 |
- src = arr[0] |
|
| 615 |
- dst = arr[1] |
|
| 616 |
- mode = "rw" |
|
| 617 |
- } else if len(arr) == 3 {
|
|
| 618 |
- src = arr[0] |
|
| 619 |
- dst = arr[1] |
|
| 620 |
- mode = arr[2] |
|
| 621 |
- } else {
|
|
| 622 |
- return fmt.Errorf("Invalid bind specification: %s", bind)
|
|
| 623 |
- } |
|
| 607 |
+ // Create the requested bind mounts |
|
| 608 |
+ binds := make(map[string]BindMap) |
|
| 609 |
+ // Define illegal container destinations |
|
| 610 |
+ illegalDsts := []string{"/", "."}
|
|
| 624 | 611 |
|
| 625 |
- // Bail if trying to mount to an illegal destination |
|
| 626 |
- for _, illegal := range illegalDsts {
|
|
| 627 |
- if dst == illegal {
|
|
| 628 |
- return fmt.Errorf("Illegal bind destination: %s", dst)
|
|
| 629 |
- } |
|
| 630 |
- } |
|
| 612 |
+ for _, bind := range hostConfig.Binds {
|
|
| 613 |
+ // FIXME: factorize bind parsing in parseBind |
|
| 614 |
+ var src, dst, mode string |
|
| 615 |
+ arr := strings.Split(bind, ":") |
|
| 616 |
+ if len(arr) == 2 {
|
|
| 617 |
+ src = arr[0] |
|
| 618 |
+ dst = arr[1] |
|
| 619 |
+ mode = "rw" |
|
| 620 |
+ } else if len(arr) == 3 {
|
|
| 621 |
+ src = arr[0] |
|
| 622 |
+ dst = arr[1] |
|
| 623 |
+ mode = arr[2] |
|
| 624 |
+ } else {
|
|
| 625 |
+ return fmt.Errorf("Invalid bind specification: %s", bind)
|
|
| 626 |
+ } |
|
| 631 | 627 |
|
| 632 |
- bindMap := BindMap{
|
|
| 633 |
- SrcPath: src, |
|
| 634 |
- DstPath: dst, |
|
| 635 |
- Mode: mode, |
|
| 628 |
+ // Bail if trying to mount to an illegal destination |
|
| 629 |
+ for _, illegal := range illegalDsts {
|
|
| 630 |
+ if dst == illegal {
|
|
| 631 |
+ return fmt.Errorf("Illegal bind destination: %s", dst)
|
|
| 636 | 632 |
} |
| 637 |
- binds[path.Clean(dst)] = bindMap |
|
| 638 | 633 |
} |
| 639 | 634 |
|
| 640 |
- if container.Volumes == nil || len(container.Volumes) == 0 {
|
|
| 641 |
- container.Volumes = make(map[string]string) |
|
| 642 |
- container.VolumesRW = make(map[string]bool) |
|
| 635 |
+ bindMap := BindMap{
|
|
| 636 |
+ SrcPath: src, |
|
| 637 |
+ DstPath: dst, |
|
| 638 |
+ Mode: mode, |
|
| 643 | 639 |
} |
| 640 |
+ binds[path.Clean(dst)] = bindMap |
|
| 641 |
+ } |
|
| 644 | 642 |
|
| 645 |
- // Apply volumes from another container if requested |
|
| 646 |
- if container.Config.VolumesFrom != "" {
|
|
| 647 |
- volumes := strings.Split(container.Config.VolumesFrom, ",") |
|
| 648 |
- for _, v := range volumes {
|
|
| 649 |
- c := container.runtime.Get(v) |
|
| 650 |
- if c == nil {
|
|
| 651 |
- return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
|
|
| 652 |
- } |
|
| 653 |
- for volPath, id := range c.Volumes {
|
|
| 654 |
- if _, exists := container.Volumes[volPath]; exists {
|
|
| 655 |
- continue |
|
| 656 |
- } |
|
| 657 |
- if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
|
| 658 |
- return err |
|
| 659 |
- } |
|
| 660 |
- container.Volumes[volPath] = id |
|
| 661 |
- if isRW, exists := c.VolumesRW[volPath]; exists {
|
|
| 662 |
- container.VolumesRW[volPath] = isRW |
|
| 663 |
- } |
|
| 664 |
- } |
|
| 665 |
- |
|
| 666 |
- } |
|
| 667 |
- } |
|
| 643 |
+ if container.Volumes == nil || len(container.Volumes) == 0 {
|
|
| 644 |
+ container.Volumes = make(map[string]string) |
|
| 645 |
+ container.VolumesRW = make(map[string]bool) |
|
| 646 |
+ } |
|
| 668 | 647 |
|
| 669 |
- // Create the requested volumes if they don't exist |
|
| 670 |
- for volPath := range container.Config.Volumes {
|
|
| 671 |
- volPath = path.Clean(volPath) |
|
| 672 |
- // Skip existing volumes |
|
| 673 |
- if _, exists := container.Volumes[volPath]; exists {
|
|
| 674 |
- continue |
|
| 648 |
+ // Apply volumes from another container if requested |
|
| 649 |
+ if container.Config.VolumesFrom != "" {
|
|
| 650 |
+ volumes := strings.Split(container.Config.VolumesFrom, ",") |
|
| 651 |
+ for _, v := range volumes {
|
|
| 652 |
+ c := container.runtime.Get(v) |
|
| 653 |
+ if c == nil {
|
|
| 654 |
+ return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID)
|
|
| 675 | 655 |
} |
| 676 |
- var srcPath string |
|
| 677 |
- var isBindMount bool |
|
| 678 |
- srcRW := false |
|
| 679 |
- // If an external bind is defined for this volume, use that as a source |
|
| 680 |
- if bindMap, exists := binds[volPath]; exists {
|
|
| 681 |
- isBindMount = true |
|
| 682 |
- srcPath = bindMap.SrcPath |
|
| 683 |
- if strings.ToLower(bindMap.Mode) == "rw" {
|
|
| 684 |
- srcRW = true |
|
| 656 |
+ for volPath, id := range c.Volumes {
|
|
| 657 |
+ if _, exists := container.Volumes[volPath]; exists {
|
|
| 658 |
+ continue |
|
| 685 | 659 |
} |
| 686 |
- // Otherwise create an directory in $ROOT/volumes/ and use that |
|
| 687 |
- } else {
|
|
| 688 |
- c, err := container.runtime.volumes.Create(nil, container, "", "", nil) |
|
| 689 |
- if err != nil {
|
|
| 660 |
+ if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
|
|
| 690 | 661 |
return err |
| 691 | 662 |
} |
| 692 |
- srcPath, err = c.layer() |
|
| 693 |
- if err != nil {
|
|
| 694 |
- return err |
|
| 663 |
+ container.Volumes[volPath] = id |
|
| 664 |
+ if isRW, exists := c.VolumesRW[volPath]; exists {
|
|
| 665 |
+ container.VolumesRW[volPath] = isRW |
|
| 695 | 666 |
} |
| 696 |
- srcRW = true // RW by default |
|
| 697 | 667 |
} |
| 698 |
- container.Volumes[volPath] = srcPath |
|
| 699 |
- container.VolumesRW[volPath] = srcRW |
|
| 700 |
- // Create the mountpoint |
|
| 701 |
- rootVolPath := path.Join(container.RootfsPath(), volPath) |
|
| 702 |
- if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
|
| 703 |
- return nil |
|
| 668 |
+ |
|
| 669 |
+ } |
|
| 670 |
+ } |
|
| 671 |
+ |
|
| 672 |
+ // Create the requested volumes if they don't exist |
|
| 673 |
+ for volPath := range container.Config.Volumes {
|
|
| 674 |
+ volPath = path.Clean(volPath) |
|
| 675 |
+ // Skip existing volumes |
|
| 676 |
+ if _, exists := container.Volumes[volPath]; exists {
|
|
| 677 |
+ continue |
|
| 678 |
+ } |
|
| 679 |
+ var srcPath string |
|
| 680 |
+ var isBindMount bool |
|
| 681 |
+ srcRW := false |
|
| 682 |
+ // If an external bind is defined for this volume, use that as a source |
|
| 683 |
+ if bindMap, exists := binds[volPath]; exists {
|
|
| 684 |
+ isBindMount = true |
|
| 685 |
+ srcPath = bindMap.SrcPath |
|
| 686 |
+ if strings.ToLower(bindMap.Mode) == "rw" {
|
|
| 687 |
+ srcRW = true |
|
| 688 |
+ } |
|
| 689 |
+ // Otherwise create an directory in $ROOT/volumes/ and use that |
|
| 690 |
+ } else {
|
|
| 691 |
+ c, err := container.runtime.volumes.Create(nil, container, "", "", nil) |
|
| 692 |
+ if err != nil {
|
|
| 693 |
+ return err |
|
| 704 | 694 |
} |
| 695 |
+ srcPath, err = c.layer() |
|
| 696 |
+ if err != nil {
|
|
| 697 |
+ return err |
|
| 698 |
+ } |
|
| 699 |
+ srcRW = true // RW by default |
|
| 700 |
+ } |
|
| 701 |
+ container.Volumes[volPath] = srcPath |
|
| 702 |
+ container.VolumesRW[volPath] = srcRW |
|
| 703 |
+ // Create the mountpoint |
|
| 704 |
+ rootVolPath := path.Join(container.RootfsPath(), volPath) |
|
| 705 |
+ if err := os.MkdirAll(rootVolPath, 0755); err != nil {
|
|
| 706 |
+ return nil |
|
| 707 |
+ } |
|
| 705 | 708 |
|
| 706 |
- // Do not copy or change permissions if we are mounting from the host |
|
| 707 |
- if srcRW && !isBindMount {
|
|
| 708 |
- volList, err := ioutil.ReadDir(rootVolPath) |
|
| 709 |
+ // Do not copy or change permissions if we are mounting from the host |
|
| 710 |
+ if srcRW && !isBindMount {
|
|
| 711 |
+ volList, err := ioutil.ReadDir(rootVolPath) |
|
| 712 |
+ if err != nil {
|
|
| 713 |
+ return err |
|
| 714 |
+ } |
|
| 715 |
+ if len(volList) > 0 {
|
|
| 716 |
+ srcList, err := ioutil.ReadDir(srcPath) |
|
| 709 | 717 |
if err != nil {
|
| 710 | 718 |
return err |
| 711 | 719 |
} |
| 712 |
- if len(volList) > 0 {
|
|
| 713 |
- srcList, err := ioutil.ReadDir(srcPath) |
|
| 714 |
- if err != nil {
|
|
| 720 |
+ if len(srcList) == 0 {
|
|
| 721 |
+ // If the source volume is empty copy files from the root into the volume |
|
| 722 |
+ if err := CopyWithTar(rootVolPath, srcPath); err != nil {
|
|
| 715 | 723 |
return err |
| 716 | 724 |
} |
| 717 |
- if len(srcList) == 0 {
|
|
| 718 |
- // If the source volume is empty copy files from the root into the volume |
|
| 719 |
- if err := CopyWithTar(rootVolPath, srcPath); err != nil {
|
|
| 720 |
- return err |
|
| 721 |
- } |
|
| 722 | 725 |
|
| 723 |
- var stat syscall.Stat_t |
|
| 724 |
- if err := syscall.Stat(rootVolPath, &stat); err != nil {
|
|
| 725 |
- return err |
|
| 726 |
- } |
|
| 727 |
- var srcStat syscall.Stat_t |
|
| 728 |
- if err := syscall.Stat(srcPath, &srcStat); err != nil {
|
|
| 726 |
+ var stat syscall.Stat_t |
|
| 727 |
+ if err := syscall.Stat(rootVolPath, &stat); err != nil {
|
|
| 728 |
+ return err |
|
| 729 |
+ } |
|
| 730 |
+ var srcStat syscall.Stat_t |
|
| 731 |
+ if err := syscall.Stat(srcPath, &srcStat); err != nil {
|
|
| 732 |
+ return err |
|
| 733 |
+ } |
|
| 734 |
+ // Change the source volume's ownership if it differs from the root |
|
| 735 |
+ // files that where just copied |
|
| 736 |
+ if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
|
|
| 737 |
+ if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
|
|
| 729 | 738 |
return err |
| 730 | 739 |
} |
| 731 |
- // Change the source volume's ownership if it differs from the root |
|
| 732 |
- // files that where just copied |
|
| 733 |
- if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid {
|
|
| 734 |
- if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil {
|
|
| 735 |
- return err |
|
| 736 |
- } |
|
| 737 |
- } |
|
| 738 | 740 |
} |
| 739 | 741 |
} |
| 740 | 742 |
} |
| 741 | 743 |
} |
| 744 |
+ } |
|
| 742 | 745 |
|
| 743 |
- if err := container.generateLXCConfig(hostConfig); err != nil {
|
|
| 744 |
- return err |
|
| 745 |
- } |
|
| 746 |
- |
|
| 747 |
- params := []string{
|
|
| 748 |
- "-n", container.ID, |
|
| 749 |
- "-f", container.lxcConfigPath(), |
|
| 750 |
- "--", |
|
| 751 |
- "/.dockerinit", |
|
| 752 |
- } |
|
| 753 |
- |
|
| 754 |
- // Networking |
|
| 755 |
- if !container.Config.NetworkDisabled {
|
|
| 756 |
- params = append(params, "-g", container.network.Gateway.String()) |
|
| 757 |
- } |
|
| 746 |
+ if err := container.generateLXCConfig(hostConfig); err != nil {
|
|
| 747 |
+ return err |
|
| 748 |
+ } |
|
| 758 | 749 |
|
| 759 |
- // User |
|
| 760 |
- if container.Config.User != "" {
|
|
| 761 |
- params = append(params, "-u", container.Config.User) |
|
| 762 |
- } |
|
| 750 |
+ params := []string{
|
|
| 751 |
+ "-n", container.ID, |
|
| 752 |
+ "-f", container.lxcConfigPath(), |
|
| 753 |
+ "--", |
|
| 754 |
+ "/.dockerinit", |
|
| 755 |
+ } |
|
| 763 | 756 |
|
| 764 |
- if container.Config.Tty {
|
|
| 765 |
- params = append(params, "-e", "TERM=xterm") |
|
| 766 |
- } |
|
| 757 |
+ // Networking |
|
| 758 |
+ if !container.Config.NetworkDisabled {
|
|
| 759 |
+ params = append(params, "-g", container.network.Gateway.String()) |
|
| 760 |
+ } |
|
| 767 | 761 |
|
| 768 |
- // Setup environment |
|
| 769 |
- params = append(params, |
|
| 770 |
- "-e", "HOME=/", |
|
| 771 |
- "-e", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", |
|
| 772 |
- "-e", "container=lxc", |
|
| 773 |
- "-e", "HOSTNAME="+container.Config.Hostname, |
|
| 774 |
- ) |
|
| 775 |
- if container.Config.WorkingDir != "" {
|
|
| 776 |
- workingDir := path.Clean(container.Config.WorkingDir) |
|
| 777 |
- utils.Debugf("[working dir] working dir is %s", workingDir)
|
|
| 762 |
+ // User |
|
| 763 |
+ if container.Config.User != "" {
|
|
| 764 |
+ params = append(params, "-u", container.Config.User) |
|
| 765 |
+ } |
|
| 778 | 766 |
|
| 779 |
- if err := os.MkdirAll(path.Join(container.RootfsPath(), workingDir), 0755); err != nil {
|
|
| 780 |
- return nil |
|
| 781 |
- } |
|
| 767 |
+ if container.Config.Tty {
|
|
| 768 |
+ params = append(params, "-e", "TERM=xterm") |
|
| 769 |
+ } |
|
| 782 | 770 |
|
| 783 |
- params = append(params, |
|
| 784 |
- "-w", workingDir, |
|
| 785 |
- ) |
|
| 786 |
- } |
|
| 771 |
+ // Setup environment |
|
| 772 |
+ params = append(params, |
|
| 773 |
+ "-e", "HOME=/", |
|
| 774 |
+ "-e", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", |
|
| 775 |
+ "-e", "container=lxc", |
|
| 776 |
+ "-e", "HOSTNAME="+container.Config.Hostname, |
|
| 777 |
+ ) |
|
| 778 |
+ if container.Config.WorkingDir != "" {
|
|
| 779 |
+ workingDir := path.Clean(container.Config.WorkingDir) |
|
| 780 |
+ utils.Debugf("[working dir] working dir is %s", workingDir)
|
|
| 787 | 781 |
|
| 788 |
- for _, elem := range container.Config.Env {
|
|
| 789 |
- params = append(params, "-e", elem) |
|
| 782 |
+ if err := os.MkdirAll(path.Join(container.RootfsPath(), workingDir), 0755); err != nil {
|
|
| 783 |
+ return nil |
|
| 790 | 784 |
} |
| 791 | 785 |
|
| 792 |
- // Program |
|
| 793 |
- params = append(params, "--", container.Path) |
|
| 794 |
- params = append(params, container.Args...) |
|
| 786 |
+ params = append(params, |
|
| 787 |
+ "-w", workingDir, |
|
| 788 |
+ ) |
|
| 789 |
+ } |
|
| 795 | 790 |
|
| 796 |
- container.cmd = exec.Command("lxc-start", params...)
|
|
| 791 |
+ for _, elem := range container.Config.Env {
|
|
| 792 |
+ params = append(params, "-e", elem) |
|
| 793 |
+ } |
|
| 797 | 794 |
|
| 798 |
- // Setup logging of stdout and stderr to disk |
|
| 799 |
- if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
|
|
| 800 |
- return err |
|
| 801 |
- } |
|
| 802 |
- if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil {
|
|
| 803 |
- return err |
|
| 804 |
- } |
|
| 795 |
+ // Program |
|
| 796 |
+ params = append(params, "--", container.Path) |
|
| 797 |
+ params = append(params, container.Args...) |
|
| 805 | 798 |
|
| 806 |
- container.cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
|
| 799 |
+ container.cmd = exec.Command("lxc-start", params...)
|
|
| 807 | 800 |
|
| 808 |
- var err error |
|
| 809 |
- if container.Config.Tty {
|
|
| 810 |
- err = container.startPty() |
|
| 811 |
- } else {
|
|
| 812 |
- err = container.start() |
|
| 813 |
- } |
|
| 814 |
- if err != nil {
|
|
| 815 |
- return err |
|
| 816 |
- } |
|
| 817 |
- // FIXME: save state on disk *first*, then converge |
|
| 818 |
- // this way disk state is used as a journal, eg. we can restore after crash etc. |
|
| 819 |
- container.State.setRunning(container.cmd.Process.Pid) |
|
| 801 |
+ // Setup logging of stdout and stderr to disk |
|
| 802 |
+ if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
|
|
| 803 |
+ return err |
|
| 804 |
+ } |
|
| 805 |
+ if err := container.runtime.LogToDisk(container.stderr, container.logPath("json"), "stderr"); err != nil {
|
|
| 806 |
+ return err |
|
| 807 |
+ } |
|
| 820 | 808 |
|
| 821 |
- // Init the lock |
|
| 822 |
- container.waitLock = make(chan struct{})
|
|
| 809 |
+ container.cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
|
|
| 823 | 810 |
|
| 824 |
- container.ToDisk() |
|
| 825 |
- container.SaveHostConfig(hostConfig) |
|
| 826 |
- go container.monitor(hostConfig) |
|
| 827 |
- return nil |
|
| 811 |
+ if container.Config.Tty {
|
|
| 812 |
+ err = container.startPty() |
|
| 813 |
+ } else {
|
|
| 814 |
+ err = container.start() |
|
| 828 | 815 |
} |
| 829 |
- err := startFct(hostConfig) |
|
| 830 | 816 |
if err != nil {
|
| 831 |
- container.cleanup() |
|
| 817 |
+ return err |
|
| 832 | 818 |
} |
| 833 |
- return err |
|
| 819 |
+ // FIXME: save state on disk *first*, then converge |
|
| 820 |
+ // this way disk state is used as a journal, eg. we can restore after crash etc. |
|
| 821 |
+ container.State.setRunning(container.cmd.Process.Pid) |
|
| 822 |
+ |
|
| 823 |
+ // Init the lock |
|
| 824 |
+ container.waitLock = make(chan struct{})
|
|
| 825 |
+ |
|
| 826 |
+ container.ToDisk() |
|
| 827 |
+ container.SaveHostConfig(hostConfig) |
|
| 828 |
+ go container.monitor(hostConfig) |
|
| 829 |
+ return nil |
|
| 834 | 830 |
} |
| 835 | 831 |
|
| 836 | 832 |
func (container *Container) Run() error {
|