Running a Service in a Network Namespace
If you want to have the container have its own real IP address (Internet-routable or CMU-internal), you'll need to set up your own network bridge. The lxcbr0 configured by lxc-net.service uses private 10.x.x.x IPs with NAT and dnsmasq.
Install bridge-utils
Edit /etc/network/interfaces; for the to-be-bridged interfaces's stanza:
Change allow-hotplug «if» -> auto br0
Change the stanza iface «if» inet ... -> iface br0 inet ...
Add a bridge_ports «if» directive
Install the lxc package.
The package installation will start lxc-net.service, which creates a NAT-ed network on lxcbr0. That can be stopped with systemctl stop lxc-net.service.
Creation of lxcbr0, the associated iptables rules, and dnsmasq daemon can be disabled on future boots by specifying USE_LXC_BRIDGE="false" in /etc/default/lxc-net.
Use a configuration similar to the following to create the container for the service:
# Common configuration lxc.include = /usr/share/lxc/config/common.conf # Container specific configuration lxc.start.auto = 0 lxc.uts.name = «hostname» lxc.arch = amd64 lxc.net.0.type = veth lxc.net.0.name = eth0 lxc.net.0.hwaddr = «mac_address» lxc.net.0.link = br0 lxc.rootfs.path = lxc.mount.entry = lxc.mount.entry = tmpfs run tmpfs defaults 0 0 lxc.mount.entry = /var/lib/dhcp-«hostname» var/lib/dhcp none bind,slave,optional 0 0 lxc.mount.auto = cgroup:mixed:force proc:mixed sys:mixed lxc.apparmor.profile = unconfined # [Debian] doesn't support consoles in /dev/lxc/ lxc.tty.dir = # Play nicely with systemd lxc.cgroup.relative = 1 # Extra cgroup device access ## rtc lxc.cgroup2.devices.allow = c 254:0 rm ## hpet lxc.cgroup2.devices.allow = c 10:228 rwm
Create the container with: lxc-create -n «hostname» -f «config_file» -t none
Define a "virtual" interface stanza for the container's network interface in /etc/network/interfaces:
iface eth0-«hostname»-container inet static address «ip_address»/«netmask_len» gateway «default_gw»
If the container's networking must be configured using DHCP (not recommended), create a directory for its dhclient lease database, to avoid clashes with the host: mkdir /var/lib/dhcp-«hostname»
Create a systemd drop-in directory and file to override the desired service. E.g., /etc/systemd/system/«service».service.d/10in_container.conf containing:
[Service] ExecStart= ExecStart=lxc-execute -n «hostname» -- /bin/sh -c "ifup lo && ifup eth0=eth0-«hostname»-container && exec «normal_exec_start»" ExecStop= ExecStop=lxc-attach -n «hostname» -- /bin/sh -c "«normal_exec_stop»; ifdown eth0" Delegate=yes
Accessing a Shell in the Container
When the service is currently running:
lxc-attach -n «hostname» -- /bin/bash
When the service is not running (network will not be available until the interfaces are manually brought up):
lxc-execute -n «hostname» -s lxc.cgroup.relative=0 -- /bin/bash