diff --git a/Dockerfile.chroot b/Dockerfile.chroot index 11bded1a..c73c0fa8 100644 --- a/Dockerfile.chroot +++ b/Dockerfile.chroot @@ -5,7 +5,6 @@ ADD . /workspace WORKDIR /workspace ENV SSL_CERT_DIR=/etc/ssl/certs -RUN makisu pull --extract /testdir --registry gcr.io --tag v0.1.10 makisu-project/makisu RUN ./tools/scripts/makisu_chroot.sh build -t test:121 --modifyfs=true testdata/build-context/symlink RUN ./tools/scripts/makisu_chroot.sh build -t test:121 --modifyfs=true testdata/build-context/user-change RUN ./tools/scripts/makisu_chroot.sh build -t test:121 --modifyfs=true testdata/build-context/chroot-simple diff --git a/bin/makisu/cmd/build.go b/bin/makisu/cmd/build.go index 4595fe2d..e832cdfd 100644 --- a/bin/makisu/cmd/build.go +++ b/bin/makisu/cmd/build.go @@ -20,6 +20,7 @@ import ( "os" "path/filepath" "runtime" + "syscall" "time" "github.com/uber/makisu/lib/builder" @@ -66,14 +67,15 @@ type buildCmd struct { compressionLevel string preserveRoot bool + chroot string } func getBuildCmd() *buildCmd { buildCmd := &buildCmd{ Command: &cobra.Command{ - Use: "build -t= [flags] ", + Use: "build -t= [flags] ", DisableFlagsInUseLine: true, - Short: "Build docker image, optionally push to registries and/or load into docker daemon", + Short: "Build docker image, optionally push to registries and/or load into docker daemon", }, } buildCmd.Args = func(cmd *cobra.Command, args []string) error { @@ -87,7 +89,6 @@ func getBuildCmd() *buildCmd { log.Errorf("failed to process flags: %s", err) os.Exit(1) } - if err := buildCmd.Build(args[0]); err != nil { log.Error(err) os.Exit(1) @@ -122,6 +123,7 @@ func getBuildCmd() *buildCmd { buildCmd.PersistentFlags().StringVar(&buildCmd.compressionLevel, "compression", "default", "Image compression level, could be 'no', 'speed', 'size', 'default'") buildCmd.PersistentFlags().BoolVar(&buildCmd.preserveRoot, "preserve-root", false, "Copy / in the storage dir and copy it back after build.") + rootCmd.PersistentFlags().StringVar(&buildCmd.chroot, "chroot", "", "Executes the command in a chrooted environment.") buildCmd.MarkFlagRequired("tag") buildCmd.Flags().SortFlags = false @@ -214,6 +216,12 @@ func (cmd *buildCmd) newBuildPlan( func (cmd *buildCmd) Build(contextDir string) error { log.Infof("Starting Makisu build (version=%s)", utils.BuildHash) + if cmd.chroot != "" { + if err := cmd.prepareChroot(contextDir); err != nil { + return fmt.Errorf("failed to prepare chroot environment: %s", err) + } + } + // Create BuildContext. contextDirAbs, err := filepath.Abs(contextDir) if err != nil { @@ -297,3 +305,29 @@ func (cmd *buildCmd) Build(contextDir string) error { log.Infof("Finished building %s", imageName.ShortName()) return nil } + +func (cmd *buildCmd) prepareChroot(context string) error { + if runtime.GOOS != "linux" { + return fmt.Errorf("cannot prepare chroot on %s", runtime.GOOS) + } + + dest, err := filepath.Abs(cmd.chroot) + if err != nil { + return fmt.Errorf("failed to convert chroot path to absolute: %s", err) + } else if _, err := os.Lstat(dest); err == nil || !os.IsNotExist(err) { + return fmt.Errorf("chroot target must not exist: %s", err) + } + + certs := filepath.Join(cmd.chroot, pathutils.DefaultInternalDir, "certs") + if err := os.MkdirAll(certs, 0644); err != nil { + return fmt.Errorf("failed to create chroot cert dir: %s", err) + } + // TODO: copy all certs into the chroot environment. + + dev := filepath.Join(cmd.chroot, "dev") + if err := os.MkdirAll(dev, 0644); err != nil { + return fmt.Errorf("failed to create chroot /dev dir: %s", err) + } + // TODO: Create all nods + return syscall.Chroot(dest) +} diff --git a/tools/scripts/makisu_chroot.sh b/tools/scripts/makisu_chroot.sh index 695f4559..0d14dd02 100755 --- a/tools/scripts/makisu_chroot.sh +++ b/tools/scripts/makisu_chroot.sh @@ -16,15 +16,22 @@ function makisu::prepare_internals () { } function makisu::prepare_dev () { - mkdir -p $CHROOT/dev + mkdir -p $CHROOT/dev $CHROOT/shm mknod -m 622 $CHROOT/dev/console c 5 1 + mknod -m 622 $CHROOT/dev/initctl p + mknod -m 666 $CHROOT/dev/full c 1 7 mknod -m 666 $CHROOT/dev/null c 1 3 - mknod -m 666 $CHROOT/dev/zero c 1 5 mknod -m 666 $CHROOT/dev/ptmx c 5 2 + mknod -m 666 $CHROOT/dev/random c 1 8 mknod -m 666 $CHROOT/dev/tty c 5 0 - mknod -m 444 $CHROOT/dev/random c 1 8 - mknod -m 444 $CHROOT/dev/urandom c 1 9 + mknod -m 666 $CHROOT/dev/tty0 c 4 0 + mknod -m 666 $CHROOT/dev/urandom c 1 9 + mknod -m 666 $CHROOT/dev/zero c 1 5 chown root:tty $CHROOT/dev/{console,ptmx,tty} + + # https://github.com/moby/moby/blob/8e610b2b55bfd1bfa9436ab110d311f5e8a74dcb/contrib/mkimage-crux.sh + # https://github.com/moby/moby/blob/8e610b2b55bfd1bfa9436ab110d311f5e8a74dcb/contrib/mkimage-arch.sh + # https://github.com/moby/moby/blob/d7ab8ad145fad4c63112f34721663021e5b02707/contrib/mkimage-yum.sh } function makisu::prepare_etc () {