28.11 Running Application Containers

You can use the lxc-execute command to create a temporary application container in which you can run a command that is effectively isolated from the rest of the system. For example, the following command creates an application container named guest that runs sleep for 100 seconds.

[root@host ~]# lxc-execute -n guest -- sleep 100

While the container is active, you can monitor it by running commands such as lxc-ls --active and lxc-info -n guest from another window.

[root@host ~]# lxc-ls --active
guest
[root@host ~]# lxc-info -n guest
Name:           guest
State:          RUNNING
PID:            11220
CPU use:        0.02 seconds
BlkIO use:      0 bytes
Memory use:     544.00 KiB
KMem use:       0 bytes

If you need to customize an application container, you can use a configuration file. For example, you might want to change the container's network configuration or the system directories that it mounts.

The following example shows settings from a sample configuration file where the rootfs is mostly not shared except for mount entries to ensure that init.lxc and certain library and binary directory paths are available.

lxc.utsname = guest
lxc.tty = 1
lxc.pts = 1
lxc.rootfs = /tmp/guest/rootfs
lxc.mount.entry=/usr/lib usr/lib none ro,bind 0 0
lxc.mount.entry=/usr/lib64 usr/lib64 none ro,bind 0 0
lxc.mount.entry=/usr/bin usr/bin none ro,bind 0 0
lxc.mount.entry=/usr/sbin usr/sbin none ro,bind 0 0
lxc.cgroup.cpuset.cpus=1

The mount entry for /usr/sbin is required so that the container can access /usr/sbin/init.lxc on the host system.

In practice, you should limit the host system directories that an application container mounts to only those directories that the container needs to run the application.

Note

To avoid potential conflict with system containers, do not use the /container directory for application containers.

You must also configure the required directories and symbolic links under the rootfs directory:

[root@host ~]# TMPDIR=/tmp/guest/rootfs
[root@host ~]# mkdir -p $TMPDIR/usr/lib $TMPDIR/usr/lib64 \
  $TMPDIR/usr/bin $TMPDIR/usr/sbin \
  $TMPDIR/dev/pts $TMPDIR/dev/shm $TMPDIR/proc
[root@host ~]# ln -s $TMPDIR/usr/lib $TMPDIR/lib
[root@host ~]# ln -s $TMPDIR/usr/lib64 $TMPDIR/lib64
[root@host ~]# ln -s $TMPDIR/usr/bin $TMPDIR/bin
[root@host ~]# ln -s $TMPDIR/usr/sbin $TMPDIR/sbin

In this example, the directories include /dev/pts, /dev/shm, and /proc in addition to the mount point entries defined in the configuration file.

You can then use the -f option to specify the configuration file (config) to lxc-execute:

[root@host ~]# lxc-execute -n guest -f config /usr/bin/bash
bash-4.2# ps -ef
UID    PID  PPID  C STIME TTY          TIME CMD
0      1       0  0 14:17 ?        00:00:00 /usr/sbin/init.lxc -- /usr/bin/bash
0      4       1  0 14:17 ?        00:00:00 /usr/bin/bash
0      5       4  0 14:17 ?        00:00:00 ps -ef
bash-4.2# mount
/dev/sda3 on / type btrfs (rw,relatime,seclabel,space_cache)
/dev/sda3 on /usr/lib type btrfs (ro,relatime,seclabel,space_cache)
/dev/sda3 on /usr/lib64 type btrfs (ro,relatime,seclabel,space_cache)
/dev/sda3 on /usr/bin type btrfs (ro,relatime,seclabel,space_cache)
/dev/sda3 on /usr/sbin type btrfs (ro,relatime,seclabel,space_cache)
devpts on /dev/pts type devpts (rw,relatime,seclabel,gid=5,mode=620,ptmxmode=666)
proc on /proc type proc (rw,relatime)
shmfs on /dev/shm type tmpfs (rw,relatime,seclabel)
mqueue on /dev/mqueue type mqueue (rw,relatime,seclabel)
bash-4.2# ls -l /
total 16
lrwxrwxrwx.   1 0 0  7 May 21 14:03 bin -> usr/bin
drwxr-xr-x.   1 0 0 52 May 21 14:27 dev
lrwxrwxrwx.   1 0 0  7 May 21 14:03 lib -> usr/lib
lrwxrwxrwx.   1 0 0  9 May 21 14:27 lib64 -> usr/lib64
dr-xr-xr-x. 230 0 0  0 May 21 14:27 proc
lrwxrwxrwx.   1 0 0  8 May 21 14:03 sbin -> usr/sbin
drwxr-xr-x.   1 0 0 30 May 21 12:58 usr
bash-4.2# touch /bin/foo
touch: cannot touch '/bin/foo': Read-only file system
bash-4.2# echo $?
1

In this example, running the ps command reveals that bash runs as a child of init.lxc. mount shows the individual directories that the container mounts read-only, such as /usr/lib, and ls -l / displays the symbolic links that you set up in rootfs.

Attempting to write to the read-only /bin file system results in an error. If you were to run the same lxc-execute command without specifying the configuration file, it would make the entire root file system of the host available to the container in read/write mode.

As for system containers, you can set cgroup entries in the configuration file and use the lxc-cgroup command to control the system resources to which an application container has access.

Note

lxc-execute is intended to run application containers that share the host's root file system, and not to run system containers that you create using lxc-create. Use lxc-start to run system containers.

For more information, see the lxc-execute(1) and lxc.conf(5) manual pages.