Rootless container/host networking in Podman, without the hassle

I’m guessing that you’re here because you want to run an application in a Podman container, and access it from the host.

For example, you’re running Podman on Linux, and you want to be able to run a component in a rootless container – such as a database, a message broker, or a data cache – and access it from your application.

You can do this with port publishing, but how do you do it without needing to do that?

One solution is to choose your networking option wisely. There is one network mode which makes host networking rather simple. Let’s have a quick look at network modes first.

Here’s a quick table of contents so you can jump straight to the part you need:

Network modes control how your container interacts with other systems

The thing you need to know about Podman is that, like docker, it has a few different network modes.

A mode changes the networking capabilities of the container – like which other containers it can interact with, or whether it can see the host.

Industrial switch with cabled connectors

To play with containers, choose your network mode

Source: Brett Sayles

Podman has a few different network modes which you can set on a container:

Mode What it does
bridge Creates a network stack on the default bridge network
none No networking is set up at all
container:<id> Uses the same network as another container with ID id
host Uses the host’s network stack
network-id Uses a user-defined network (which you can create using podman network create ...)
ns:<path> Joins a network namespace found at path <path>
private Creates a new network namespace for the container
slirp4netns Creates a user network stack with slirp4netns (This is the default option for rootless containers.)

As you can see there’s a mind-boggling array of options.

The mode I’ve highlighted, the host mode, is the simplest solution for host-to-container and container-to-host networking. We’ll look at that next.

For simple container-to-host networking, connect your container to the host network

In the ‘host’ network mode, a container shares the host’s networking namespace; which means it shares the same network interface, routing tables and so on, so it can ‘see’ the same things that the host can.

Being able to sharing the same network interface and routing tables can be really useful, because it means that your container can see and access services as if it was a regular (non-container) process. And your host can see and access services running in containers.

Security heads-up! Connecting a container to the host network is generally considered insecure, as your container can basically access other ports. And it opens you up to a bunch of risks (OMG!)

The man page (man podman-run) also agrees:

Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure;

For this reason, it’s best used only in development. And you definitely shouldn’t use it for running containers in production.

Use the host network to access the container’s port from the host

Let’s see the host network in action, to see how we can access a service running in a container, from the host.

We’ll use podman run to run a process in a new, rootless container, and add --network=host to attach it to the host network:

podman run --network=host nginxinc/nginx-unprivileged

The Nginx web server is now running on port 8080, inside a container.

(The nginx-unprivileged image is a variation on the standard nginx image, which is configured to run Nginx on an unprivileged port.)

If I go to my web browser on the host and access http://localhost:8080, I’ll see the nginx welcome page:

Firefox browser showing the nginx welcome page on localhost:8080

When a rootless container is connected to the host network, you can access its ports from outside the container

How is that? I didn’t configure any port publishing or forwarding…..

Since the container is connected to the host network, it binds to a port in the host’s network namespace. This is another way of saying that it binds to a port on the host.

You don’t need to set up any extra port publishing, or forwarding, or anything like that. With host network mode, the network is shared between the host and the container. Stuff on localhost in the container can be accessed on localhost from the host.

Heads-up! Since we’re running a rootless container, you must make sure that the application doesn’t attempt to bind (run) on a privileged port, like port 80. If it does try to bind to a privileged port, you’ll see an error like:

bind() to failed (13: Permission denied)

So you’ll need to configure your app to bind on a non-privileged port, which is a port number starting from 1024.

Why is this? Because you’re running as a non-privileged (i.e. non-root) user.

From the manpages for man 7 ip (it took me ages to find exactly where this is described in the manpages!):

The port numbers below 1024 are called privileged ports (or sometimes: reserved ports). Only a privileged process (on Linux: a process that has the CAP_NET_BIND_SERVICE capability in the user namespace governing its network namespace) may bind(2) to these sockets.

On the host network, a container can also access ports on the host

When you use the host network mode, you can also access ports on the host from inside the container.

(This is why it’s considered somewhat insecure.)

On my host operating system, I’m running Apache web server on port 80. I use curl to make a request to the server and get a silly little test page I created:

$ curl http://localhost:80
Hello, internet friend!

Now what happens when I run that same curl http://localhost:80 command, but inside a container that’s configured with the host network mode?

$ podman exec -it 8918c8ebbbfd curl http://localhost:80
Hello, internet friend!

I get the same result! My container able to hit the web server that’s running on my host, simply using localhost.

So when a rootless container uses the host network mode, it can access ports on the host, too, using the localhost address.

Next steps

I hope you got 🌠 VALUE 🌠 out of this article and it’s helped save you some time when setting up ports and networking with your rootless Podman containers.

Don’t forget you shouldn’t really use this in production. But it’s a time-saver for development and lets you run software in containers very easily without fiddling about with port publishing.

Want to learn something else next? I recommend these:

Tom Donohue

By Tom Donohue, Editor | Twitter | LinkedIn

Tom is the founder of Tutorial Works. He’s an engineer and open source advocate. He uses the blog as a vehicle for sharing tutorials, writing about technology and talking about himself in the third person. His very first computer was an Acorn Electron.

Join the discussion

Got some thoughts on what you've just read? Want to know what other people think? Or is there anything technically wrong with the article? (We'd love to know so that we can correct it!) Join the conversation and leave a comment.

Comments are moderated.