Podman - Ports and Volumes - Part 5
In this part we will talk about ports and volumes for podman. We will cover the basics on how to add them to your container and what to think about going forward.
Ports
Ports can be assigned both on container level and pod level and we will talk about both ways.
The purpose of port is simply to open up access into a container or pod from the outside to gain access to services within, may it be a web container, database container or containers with other services.
Port settings are defined by three parts.
- Outside port
- Inside port
- Protocol
Think of it like this, we have a web server that should listen for incoming traffic on port 8080 and the inside port is 80, this will be with the protocol TCP (More on this later).
graph LR
A(Client) --> |8080/tcp| B{Podman Network Stack<br>Internal translation}
--> |80/tcp| C(Server) --> |80/tcp| B
--> |8080/tcp| A
What this means is that podmans receives the request on port 8080 and the network stack translates the traffic from the outside port to the inside port and then to the service that runs on the server itself.
After that the server sends the data back to the network translation stack where it translates it from port 80 to port 8080 and finally back to the client.
There are never any direct traffic into the containers since running podman as rootless means you have one IP that podman listens to for all your pods/containers under normal operations.
To add port to a container you do that when you create the container either via podman run
or podman create
with the --publish
parameter.
The port option can be individual ports like this.
Or a port range like this.
One thing to take note of is that opening for both TCP
and UDP
requires a --publish
for each protocol like this.
When it comes to pods it is same as with containers with the --publish
parameter and the options with port range and protocol.
Protocol
When setting up what to open up into your pods/containers you must chose on what protocol that it will listen on.
The two you can choose from is either TCP or UDP and these behave different from each other and for what purpose the serve.
I will only cover the basics so you get some understanding for when these are used.
TCP
TCP stands for Transmission Control Protocol
and is the standard when it comes to communication that requires 100% accuracy of the data that is transferred.
Data that is transferred is split up into small packets and then transferred to it's destination, when the packet arrives at the receiver it checks the package to see if the package is ok or not, and if it is not that packet is sent back again from the sender to make the transfer complete.
It is a more robust failsafe protocol, but has a drawback that it is not as fast as UDP and not used for the same type of data.
UDP
UDP stands for User Datagram Protocol
and is standard for data that do not require 100% accuracy and where there are no validity control on each and every packet that is sent.
UDP is mainly used for service that send a lot of data quick in one direction, for example streaming services like Youtube, Netflix, and so on, here the receiver do not report back on lost packets nor do the sender care if packet here and there are lost if the receiver part still actively accept the flow of data that goes in one direction.
This makes the UDP protocol send data at a much faster rate than TCP.
Many game services utilize both TCP and UDP to maximize user experiences when gaming online so it is not one protocol to rule them all.
VLANs
Yes if running in rootful mode you can take advantage of VLAN and assigning each container/pod to a specific network & IP, but then you are running your pods at highest security level and this we wish not to do and in return have a more secure container environment.
So this we will not cover in this series, since we are focused on the rootless way of running things.
Volumes
Volumes are an integral part of data storage in containers, without them no data is persistent and will now survive container upgrades or container decommissions.
As standard all volumes are stored in .local/share/containers/storage/
in your container users home directory, but can be moved to other location if needed.
Volumes are added to a container when you either run the create
or run
parameter on podman, we will go through both of them even if their syntax is exactly the same.
We will use our web server we created earlier, so if you still has it running, run this command to remove it so we can recreate it with a volume attached.
Now we are at square one and can continue.
Run the following.
$ podman run --name MyWebServer --publish=8080:80/tcp \
--volume vol-mywebserver:/usr/share/nginx/html:ro \
--detach docker.io/library/nginx
Now we created a web server with external storage and now we will break down the --volume
parameter to explain some options.
The settings consist of three parameters.
- Storage on disk physical disk where data will reside, default is
.local/share/containers/storage/volumes
. - Internal folder to store on disk, must be an absolut path inside the container.
- The security mode on the attached volume.
So the first part we wrote vol-mywebserver
and that makes podman create a volume named that and put it in .local/share/containers/storage/
, the second part is what we want to map from inside the container to external storage, in this case /usr/share/nginx/html
, this one must be the full path inside the container.
The last part indicates that it should only be mounted in Read-Only mode, default is rw
which is Read-Write.
By just exchanging the run
for create
we can use almost the same syntax as above, excluding the --detach
, this one is not used in create
.
$ podman create --name MyWebServer --publish=8080:80/tcp \
--volume vol-mywebserver:/usr/share/nginx/html:ro \
docker.io/library/nginx
Since we already created our server with the run
parameter we cannot create it again, but as you see, not much is different in both of the commands.
There are more option to the security mode and i recommend reading up on them, can be cases where default not always work, i know i use an option of Z
as the security settings and this is what the manual says about it.
The Z option tells Podman to label the content with a private unshared label Only the current container can use a private volume.
More information from podman run manual about volume security
You can list your volumes with the following command.
The downside is that you do not see what container it is attached to if you do not give it a name that matches, here we did that so we see by the VOLUME NAME
that it is the web servers volume, but we cannot see its mount point inside the container nor the path in our storage.
For that we need to inspect both the container and the volume.
For the container look for the Binds
json with the following command.
JSON output.
For the volume use this command.
JSON output.
[
{
"Name": "vol-mywebserver",
"Driver": "local",
"Mountpoint": ".local/share/containers/storage/volumes/vol-mywebserver/_data",
"CreatedAt": "2023-08-28T18:17:16.132346403Z",
"Labels": {},
"Scope": "local",
"Options": {}
}
]
Now you can match the volume with the Bind mount.
Shared disk
Now we share disk with the rest of the operating system and that is not always desired, since images, containers and other volume data can get really big quick when you start adding data.
Here comes the file storage.conf
to the rescue, placing it under .config/containers/
in your podman users home directory makes it override default settings for podman.
It will only override the specific settings we put in and if it would not find it in this file it uses it's own defaults.
Here i put in /mnt/containerdata
as an example and it is mounted on an second drive, you can place it wherever you want as long as it is placed where you have enough storage.
Important is that your user account running your containers is the only one that has full permission on this folder.
In this guide we used podman
as our user so i will use that as an example, we would give it user and group permission to the folder and make it only readable for this account.
When planning your podman container system take this into account from the start, before you start adding images, containers and volumes.
If you are running multi user podman environment you could add a directory for each user on an external disk and assign right permission on each folder and then ask them to update their storage.conf
with right path and still separate containers from operating system disk, or move the entire home holder to separate disk, recommended to do while you are installing your operating system before users are added.
Recap
In this part we talked about port and volumes for your containers and pods, these are some of the essential parts for your environment, we barely scratch the surface on which options there is but it is still a good ground to build upon.
In the next part we will talk about the difference between pods and containers.