github.com/circular-dark/docker@v1.7.0/daemon/execdriver/lxc/init.go (about)

     1  // +build linux
     2  
     3  package lxc
     4  
     5  import (
     6  	"encoding/json"
     7  	"flag"
     8  	"fmt"
     9  	"log"
    10  	"os"
    11  	"os/exec"
    12  	"runtime"
    13  	"strings"
    14  	"syscall"
    15  
    16  	"github.com/docker/docker/pkg/reexec"
    17  )
    18  
    19  // Args provided to the init function for a driver
    20  type InitArgs struct {
    21  	User       string
    22  	Gateway    string
    23  	Ip         string
    24  	WorkDir    string
    25  	Privileged bool
    26  	Env        []string
    27  	Args       []string
    28  	Mtu        int
    29  	Console    string
    30  	Pipe       int
    31  	Root       string
    32  	CapAdd     string
    33  	CapDrop    string
    34  }
    35  
    36  func init() {
    37  	// like always lxc requires a hack to get this to work
    38  	reexec.Register("/.dockerinit", dockerInititalizer)
    39  }
    40  
    41  func dockerInititalizer() {
    42  	initializer()
    43  }
    44  
    45  // initializer is the lxc driver's init function that is run inside the namespace to setup
    46  // additional configurations
    47  func initializer() {
    48  	runtime.LockOSThread()
    49  
    50  	args := getArgs()
    51  
    52  	if err := setupNamespace(args); err != nil {
    53  		log.Fatal(err)
    54  	}
    55  }
    56  
    57  func setupNamespace(args *InitArgs) error {
    58  	if err := setupEnv(args); err != nil {
    59  		return err
    60  	}
    61  
    62  	if err := finalizeNamespace(args); err != nil {
    63  		return err
    64  	}
    65  
    66  	path, err := exec.LookPath(args.Args[0])
    67  	if err != nil {
    68  		log.Printf("Unable to locate %v", args.Args[0])
    69  		os.Exit(127)
    70  	}
    71  
    72  	if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
    73  		return fmt.Errorf("dockerinit unable to execute %s - %s", path, err)
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  func getArgs() *InitArgs {
    80  	var (
    81  		// Get cmdline arguments
    82  		user       = flag.String("u", "", "username or uid")
    83  		gateway    = flag.String("g", "", "gateway address")
    84  		ip         = flag.String("i", "", "ip address")
    85  		workDir    = flag.String("w", "", "workdir")
    86  		privileged = flag.Bool("privileged", false, "privileged mode")
    87  		mtu        = flag.Int("mtu", 1500, "interface mtu")
    88  		capAdd     = flag.String("cap-add", "", "capabilities to add")
    89  		capDrop    = flag.String("cap-drop", "", "capabilities to drop")
    90  	)
    91  
    92  	flag.Parse()
    93  
    94  	return &InitArgs{
    95  		User:       *user,
    96  		Gateway:    *gateway,
    97  		Ip:         *ip,
    98  		WorkDir:    *workDir,
    99  		Privileged: *privileged,
   100  		Args:       flag.Args(),
   101  		Mtu:        *mtu,
   102  		CapAdd:     *capAdd,
   103  		CapDrop:    *capDrop,
   104  	}
   105  }
   106  
   107  // Clear environment pollution introduced by lxc-start
   108  func setupEnv(args *InitArgs) error {
   109  	// Get env
   110  	var env []string
   111  	dockerenv, err := os.Open(".dockerenv")
   112  	if err != nil {
   113  		return fmt.Errorf("Unable to load environment variables: %v", err)
   114  	}
   115  	defer dockerenv.Close()
   116  	if err := json.NewDecoder(dockerenv).Decode(&env); err != nil {
   117  		return fmt.Errorf("Unable to decode environment variables: %v", err)
   118  	}
   119  	// Propagate the plugin-specific container env variable
   120  	env = append(env, "container="+os.Getenv("container"))
   121  
   122  	args.Env = env
   123  
   124  	os.Clearenv()
   125  	for _, kv := range args.Env {
   126  		parts := strings.SplitN(kv, "=", 2)
   127  		if len(parts) == 1 {
   128  			parts = append(parts, "")
   129  		}
   130  		os.Setenv(parts[0], parts[1])
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  // Setup working directory
   137  func setupWorkingDirectory(args *InitArgs) error {
   138  	if args.WorkDir == "" {
   139  		return nil
   140  	}
   141  	if err := syscall.Chdir(args.WorkDir); err != nil {
   142  		return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
   143  	}
   144  	return nil
   145  }