Go to file
Kir Kolyshkin 6f82d4b544 Simplify and fix os.MkdirAll() usage
TL;DR: check for IsExist(err) after a failed MkdirAll() is both
redundant and wrong -- so two reasons to remove it.

Quoting MkdirAll documentation:

> MkdirAll creates a directory named path, along with any necessary
> parents, and returns nil, or else returns an error. If path
> is already a directory, MkdirAll does nothing and returns nil.

This means two things:

1. If a directory to be created already exists, no error is
returned.

2. If the error returned is IsExist (EEXIST), it means there exists
a non-directory with the same name as MkdirAll need to use for
directory. Example: we want to MkdirAll("a/b"), but file "a"
(or "a/b") already exists, so MkdirAll fails.

The above is a theory, based on quoted documentation and my UNIX
knowledge.

3. In practice, though, current MkdirAll implementation [1] returns
ENOTDIR in most of cases described in #2, with the exception when
there is a race between MkdirAll and someone else creating the
last component of MkdirAll argument as a file. In this very case
MkdirAll() will indeed return EEXIST.

Because of #1, IsExist check after MkdirAll is not needed.

Because of #2 and #3, ignoring IsExist error is just plain wrong,
as directory we require is not created. It's cleaner to report
the error now.

Note this error is all over the tree, I guess due to copy-paste,
or trying to follow the same usage pattern as for Mkdir(),
or some not quite correct examples on the Internet.

[1] https://github.com/golang/go/blob/f9ed2f75/src/os/path.go

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
2015-07-29 18:03:27 -07:00
Godeps Godeps: Update github.com/opencontainers/specs to include IDMapping change 2015-07-08 10:53:06 -07:00
libcontainer Simplify and fix os.MkdirAll() usage 2015-07-29 18:03:27 -07:00
script Move test_Dockerfile to script dir 2015-07-09 06:19:26 -07:00
.gitignore Initial commit of runc binary 2015-06-21 19:34:13 -07:00
CONTRIBUTING.md Move libcontainer documenation to root of repo 2015-06-26 11:50:46 -07:00
LICENSE Initial commit of runc binary 2015-06-21 19:34:13 -07:00
MAINTAINERS Move libcontainer documenation to root of repo 2015-06-26 11:50:46 -07:00
MAINTAINERS_GUIDE.md Update maintainers guide 2015-07-21 10:59:56 -07:00
Makefile Add TESTFLAGS to Makefile targets 2015-07-28 19:55:44 -03:00
NOTICE Move libcontainer documenation to root of repo 2015-06-26 11:50:46 -07:00
PRINCIPLES.md Move libcontainer documenation to root of repo 2015-06-26 11:50:46 -07:00
README.md Update README.md to correct comment about spec and user 2015-07-28 10:27:09 -04:00
checkpoint.go Enable build on unsupported platforms 2015-06-29 17:03:44 -07:00
events.go Enable build on unsupported platforms 2015-06-29 17:03:44 -07:00
main.go Change default state directory to /run/oci 2015-07-28 17:02:56 -07:00
main_unix.go Windows: Remove nsenter dependency 2015-06-28 17:04:16 -07:00
main_unsupported.go Create linux spec for runc spec command 2015-07-02 13:45:56 -07:00
restore.go typo: SICHLD -> SIGCHLD 2015-07-10 11:17:54 +09:00
run.go systemd integration with container runtime for supporting sd_notify protocol 2015-07-22 15:53:26 -04:00
signals.go signal: Fix leak 2015-07-27 13:05:15 -04:00
spec.go Only add network info if NEWNET is set 2015-07-27 16:36:28 -07:00
tty.go in signals.go: depeding -> depending 2015-07-15 10:11:24 +09:00
utils.go typo: exists -> exits 2015-07-11 08:19:18 +09:00

README.md

runc

runc is a CLI tool for spawning and running containers according to the OCF specification.

State of the project

Currently runc is an implementation of the OCF specification. We are currently sprinting to have a v1 of the spec out within a quick timeframe of a few weeks, ~July 2015, so the runc config format will be constantly changing until the spec is finalized. However, we encourage you to try out the tool and give feedback.

OCF

How does runc integrate with the Open Container Format? runc depends on the types specified in the specs repository. Whenever the specification is updated and ready to be versioned runc will update it's dependency on the specs repository and support the update spec.

Building:

# create a 'github.com/opencontainers' in your GOPATH/src
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc
make
sudo make install

Using:

To run a container that you received just execute runc with the JSON format as the argument or have a config.json file in the current working directory.

runc
/ $ ps
PID   USER     COMMAND
1     daemon   sh
5     daemon   sh
/ $

OCF Container JSON Format:

Below is a sample config.json configuration file. It assumes that the file-system is found in a directory called rootfs and there is a user named daemon defined within that file-system.

{
    "version": "pre-draft",
    "platform": {
        "os": "linux",
        "arch": "amd64"
    },
    "process": {
        "terminal": true,
        "user": {
            "uid": 0,
            "gid": 0,
            "additionalGids": null
        },
        "args": [
            "sh"
        ],
        "env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "TERM=xterm"
        ],
        "cwd": ""
    },
    "root": {
        "path": "rootfs",
        "readonly": true
    },
    "hostname": "shell",
    "mounts": [
        {
            "type": "proc",
            "source": "proc",
            "destination": "/proc",
            "options": ""
        },
        {
            "type": "tmpfs",
            "source": "tmpfs",
            "destination": "/dev",
            "options": "nosuid,strictatime,mode=755,size=65536k"
        },
        {
            "type": "devpts",
            "source": "devpts",
            "destination": "/dev/pts",
            "options": "nosuid,noexec,newinstance,ptmxmode=0666,mode=0620,gid=5"
        },
        {
            "type": "tmpfs",
            "source": "shm",
            "destination": "/dev/shm",
            "options": "nosuid,noexec,nodev,mode=1777,size=65536k"
        },
        {
            "type": "mqueue",
            "source": "mqueue",
            "destination": "/dev/mqueue",
            "options": "nosuid,noexec,nodev"
        },
        {
            "type": "sysfs",
            "source": "sysfs",
            "destination": "/sys",
            "options": "nosuid,noexec,nodev"
        },
        {
            "type": "cgroup",
            "source": "cgroup",
            "destination": "/sys/fs/cgroup",
            "options": "nosuid,noexec,nodev,relatime,ro"
        }
    ],
    "linux": {
        "uidMapping": null,
        "gidMapping": null,
        "rlimits": null,
        "systemProperties": null,
        "resources": {
            "disableOOMKiller": false,
            "memory": {
                "limit": 0,
                "reservation": 0,
                "swap": 0,
                "kernel": 0,
                "swappiness": -1
            },
            "cpu": {
                "shares": 0,
                "quota": 0,
                "period": 0,
                "realtimeRuntime": 0,
                "realtimePeriod": 0,
                "cpus": "",
                "mems": ""
            },
            "blockIO": {
                "blkioWeight": 0,
                "blkioWeightDevice": "",
                "blkioThrottleReadBpsDevice": "",
                "blkioThrottleWriteBpsDevice": "",
                "blkioThrottleReadIopsDevice": "",
                "blkioThrottleWriteIopsDevice": ""
            },
            "hugepageLimits": null,
            "network": {
                "classId": "",
                "priorities": null
            }
        },
        "namespaces": [
            {
                "type": "process",
                "path": ""
            },
            {
                "type": "network",
                "path": ""
            },
            {
                "type": "ipc",
                "path": ""
            },
            {
                "type": "uts",
                "path": ""
            },
            {
                "type": "mount",
                "path": ""
            }
        ],
        "capabilities": [
            "AUDIT_WRITE",
            "KILL",
            "NET_BIND_SERVICE"
        ],
        "devices": [
            "null",
            "random",
            "full",
            "tty",
            "zero",
            "urandom"
        ]
    }
}

Examples:

Using a Docker image (requires version 1.3 or later)

To test using Docker's busybox image follow these steps:

  • Install docker and download the busybox image: docker pull busybox
  • Create a container from that image and export its contents to a tar file: docker export $(docker create busybox) > busybox.tar
  • Untar the contents to create your filesystem directory:
mkdir rootfs
tar -C rootfs -xf busybox.tar
  • Create a file called config.json using the example from above. You can also generate a spec using runc spec, redirecting the output into config.json
  • Execute runc and you should be placed into a shell where you can run ps:
$ runc
/ # ps
PID   USER     COMMAND
    1 root     sh
    9 root     ps

Using runc with systemd

[Unit]
Description=Minecraft Build Server
Documentation=http://minecraft.net
After=network.target

[Service]
CPUQuota=200%
MemoryLimit=1536M
ExecStart=/usr/local/bin/runc
Restart=on-failure
WorkingDirectory=/containers/minecraftbuild

[Install]
WantedBy=multi-user.target