7.0 KiB
Building LXC containers
Overview
lxcbuild
utility creates a LXC container based on its build recipe and build context path given in command line parameter. If a filename is given, the build recipe is loaded from the file and the directory in which the file resides is taken as build context, ie. all relative paths are resolved from it. In case a directory path is passed as parameter, the directory is then used as build context and a file called lxcfile
from the given directory is used as build recipe.
Usage
lxcbuild <buildpath>
where the buildpath can be either specific lxcfile or a directory containing one
Directives used in lxcfile
The lxcfile syntax is designed to resemble Dockerfile syntax in order to ease the potential transition. Since LXC operates on much lower level of abstraction than Docker, some principles are applied more explicitly and verbosely. Major difference between Docker and lxcbuild is that every directive in Dockerfile creates a new filesystem layer whereas layers in lxcbuild are managed manually.
IMAGE
- Usage:
IMAGE <name>
- Description: Sets container name. Every lxcfile needs to have one, otherwise no LXC config can be written and no
RUN
scripts can be run. LXC configuration file is written to path/var/lib/lxc/<name>/config
- Docker equivalent:
-t
indocker build
command line parameters - Populates LXC field:
lxc.uts.name
LAYER
- Usage:
LAYER <path>
- Description: Includes OverlayFS layer. Unlike Dockerfile's
FROM
, in lxcfile all layers need to be defined. TheLAYER
directives are given from the lowermost to the uppermost layer, where the lowermost is usually the basic operating system and the uppermost is the working layer in which all subsequentRUN
commands and other action will take place. - Docker equivalent:
FROM
- Populates LXC field:
lxc.rootfs.path
MERGE
- Usage:
MERGE <scriptname>
- Description: Runs
<scriptname>
on LXC host and passes all layer paths as parameter to this script. This helps you to resolve the conflicts in cases where you mix multiple OverlayFS layers with overlapping files, ie. package manager cache. The idea is that all layers are read separately by the<scriptname>
script and the fixed result is written back to the uppermost layer. - Docker equivalent: None
- Populates LXC field: None
RUN
-
Usage:
RUN <label> <commands> <label>
-
Description: Executes a shell script in the currently built container. The
<label>
is an arbitrary user defined string which needs to be given as the first parameter and repeated at the end of the script block. The shell script between the labels is passed as-is, including comments and empty lines, to a POSIX shell with-e
and-v
parameters set. Basically, following lxcfile entry:RUN EOF # Comment command1 command2 EOF
translates to the following script:
#!/bin/sh set -ev # Comment command1 command2
The command chaining via
&&
which is required in Dockerfile is optional in lxcbuild. -
Docker equivalent:
RUN
-
Populates LXC field: None
COPY
-
Usage:
COPY <source> [destination]
-
Description: Recursively copies
<source>
files into<destination>
. Source path is relative to the build context directory, destination path is relative to the container root directory. The files are copied asroot:root
. Permissions can be changed by subsequentRUN
command.The
<source>
can be given as http:// or https:// URL in which case gzip, bzip2 or xz tar archive is expected to be downloaded and unpacked into the<destination>
. This is commonly used for creating a basic root filesystem of the container in similar fashion like with Docker'sFROM scratch
. -
Docker equivalent:
COPY
orADD
-
Populates LXC field: None
USER
- Usage:
USER <uid> <gid>
- Description: Sets UID/GID of the container init process to
<uid>
and<gid>
. The default UID/GID is0:0 (root:root)
. - Docker equivalent:
USER
- Populates LXC field:
lxc.init.uid
andlxc.init.gid
CMD
- Usage:
CMD <command> [parameters...]
- Description: Sets the init process of the container. This is the process which is automatically started after the container is launched. The default command is
/bin/true
which immediately terminates with return code 0. - Docker equivalent:
CMD
- Populates LXC field:
lxc.init.cmd
ENV
- Usage:
ENV <variable> <value>
- Description: Populates environment variable
<variable>
with<value>
which is then passed to the init process when the container is launched. - Docker equivalent:
ENV
- Populates LXC field:
lxc.environment
WORKDIR
- Usage:
WORKDIR <dirname>
- Description: Sets working directory of the container init process to
<dirname>
. The default working directory is the container's root directory. - Docker equivalent:
WORKDIR
- Populates LXC field:
lxc.init.uid
andlxc.init.gid
HALT
- Usage:
HALT <signal>
- Description: Sets container stop signal to
<signal>
. The default signal is SIGINT. - Docker equivalent:
--signal
indocker kill
command line parameters - Populates LXC field:
lxc.signal.halt
LXC config
Although lxcfile populates some LXC config fields, there are lot of defaults with remain unchanged. The template file to which lxcbuild fills in the values looks as follows:
# Image name
lxc.uts.name = {name}
# Network
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
# Volumes
lxc.rootfs.path = {rootfs}
# Mounts
lxc.mount.entry = shm dev/shm tmpfs rw,nodev,noexec,nosuid,relatime,mode=1777,create=dir 0 0
lxc.mount.entry = /etc/hosts etc/hosts none bind,create=file 0 0
lxc.mount.entry = /etc/resolv.conf etc/resolv.conf none bind,create=file 0 0
{mounts}
# Init
lxc.init.cmd = {cmd}
lxc.init.uid = {uid}
lxc.init.gid = {gid}
lxc.init.cwd = {cwd}
# Environment
lxc.environment = PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
{env}
# Halt
lxc.signal.halt = {halt}
# Log
lxc.console.size = 1MB
lxc.console.logfile = /var/log/lxc/{name}.log
# Other
lxc.arch = x86_64
lxc.cap.drop = sys_admin
lxc.hook.pre-start = /usr/bin/vmmgr prepare-container
lxc.hook.start-host = /usr/bin/vmmgr register-container
lxc.hook.post-stop = /usr/bin/vmmgr unregister-container
lxc.include = /usr/share/lxc/config/common.conf
For explanation of hooks and overall container integration and behavior, refer to VMMgr hooks page.
Example lxcfile
Following is an example of lxcfile for Redis:
IMAGE redis
LAYER shared/alpine
LAYER redis/redis
RUN EOF
# Create OS user (which will be picked up later by apk add)
addgroup -S -g 6379 redis
adduser -S -u 6379 -h /var/lib/redis -s /bin/false -g redis -G redis redis
# Install Redis
apk --no-cache add redis
EOF
USER 6379 6379
CMD redis-server /etc/redis.conf