Here are a bunch of Docker related commands and scripts I never remember.

Create minimal Ubuntu image

Create a Dockerfile with the following:

# Use the official minimal Ubuntu base image
FROM ubuntu:20.04
 
# Set environment variables to avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive
 
# Update the package list and install necessary packages
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    vim \
    && apt-get clean && \
    rm -rf /var/lib/apt/lists/*

Build it:

docker build -t minimal-ubuntu .

Create a docker-compose.yml:

version: '3.3'
 
services:
  minimal-ubuntu:
    image: minimal-ubuntu
    container_name: my_minimal_ubuntu
    networks:
      - isolated_network
    volumes:
      - ./shared:/shared
    stdin_open: true
    tty: true
 
networks:
  isolated_network:
    external: true

Create the container and shell into the container:

docker compose up -d
docker exec -it minimal-ubuntu bash

Of course you can create even more minimal Ubuntu images, but they are usually missing too much functionality during the delevopment cycle. But if you want to either way, try this:

# Use the scratch base image
FROM scratch
 
# Copy the necessary files from a minimal Ubuntu installation
COPY --from=ubuntu:20.04 /bin /bin
COPY --from=ubuntu:20.04 /lib /lib
COPY --from=ubuntu:20.04 /lib64 /lib64
COPY --from=ubuntu:20.04 /usr /usr
COPY --from=ubuntu:20.04 /etc /etc
COPY --from=ubuntu:20.04 /var /var
 
# Set environment variables to avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

Canonical officially publishes images that are ~30MB on Docker Hub. Alpine probably has seriously small images at ~3MB.

Find network interface for Docker network

If you don’t have Docker network yet, create one:

docker network create --driver=bridge isolated_network
NETWORK_NAME=isolated_network
docker network inspect $NETWORK_NAME | jq -r '.[0].Id' | cut -c1-12 | xargs -I {} ip link show | grep -oP 'br-\K\w+' | sort | uniq | grep -Ff <(docker network inspect $NETWORK_NAME | jq -r '.[0].Id' | cut -c1-12) | sed 's/^/br-/'

Set NETWORK_NAME to whichever network you are looking for.

The output should be something like br-7bd541de061b.

Allow Docker network to access Internet, but block host and LAN access

First make sure forwarding is turned on:

sudo sysctl -w net.ipv4.ip_forward=1
 
# Make it permanent
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Then let’s update iptables.

Before we do that, let’s back up the existing iptables:

iptables-save > iptables-backup.rules

If you ever need to restore the original iptables:

sudo iptables-restore < iptables-backup.rules

Now let’s make the necessary changes to the iptables:

# Drop traffic from the Docker network to the host's local addresses
sudo iptables -I INPUT -s 172.22.0.0/16 -m addrtype --dst-type LOCAL -j DROP
 
# Drop traffic to the LAN (private IP ranges) in the DOCKER-USER chain
sudo iptables -I DOCKER-USER 1 -i <DOCKER NETWORK INTERFACE> -d 192.168.0.0/16 -j DROP
sudo iptables -I DOCKER-USER 2 -i <DOCKER NETWORK INTERFACE> -d 10.0.0.0/8 -j DROP
sudo iptables -I DOCKER-USER 4 -i <DOCKER NETWORK INTERFACE> -d 172.16.0.0/12 -j DROP
 
# Allow traffic to the internet
sudo iptables -A FORWARD -i <DOCKER NETWORK INTERFACE> -o enp3s0f0 -j ACCEPT
sudo iptables -A FORWARD -i enp3s0f0 -o <DOCKER NETWORK INTERFACE> -m state --state ESTABLISHED,RELATED -j ACCEPT
 
# Enable IP masquerading for the Docker network
sudo iptables -t nat -A POSTROUTING -s 172.22.0.0/16 ! -o <DOCKER NETWORK INTERFACE> -j MASQUERADE

Replace <DOCKER NETWORK INTERFACE> with the network interface (like br-7bd541de061b) for your Docker network.

Run a shell in your Docker container and make sure the iptables changes work.

To persist the iptables now:

iptables-save > /etc/iptables/rules.v4

Make sure you have netfilter-persistent and iptables-persistent installed. If not:

sudo apt install iptables-persistent netfilter-persistent

Then verify netfilter-persistent is running:

sudo systemctl status netfilter-persistent

If not, enable it:

sudo systemctl enable netfilter-persistent

Reboot to make sure it works.

Find space taken by docker logs

sh -c "du -ch /var/lib/docker/containers/*/*-json.log | grep total"

Truncate docker logs

truncate -s 0 /var/lib/docker/containers/**/*-json.log

Find space used by journalctl

journalctl --disk-usage

Set max size of journalctl log files

journalctl --vacuum-size=50M

Stop all containers specific to image

docker ps -a -q --filter ancestor=archivebox/archivebox:master | xargs docker stop

Remove all containers specific to an image

Use the stop command above first, then run the following:

docker ps -a -q --filter ancestor=archivebox/archivebox:master | xargs docker rm

Podman rootless: overlayfs: fs on ‘/home/…’ does not support file handles, falling back to xino=off

Edit (or create) ~/.config/containers/storage.conf and put this in there:

[storage]
  driver = "overlay"
  [storage.options]
    mount_program = "/usr/bin/fuse-overlayfs"

Podman rootless: The cgroupv2 manager is set to systemd but there is no systemd user session available

When trying to create a container, if you see this:

WARN[0000] The cgroupv2 manager is set to systemd but there is no systemd user session available
WARN[0000] For using systemd, you may need to login using an user session
WARN[0000] Alternatively, you can enable lingering with: `loginctl enable-linger 1002` (possibly as root)
WARN[0000] Falling back to --cgroup-manager=cgroupfs
WARN[0000] The cgroupv2 manager is set to systemd but there is no systemd user session available
WARN[0000] For using systemd, you may need to login using an user session
WARN[0000] Alternatively, you can enable lingering with: `loginctl enable-linger 1002` (possibly as root)
WARN[0000] Falling back to --cgroup-manager=cgroupfs
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/shortnames.conf)
Trying to pull docker.io/library/hello-world:latest...
Getting image source signatures
Copying blob c1ec31eb5944 done
Copying config d2c94e258d done
Writing manifest to image destination
Storing signatures
 

Do actually what line 3 says. Run the following:

loginctl enable-linger $USER

Don’t substitute for $USER, leave it as a variable.

This problem to occur if you sudo as the user. If you directly login with ssh, you don’t get these errors.

Podman rootless: Error validating CNI config file [plugin bridge does not support config version “1.0.0”…

This is tested on Ubuntu 22.04 running Podman 3.4.4.

When trying to create a new network for a rootless Podman container, you might get the following error:

WARN[0000] Error validating CNI config file /home/user/.config/cni/net.d/n1.conflist: [plugin bridge does not support config version "1.0.0" plugin portmap does not support config version "1.0.0" plugin firewall does not support config version "1.0.0" plugin tuning does not support config version "1.0.0"]

Change "cniVersion": "1.0.0" in your ~/.config/net.d/<network name>.conflist to "cniVersion": "0.4.0". Then do a podman network ls to make sure there are no more errors.

Podman 5 on Ubuntu

None of the Ubuntu repositories have the latest version of podman.

Thankfully someone is maintaining a static binary that works: mgoltzsche/podman-static.