184 lines
6.5 KiB
Markdown
184 lines
6.5 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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` in `docker 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. The `LAYER` 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 subsequent `RUN` commands and other action will take place.
|
|
- **Docker equivalent:** `FROM`
|
|
- **Populates LXC field:** `lxc.rootfs.path`
|
|
|
|
### RUN
|
|
|
|
- **Usage:**
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
RUN EOF
|
|
# Comment
|
|
command1
|
|
command2
|
|
EOF
|
|
```
|
|
|
|
translates to the following script:
|
|
|
|
```bash
|
|
#!/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 as `root:root`. Permissions can be changed by subsequent `RUN` 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's `FROM scratch`.
|
|
|
|
- **Docker equivalent:** `COPY` or `ADD`
|
|
- **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 is `0:0 (root:root)`.
|
|
- **Docker equivalent:** `USER`
|
|
- **Populates LXC field:** `lxc.init.uid` and `lxc.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` and `lxc.init.gid`
|
|
|
|
### HALT
|
|
|
|
- **Usage:** `HALT <signal>`
|
|
- **Description:** Sets container stop signal to `<signal>`. The default signal is SIGINT.
|
|
- **Docker equivalent:** `--signal` in `docker 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:
|
|
|
|
```bash
|
|
# 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](vmmgr-hooks) page.
|
|
|
|
## Example lxcfile
|
|
|
|
Following is an example of *lxcfile* for *Redis*:
|
|
|
|
```bash
|
|
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
|
|
```
|