Debian: Docker-CE

Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Containers are isolated from one another and bundle their own software, libraries and configuration files; they can communicate with each other through well-defined channels.

Step 1: Define Package Repository

The Docker-CE (Community Edition) packages must first have a repository defined, first add the GPG keys

# curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Define the apt repository, the the following example we define the Docker CE stable repository

# echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Step 2: Install Packages

Install the basic docker packages

# apt update
# apt install docker-ce docker-ce-cli containerd.io

Step 3: NFTables

As docker usually uses iptables, make sure that nftables is properly configured and a docker chain entrires are properly defined in /etc/nftables.conf as following example. You will need to customize to suit your current NFTables configuration.

table ip filter {
	chain INPUT {
		type filter hook input priority 0; policy accept;
	}

	chain FORWARD {
		type filter hook forward priority 0; policy accept;
		counter jump DOCKER-USER
		counter jump DOCKER-ISOLATION-STAGE-1
		oifname "docker0" ct state established,related counter accept
		oifname "docker0" counter jump DOCKER
		iifname "docker0" oifname != "docker0" counter accept
		iifname "docker0" oifname "docker0" counter accept
	}

	chain OUTPUT {
		type filter hook output priority 0; policy accept;
	}

	chain DOCKER {
	}

	chain DOCKER-ISOLATION-STAGE-1 {
		iifname "docker0" oifname != "docker0" counter jump DOCKER-ISOLATION-STAGE-2
		counter return
	}

	chain DOCKER-ISOLATION-STAGE-2 {
		oifname "docker0" counter drop
		counter return
	}

	chain DOCKER-USER {
		counter return
	}
}
table ip nat {
        chain PREROUTING {
                type nat hook prerouting priority -100; policy accept;
                fib daddr type local counter jump DOCKER
        }

        chain INPUT {
                type nat hook input priority 100; policy accept;
        }

        chain POSTROUTING {
                type nat hook postrouting priority 100; policy accept;
                oifname != "docker0" ip saddr 172.17.0.0/16 counter masquerade
        }

        chain OUTPUT {
                type nat hook output priority -100; policy accept;
                ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER
        }

        chain DOCKER {
                iifname "docker0" counter return
        }
}

reload your nftables

# sudo systemctl restart nftables

Also make sure that docker knows that iptables is not default by defining the following in /etc/docker/daemon.json

{
  "iptables": false
}

restart docker

# sudo systemctl restart docker