mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-10-16 01:15:03 +00:00
Add a runtime config
This adds support for a runtime configuration file that can do: - `mkdir` to make a directory at runtime, eg in `/var` or `/tmp`, to avoid workarounds - `interface` that can create network interfaces in a container or move them - `bindNS` that can bind mount namespaces of an `onboot` container to a file so a service can be started in that namespace. It merges the `service` and `onboot` tools (in `init`) to avoid duplication. This also saves some size for eg LCOW which did not use the `onboot` code in `runc`. Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
@@ -20,14 +20,12 @@ RUN git checkout $RUNC_COMMIT
|
||||
RUN make static BUILDTAGS="seccomp" EXTRA_FLAGS="-buildmode pie" EXTRA_LDFLAGS="-extldflags \\\"-fno-PIC -static\\\""
|
||||
RUN cp runc /usr/bin/
|
||||
|
||||
ADD cmd /go/src/cmd
|
||||
RUN go-compile.sh /go/src/cmd/onboot
|
||||
RUN mkdir -p /etc/init.d && ln -s /usr/bin/onboot /etc/init.d/010-onboot
|
||||
RUN mkdir -p /etc/shutdown.d && ln -s /usr/bin/onboot /etc/shutdown.d/010-onshutdown
|
||||
RUN mkdir -p /etc/init.d && ln -s /usr/bin/service /etc/init.d/010-onboot
|
||||
RUN mkdir -p /etc/shutdown.d && ln -s /usr/bin/service /etc/shutdown.d/010-onshutdown
|
||||
|
||||
FROM scratch
|
||||
WORKDIR /
|
||||
ENTRYPOINT []
|
||||
COPY --from=alpine /usr/bin/runc /go/bin/onboot /usr/bin/
|
||||
COPY --from=alpine /usr/bin/runc /usr/bin/
|
||||
COPY --from=alpine /etc/init.d/ /etc/init.d/
|
||||
COPY --from=alpine /etc/shutdown.d/ /etc/shutdown.d/
|
||||
|
@@ -1,5 +1,4 @@
|
||||
IMAGE=runc
|
||||
NETWORK=1
|
||||
DEPS=$(wildcard cmd/onboot/*.go)
|
||||
|
||||
include ../package.mk
|
||||
|
@@ -1,66 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
runcBinary = "/usr/bin/runc"
|
||||
onbootPath = "/containers/onboot"
|
||||
shutdownPath = "/containers/onshutdown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// try to work out how we are being called
|
||||
command := os.Args[0]
|
||||
if len(os.Args) > 1 {
|
||||
command = os.Args[1]
|
||||
}
|
||||
var path = onbootPath
|
||||
switch {
|
||||
case strings.Contains(command, "boot"):
|
||||
path = onbootPath
|
||||
case strings.Contains(command, "shutdown"):
|
||||
path = shutdownPath
|
||||
}
|
||||
|
||||
// do nothing if the path does not exist
|
||||
if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// get files; note ReadDir already sorts them
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot read files in %s: %v", path, err)
|
||||
}
|
||||
|
||||
status := 0
|
||||
|
||||
for _, file := range files {
|
||||
name := file.Name()
|
||||
fullPath := filepath.Join(path, name)
|
||||
if err := prepare(fullPath); err != nil {
|
||||
log.Printf("Error preparing %s: %v", name, err)
|
||||
status = 1
|
||||
continue
|
||||
}
|
||||
cmd := exec.Command(runcBinary, "run", "--bundle", fullPath, name)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
log.Printf("Error running %s: %v", name, err)
|
||||
status = 1
|
||||
} else {
|
||||
// do not clean up on error to make debug easier
|
||||
cleanup(fullPath)
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(status)
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
package main
|
||||
|
||||
// Please note this file is shared between pkg/runc and pkg/containerd
|
||||
// Update it in both places if you make changes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func prepare(path string) error {
|
||||
// see if we are dealing with a read only or read write container
|
||||
if _, err := os.Stat(filepath.Join(path, "lower")); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return prepareRO(path)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return prepareRW(path)
|
||||
}
|
||||
|
||||
func prepareRO(path string) error {
|
||||
// make rootfs a mount point, as runc doesn't like it much otherwise
|
||||
rootfs := filepath.Join(path, "rootfs")
|
||||
if err := syscall.Mount(rootfs, rootfs, "", syscall.MS_BIND, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareRW(path string) error {
|
||||
// mount a tmpfs on tmp for upper and workdirs
|
||||
// make it private as nothing else should be using this
|
||||
tmp := filepath.Join(path, "tmp")
|
||||
if err := syscall.Mount("tmpfs", tmp, "tmpfs", 0, "size=10%"); err != nil {
|
||||
return err
|
||||
}
|
||||
// make it private as nothing else should be using this
|
||||
if err := syscall.Mount("", tmp, "", syscall.MS_REMOUNT|syscall.MS_PRIVATE, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
upper := filepath.Join(tmp, "upper")
|
||||
// make the mount points
|
||||
if err := os.Mkdir(upper, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
work := filepath.Join(tmp, "work")
|
||||
if err := os.Mkdir(work, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
lower := filepath.Join(path, "lower")
|
||||
rootfs := filepath.Join(path, "rootfs")
|
||||
opt := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lower, upper, work)
|
||||
if err := syscall.Mount("overlay", rootfs, "overlay", 0, opt); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cleanup functions are best efforts only, mainly for rw onboot containers
|
||||
func cleanup(path string) {
|
||||
// see if we are dealing with a read only or read write container
|
||||
if _, err := os.Stat(filepath.Join(path, "lower")); err != nil {
|
||||
cleanupRO(path)
|
||||
} else {
|
||||
cleanupRW(path)
|
||||
}
|
||||
}
|
||||
|
||||
func cleanupRO(path string) {
|
||||
// remove the bind mount
|
||||
rootfs := filepath.Join(path, "rootfs")
|
||||
_ = syscall.Unmount(rootfs, 0)
|
||||
}
|
||||
|
||||
func cleanupRW(path string) {
|
||||
// remove the overlay mount
|
||||
rootfs := filepath.Join(path, "rootfs")
|
||||
_ = os.RemoveAll(rootfs)
|
||||
_ = syscall.Unmount(rootfs, 0)
|
||||
// remove the tmpfs
|
||||
tmp := filepath.Join(path, "tmp")
|
||||
_ = os.RemoveAll(tmp)
|
||||
_ = syscall.Unmount(tmp, 0)
|
||||
}
|
Reference in New Issue
Block a user