LXC

Linux Containers (LXC) provides containers similar to BSD Jails, Linux VServers and Solaris Zones. It gives the impression of virtualization, but shares the kernel and resources with the "host". You can use lxc directly or through LXD.
== Installation ==
Install the required packages:
If you want to create containers other than Alpine, you'll need lxc-templates:
== Upgrading from 2.x ==
Starting with Alpine 3.9, we ship LXC version 3.1.
LXC 3.x has major changes which can and will break your current setup.
LXC 3.x will NOT ship with legacy container templates. Check your current container configs to see if you have any includes pointing to files that don't exist (shipped by legacy templates).
For example if you use Alpine containers created with the Alpine template, you'll need to install:
 apk add lxc-templates-legacy-alpine
Also make sure you convert your LXC config files to the new 2.x format (this is now required).
 lxc-update-config -c /var/lib/lxc/container-name/config
Make sure you have removed cgroup_enable from your cmdline as this will fail to mount cgroups and fail LXC service.
== Prepare network on host ==
Install the package to create the lxcbr0 bridge and configure the forwarding routes using iptables
 apk add lxc-bridge iptables
Enable the dnsmasq OpenRC service at boot and start it
 rc-update add dnsmasq.lxcbr0 boot
 service dnsmasq.lxcbr0 start
If you dont want to forward the routes, add DISABLE_IPTABLES="yes" to the /etc/conf.d/dnsmasq.lxcbr0 file
=== Assign static IP for a container ===
Using the dnsmasq method you can leave the container interface asking for DHCP as it is. You will just need to set the DHCP server asnwers.
By editing the file /etc/lxc/dnsmasq.conf and add the hostname (container name) and desired ip
 dhcp-host=guest1,10.0.3.4
 dhcp-host=guest2,10.0.3.5
Restart the service
 service dnsmasq.lxcbr0 restart
== Create a guest ==
=== Picking from the list ===
And just pick from the list. lxc-download and xz can be uninstalled after you are done.
=== Alpine Template ===
This will create a /var/lib/lxc/guest1 directory with a config file and a rootfs directory.
Note: by default, the alpine template does not have networking service on, you will need to add it using lxc-console
If running on x64 compatible hardware, it is possible to create a 32bit guest:
=== Debian template ===
In order to create a debian template container you'll need to install some packages:
You'll need to turn off some grsecurity chroot options otherwise the debootstrap will fail:
Remember to turn them back on, or simply reboot.
Now you can run:
==== Setting a static IP ====
Since Debian Bullseye 11.3 you can't assign a static IP address using the lxc config file of the container because of a systemd change.
To make it work with a configuration like the following
 # grep net /var/lib/lxc/bullseye/config 
 lxc.net.0.type = veth
 lxc.net.0.flags = up
 lxc.net.0.link = virbr1
 lxc.net.0.ipv4.address = 192.168.1.111/24
 lxc.net.0.ipv4.gateway = 192.168.1.1
You have to attach to the container and run 
After the reboot the IP address should be set correctly. This can be confirmed using the lxc-ls command
=== Ubuntu template ===
In order to create an ubuntu template container, you'll need to turn off some grsecurity chroot options:
Remember to turn them back on, or simply reboot.
Now you can run (replace %MIRROR% with the actual hostname, for example: http://us.archive.ubuntu.com/ubuntu/)
=== Unprivileged LXC images (Alpine / Debian / Ubuntu / Centos etc..) ===
To enable unprivileged containers, one must create a uidgid map:
 echo root:1000000:65536 | tee -a /etc/subuid 
 echo root:1000000:65536 | tee -a /etc/subgid
This creates a uid and gid map for the root user starting at 1000000 with a size of 65536.
To configure containers to use this mapping, add the following lines to the configuration:
 lxc.idmap = u 0 1000000 65536
 lxc.idmap = g 0 1000000 65536
This can be in the global or container-specific configuration.
To create an unprivileged lxc container, you need to use the download template. The download template must be installed:
choose the Distribution | Release | Architecture.
To be able to log in to a Debian container, you currently need to:
You can also remove Systemd from the container.
== Starting/Stopping the guest ==
First, you should enable the cgroup script:
If you don't want to reboot, you can start the service by running
Create a symlink to the /etc/init.d/lxc script for your guest.
You can start your guest with:
Stop it with:
Make it autostart at boot-up with:
You can add to the container config: lxc.start.auto = 1
to autostart containers with the lxc service only.
== Connecting to the guest ==
By default, sshd is not installed. You'll have to attach to the container or connect to the virtual console. This is done with:
Type exit to detach from the container again (please check the grsec notes above)
== Connect to virtual console ==
To disconnect, press + 
== Deleting a guest ==
Make sure the guest is stopped, then run:
This will erase everything, without asking any questions. It is equivalent to: 
== Advanced ==
=== Creating a LXC container without modifying your network interfaces ===
The problem with bridging is that the interface you bridge gets replaced with your new bridge interface.
Let's say you have interface eth0 that you want to bridge. Your eth0 interface gets replaced with the br0 interface that you create. It also means that the interface you use needs to be placed into promiscuous mode to catch all the traffic that could be destined to the other side of the bridge, which may not be what you want.
The solution is to create a dummy network interface, bridge that, and set up NAT so that traffic out of your bridge interface gets pushed through the interface of your choice.
Let's create that dummy interface (thanks to ncopa for talking me out of macvlan and pointing out the dummy interface kernel module)
This will create a dummy interface called dummy0 on your host. To create this interface on every boot, append "dummy" to /etc/modules:
Now we will create a bridge called br0
and then make that dummy interface one end of the bridge
Next, let's give that bridged interface a reason to exist:
Create a file for your container. Let's say /etc/lxc/bridgenat.conf, with the following settings.
lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.link = br0
lxc.net.0.name = eth1
lxc.net.0.ipv4.address = 192.168.1.2/24 192.168.1.255
lxc.net.0.ipv4.gateway = 192.168.1.1
lxc.net.0.veth.pair = veth-if-0
and build your container with that file:
You should now be able to ping your container from your host, and your host from your container.
Your container needs to know where to push traffic that isn't within it's subnet. To do so, we tell the container to route through the bridge interface, br0
From inside the container run
The next step is to push the traffic coming from your private subnet over br0 out through your internet facing interface, or any interface you chose
We are messing with your IP tables here, so make sure these settings don't conflict with anything you may have already set up.
Say eth0 was your internet facing network interface, and br0 is the name of the bridge you made earlier. We'd do this:
Now you should be able to route through your bridge interface to the internet facing interface of your host from your container, just like at home!
You could also have a dhcp server running on your host, and set it up to give IP addresses from your private subnet to any container that requests it, and then have one template for multiple alpine LXC containers, perfect for alpine development :)
=== Using static IP ===
If you're using static IP, you need to configure this properly on the guest /etc/network/interfaces. To stay in line with the above example, modify /var/lib/lxc/guest1/rootfs/etc/network/interfaces 
from
 #auto lo
 iface lo inet loopback
 auto eth0
 iface eth0 inet dhcp
to 
 #auto lo
 iface lo inet loopback
 auto eth0
 iface eth0 inet static
 address <lxc-container-ip> # IP which the lxc container should use
 gateway <gateway-ip> # IP of gateway to use, mostly same as on lxc-host
 netmask <netmask>
=== mem and swap ===
=== checkconfig ===
=== VirtualBox ===
In order for the network to work on containers, you need to set "Promiscuous Mode" to "Allow All" in VirtualBox settings for the network adapter.
Category:Virtualization
=== postgreSQL ===
Inside the container run: to fix 
=== openVPN ===
see Setting_up_a_OpenVPN_server#openVPN_and_LXC
== LXC 1.0 Additional information ==
Some info regarding new features in LXC 1.0
 
https://www.stgraber.org/2013/12/20/lxc-1-0-blog-post-series/
== See also ==
* Howto-lxc-simple