Currently, I’ve transitioned from Docker to Podman to explore its capabilities and learn more about container management. What tasks and setups did I migrate from Docker to Podman? Here’s the list:
Podman eliminates the need for a central, always-running daemon. Each Podman command directly interacts with the container runtime (e.g., runc) and underlying system APIs, making it lightweight and efficient.
When executed by a non-root user, Podman operates in rootless mode. This ensures that Podman does not require root privileges to manage containers. Instead, it leverages user namespaces to provide isolation and security. This is a significant advantage over other container engines like Docker.
One of my biggest issues with Docker is how it silently adds iptables rules without my knowledge. Podman, especially in rootless mode, doesn’t modify your iptables by default. This transparency and control make it my preferred choice.
{% alert(caution=true) %} Real-World Example: Security Risks with Public Wi-Fi
Imagine you run the following command while working in your office:
docker run -d -p 8181:80 docker.io/sensitive-container
This starts a container exposing port 8181 mapped to port 80 inside the container. Everything seems fine while you’re on a trusted office network. However, the next day, you connect to public Wi-Fi at an airport or coffee shop. Unless you’ve properly configured your firewall, your sensitive container is now accessible to anyone on the same public network.
Do you think something like sudo ufw deny 8181 is enough? NO!. Because docker will silently override that rule. This is why I dislike docker silently mess with the firewall.
The risks here are immense. A malicious actor could discover your exposed port and potentially exploit the container or gain access to its data. This highlights the importance of controlling Docker’s network behavior and understanding how your firewall manages traffic. {% end %}
Despite my preference for Podman, there are still tools and workflows tightly coupled with Docker. For instance, a fantastic deployment tool like Kamal relies on Docker. As a result, I keep Docker installed on my system but restrict its capabilities.
Here’s an example of how I disable Docker’s firewall modifications by adding the following to daemon.json:
{
"iptables": false,
"ip6tables": false
}
With this configuration, Docker no longer manages iptables rules. However, this means I need to manually handle network configurations. My firewall is managed by firewalld, and one immediate issue is that containers lose internet access. For example, building a container image fails when commands like apk add or npm install can’t run due to lack of internet connectivity.
While this issue might seem inconvenient, I appreciate the control it offers. Now, I can explicitly define firewall rules, ensuring I’m aware of what’s happening on my system. Here’s how to allow internet access for Docker containers step by step:
By default, Docker uses the docker0 bridge. First, identify the IP subnet assigned to it:
ip addr show docker0
Look for an output similar to this:
inet 172.17.0.1/16
The subnet in this example is 172.17.0.0/16.
To enable internet access, firewalld needs to perform NAT (masquerading) for the containers. Run the following commands:
# Add the docker0 interface to the public firewall zone
# The public zone is restrictive yet usable for daily network connections.
sudo firewall-cmd --zone=public --add-interface=docker0 --permanent
# Enable masquerade on public zone
sudo firewall-cmd --zone=public --add-masquerade --permanent
# Allow the Docker bridge network for masquerading
sudo firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="172.17.0.0/16" masquerade' --permanent
Note: Replace
172.17.0.0/16with your actual Docker bridge subnet if it differs.
Apply the changes by reloading firewalld:
sudo firewall-cmd --reload
Check if masquerading is enabled and confirm that your rules are in place:
sudo firewall-cmd --zone=public --query-masquerade
sudo firewall-cmd --zone=public --list-rich-rules
Restart your Docker containers and verify that they now have internet access. You can test this by running commands like curl or ping inside a container.
By disabling Docker’s automatic iptables management and configuring firewalld manually, I’ve gained greater control and transparency over my system’s network rules. While Podman has become my primary container engine due to its rootless and daemonless nature, Docker remains essential for certain workflows and tools. Managing both tools in harmony has enhanced my container management experience and improved my understanding of firewall configurations.