Create an Incus container
1. Create the container
Let’s create an ubuntu container, named test1.
incus launch images:ubuntu/noble test1 \
-c security.nesting=true \
-c security.syscalls.intercept.mknod=true \
-c security.syscalls.intercept.setxattr=true
incus list
incus list -c ns4t
incus info test1
incus config show test1
The configuration -c security.nesting=true is needed in order
to run docker inside the container. However if the container is
unprivileged, it does not really have any security implications.
Similarly, the other two configuration options are needed so that docker can handle images efficiently.
For a Debian container use a debian image, for example
images:debian/12. The rest of the instructions will be almost the
same.
|
2. Customize the container
Let’s make a few small improvements inside the container.
-
Get a shell in the container:
incus shell test1 -
Update/upgrade:
apt update apt upgrade --yes -
Uncomment some aliases (in debian):
sed -i ~/.bashrc \ -e 's/# export LS_OPTIONS=/export LS_OPTIONS=/' \ -e 's/# alias ls=/alias ls=/' \ -e 's/# alias ll=/alias ll=/' \ -e 's/# alias l=/alias l=/' cat ~/.bashrc -
Set a better prompt:
sed -i ~/.bashrc -e '/bashrc_custom/d' echo 'source ~/.bashrc_custom' >> ~/.bashrccat <<'EOF' > ~/.bashrc_custom # set a better prompt PS1='${debian_chroot:+($debian_chroot)}\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;36m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]' EOF -
Make sure that bash-completion is enabled:
apt install --yes bash-completion cat <<'EOF' >> ~/.bashrc_custom # enable programmable completion features if [ -f /etc/bash_completion ] && ! shopt -oq posix; then source /etc/bash_completion fi EOFsource ~/.bashrc -
Make sure that
vimis installed and enable its dark background setting:apt install --yes vim sed -i /etc/vim/vimrc \ -e 's/^"set background=dark/set background=dark/' -
Enable automatic security updates:
apt install --yes unattended-upgrades
3. Set a fixed IP
Most of the containers need to have a fixed IP, so that ports can be forwarded to them from the host, etc. It is done differently on Debian and Ubuntu.
3.1. In Debian
IP=10.25.177.206/24
GW=10.25.177.1
cat <<EOF > /etc/systemd/network/eth0.network
[Match]
Name=eth0
[Address]
Address=$IP
[Route]
Gateway=$GW
[Network]
DHCP=no
DNS=8.8.8.8
EOF
cat /etc/systemd/network/eth0.network
systemctl restart systemd-networkd
ip addr
ip ro
ping google.com
3.2. In Ubuntu
apt purge cloud-init
rm /etc/netplan/50-cloud-init.yaml
IP=10.25.177.206/24
GW=10.25.177.1
cat <<EOF > /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
dhcp4: no
addresses:
- $IP
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
routes:
- to: default
via: $GW
EOF
chmod 600 /etc/netplan/01-netcfg.yaml
cat /etc/netplan/01-netcfg.yaml
netplan apply
ip address
ip route
ping 8.8.8.8
4. Install Docker
Not all the containers need to have Docker installed, but most of them do.
-
Add Docker’s official GPG key:
apt install --yes ca-certificates curl install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc ls -l /etc/apt/keyrings/docker.asc -
Add the repository to the apt sources:
arch=$(dpkg --print-architecture) key=/etc/apt/keyrings/docker.asc codename=$(. /etc/os-release && echo "$VERSION_CODENAME") os=$(. /etc/os-release && echo "$ID") repo_url="https://download.docker.com/linux/$os" echo \ "deb [arch=$arch signed-by=$key] $repo_url $codename stable" \ > /etc/apt/sources.list.d/docker.list cat /etc/apt/sources.list.d/docker.list apt update -
Install the Docker packages
apt install --yes \ docker-ce \ docker-ce-cli \ containerd.io \ docker-buildx-plugin \ docker-compose-plugin docker --version docker compose version docker run hello-world