Recap:
In the last part of the series, we saw how to configure the network in host for containers and learnt how to pull images using machinectl
. If you haven’t gone through that first, please do so.
Before Booting your container for the first time:
I’m using an cloud based ubuntu image, as it provides cloud-init support, which lets me configure my container during the boot itself. I’m not going to go into the details of cloud-init, but I’ll give you some idea about minimising full-blown cloud setup.
Also, you can feel familiar with cloud vendors system startup by using the cloud based images.
cloud-init:
By default, if you don’t configure cloud-init, it will try to hit and reach many cloud vendors looking for source configuration, which can take an awful lot of time approximately upto 40 minutes. We’ll see how to disable that:
- create a file named
ds-identity.cfg
with the following contents
datasource: NoCloud
policy: search,found=first,maybe=none,notfound=disabled
This file is telling the cloud-init to use the datasource as NoCloud
, which will not do any lookup with cloud vendors
- create a folder
nocloud
and put three files in them, namely:meta-data
with the following contentsinstance-id: xenial local-hostname: xenial
user-data
with the following contents (or anything else based on your requirements)#cloud-config hostname: xenial # Any package that you'd like to install in the container packages: - bash - bash-completion - wget - git - make # Any setup commands that you'd like to run at the bootup runcmd: - apt-get -y update - apt-get -y clean - apt-get -y autoremove --purge # for security, if you don't care, just put it as false disable_root: true # Additional users that you'd like to provide access to your container after boot users: - name: testuser gecos: TEST USER lock_passwd: true groups: [sudo, users, admin, adm, audio, cdrom, dialout, floppy, video, plugdev, dip, netdev] shell: /bin/bash sudo: ["ALL=(ALL) NOPASSWD:ALL"] # Setup a dummy password for the additional users and during first login, it'll ask for a new password chpasswd: list: | testuser:testuser # Common maintenance options package_upgrade: true package_update: true package_reboot_if_required: true power_state: delay: now mode: reboot message: Rebooting the OS condition: if [ -e /var/run/reboot-required ];then exit 0; else exit 1; fi
network-config
, this is optional, only if you want to configure network at boot. This is necessary for me as my setup demands it.version: 2 ethernets: host0: set-name: host0 addresses: - 192.168.30.10/255.255.255.0 gateway4: 192.168.30.1 nameservers: addresses: [1.1.1.1, 8.8.8.8, 8.8.4.4]
- You should now be having the following directory structure
$ tree
.
├── ds-identity.cfg
├── nocloud
│ ├── meta-data
│ ├── network-config
│ └── user-data
└── xenial.nspawn
1 directory, 5 files
Our mount file for container - xenial.nspawn:
Always have a copy of this file xenial.nspawn
stored somewhere, as the container removal leads to deletion of this file. Copy this file to /etc/systemd/nspawn
directory.
[Exec]
# Writable bind mounts don't with user namespacing
PrivateUsers=pick
[Files]
# these lines should be familiar for those who are using docker
# this is a simple read-only volume mount for the cloud-init files
BindReadOnly=/home/user/cloud-init/ds-identity.cfg:/etc/cloud/ds-identity.cfg
BindReadOnly=/home/user/cloud-init/nocloud:/var/lib/cloud/seed/nocloud
PrivateUsersChown=yes
# PrivateUsersChown is an expensive operation according to the documentation
[Network]
VirtualEthernet=yes
Bridge=virxen
Let’s fire up our container:
$ sudo systemd-nspawn -D /var/lib/machines/xenial -U -b -M xenial
# -b flag means boot, which boots our container
...............System Startup messages.............................
......................Login Page...................................
You need to wait for sometime, for the cloud-init to complete, then only we can use the testuser
created with the config file. You will see the familiar output logs from cloud-vendors. Use the below command to view the system setup and once, it comes to a halt, use the username and password from the cloud-init config file to login to your new container. Voila!!!
$ sudo journalctl -M xenial -f
.....................Cloud-Init Output Logs........................
Those who want an easier way out of this setup:
Please use debootsrap
as follows:
$ sudo mkdir -p /var/lib/machines/{any name of your choice}
$ sudo debootstrap --arch=amd64 jessie /var/lib/machines/{any name of your choice}/
If you don’t specify any network in the xenial.nspawn
file, the container will see all network interfaces of the host and acts like it’s an application inside the host using the same ip addresses.
Once, again, some of the steps might be volatile, such as networks, so please make a backup of them if you want to persist. Follow, these tutorials for making them persistent across system reboots.
- How to configure iptables on Ubuntu
- How To Set Up a Firewall Using Iptables on Ubuntu 14.04
- Make iptables rules persistent after reboot on Ubuntu 18.04
- How to make iptables rules persistent after reboot on Linux
Problems that might arise and solutions:
- Network connectivity, please check the container ip adresses and journalctl (in host) for reason of failure and address them. Sometime, tweaking the iptables based on your host setup can help.
- Cloud-init some installation failed and needs a fresh start, use
sudo cloud-init clean
inside the container - Do not use any overlaping ip addresses when using static ip address for the bridge
Container Management:
After the setup you don’t have to use systemd-nspawn
at all except certain cases. machinectl
is more than sufficient to manage containers.
- start the container
machinectl start {container name}
- login into the container
machinectl login {container name}
- shell of the container
machinectl shell {container name}
- status of the container
machinectl status {container name}
- reboot the container
machinectl reboot {container name}
- terminate the container
machinectl terminate {container name}
- list running containers
machinectl list
- list available images
machinectl list-images
I have intentionally left out the container resource management as it is easy to follow from the official documentation of @.nspawn from the references.
References:
- systemd-nspawn official documentation
- @.nspawn official documentation
- Introduction to systemd-nspawn by Selectel
- Introduction to systemd-nspawn by Patrick Skiba
- systemd-nspawn - Lorenzo Fontana
- unifi-controller-systemd-nspawn.md
- systemd-nspawn container architecture
- Setting up containers with systemd-nspawn
- Networking Config Version 2 - Cloud Init
- LXC Container Networking:NAT Bridge
- A Simple Script to Create systemd-nspawn Alpine Container
- Run Docker containers with systemd-nspawn
- How to use systemd-nspawn for Linux system recovery
- Run Desktop Apps with systemd-nspawn Container
- systemd-nspawn and Private Networking
- Containerizing Graphical Applications On Linux With systemd-nspawn
- systemd-nspawn: redirect ports and keep internet
- Taming systemd-nspawn for running containers
- systemd-nspawn Archwiki
- NATTING in Ubuntu Server
- LXD Container Home Server Networking For Dummies
- Docker containers networking - Tutorial
- Changing Passwords with cloud-init
- How to configure networking with Netplan on Ubuntu
- Containers From Scratch Pt.2 Networking