Containers in VyOS - Podman Container Management

Containers in VyOS - Podman Container Management

VyOS supports running Podman-based containers, allowing you to deploy applications directly on the router.

Overview

VyOS uses Podman - a daemonless container engine compatible with Docker and the OCI standards.

Capabilities:

  • Running OCI-compatible containers
  • Integration with VyOS networking
  • Managing images from various registries
  • Custom container networks
  • Volume and device mounting
  • Resource limits (CPU, memory)
  • Automatic restart
  • Capability management

Use cases:

  • Monitoring (Zabbix, Prometheus)
  • DNS services (Pi-hole, AdGuard)
  • Web services
  • Proxy servers (Squid, HAProxy)
  • VPN clients
  • Utilities and tools

Basic Configuration

Simple Container

Running a container from Docker Hub:

set container name nginx image docker.io/nginx:latest
commit

The container starts automatically after commit.

Container with a Port

Forward a host port into the container:

set container name nginx image docker.io/nginx:latest
set container name nginx port http source 8080
set container name nginx port http destination 80
set container name nginx port http protocol tcp
commit

Now nginx is available at http://<vyos-ip>:8080.

Checking Status

show container
show container nginx

Container Images

Pulling an Image

The image is pulled automatically on commit, but you can also pull it manually:

add container image docker.io/nginx:latest

Viewing Images

show container image

Example output:

REPOSITORY               TAG      IMAGE ID      CREATED      SIZE
docker.io/library/nginx  latest   3b25b682ea82  2 weeks ago  192 MB

Updating an Image

update container image nginx

Pulls a new version of the image (if the tag has changed).

Specifying an Image

set container name myapp image docker.io/myuser/myapp:1.0
commit

Format: registry/repository:tag

By default, Docker Hub (docker.io) is used.

Entrypoint and Command

Overriding the entrypoint:

set container name myapp image myapp:latest
set container name myapp entrypoint '/usr/local/bin/custom-start.sh'
commit

Command arguments:

set container name myapp image myapp:latest
set container name myapp command '/bin/bash'
set container name myapp arguments '-c "echo Hello && sleep infinity"'
commit

Network Configuration

Container Network

Creating a custom network:

set container network mynet prefix 172.20.0.0/16
set container network mynet description 'Custom container network'
commit

IPv6:

set container network mynet prefix fd00::/64
commit

Connecting a Container to a Network

set container name nginx network mynet
commit

The container receives a dynamic IP from the mynet network.

Static IP

set container name nginx network mynet address 172.20.0.10
commit

MTU for a Network

set container network mynet mtu 1400
commit

VRF for a Container Network

set container network mynet vrf MGMT
commit

The container network will reside in the specified VRF.

Viewing Networks

show container network

Volumes and Mounting

Mounting a Directory

set container name nginx volume config source /config/nginx
set container name nginx volume config destination /etc/nginx/conf.d
set container name nginx volume config mode ro
commit
  • source - path on VyOS
  • destination - path in the container
  • mode - ro (read-only) or rw (read-write)

Mounting a Configuration File

set container name app volume appconfig source /config/app.conf
set container name app volume appconfig destination /etc/app/app.conf
set container name app volume appconfig mode ro
commit

Data in /config

To preserve data across reboots, use /config:

set container name database volume data source /config/database
set container name database volume data destination /var/lib/postgresql/data
set container name database volume data mode rw
commit

/config is the only VyOS directory that persists across reboots.

Device Mounting

Mounting devices (for example, USB):

set container name app device source /dev/ttyUSB0
set container name app device destination /dev/ttyUSB0
commit

Environment Variables

Passing environment variables into a container:

set container name myapp environment TZ value 'Europe/Moscow'
set container name myapp environment DEBUG value 'true'
set container name myapp environment DB_HOST value '192.168.1.100'
commit

Format:

set container name <name> environment <KEY> value '<value>'

Secrets (passwords):

set container name db environment POSTGRES_PASSWORD value 'secret123'
commit

Ports

TCP Port Forwarding

set container name webapp port http source 8080
set container name webapp port http destination 80
set container name webapp port http protocol tcp
commit
  • source - port on VyOS
  • destination - port in the container
  • protocol - tcp or udp

Now traffic to <vyos-ip>:8080 will be forwarded to the container on port 80.

UDP Port Forwarding

set container name dnsserver port dns source 5353
set container name dnsserver port dns destination 53
set container name dnsserver port dns protocol udp
commit

Multiple Ports

set container name webapp port http source 8080
set container name webapp port http destination 80
set container name webapp port http protocol tcp

set container name webapp port https source 8443
set container name webapp port https destination 443
set container name webapp port https protocol tcp

commit

Binding to a Specific IP

To bind to a specific interface, use firewall DNAT:

set nat destination rule 10 destination address 192.168.1.1
set nat destination rule 10 destination port 8080
set nat destination rule 10 inbound-interface name eth1
set nat destination rule 10 translation address 172.20.0.10
set nat destination rule 10 translation port 80
set nat destination rule 10 protocol tcp
commit

Hostname

Setting the container hostname:

set container name myapp host-name myapp.local
commit

The hostname is visible inside the container and in DNS (if configured).

Restart Policy

Container restart policy on failure:

Always

Always restart (default):

set container name myapp restart always
commit

On-failure

Restart only on a non-zero exit code:

set container name myapp restart on-failure
commit

No

Do not restart:

set container name myapp restart no
commit

Resource Limits

CPU Quota

CPU limit (as a percentage):

set container name myapp cpu-quota 50
commit

50 = 50% of one CPU core.

Memory Limit

Memory limit (in megabytes):

set container name myapp memory 512
commit

The container is limited to 512 MB of RAM.

Combined Limits

set container name myapp cpu-quota 25
set container name myapp memory 256
commit

Capabilities

Managing Linux capabilities for a container.

Adding a Capability

set container name myapp capability net-admin
set container name myapp capability sys-time
commit

Commonly used capabilities:

  • net-admin - network management
  • sys-time - changing the system time
  • net-raw - raw sockets (ping)
  • sys-module - loading kernel modules

Privileged Containers

For full access (all capabilities):

set container name myapp capability all
commit

Use with caution (it reduces security).

Sysctl Parameters

Changing kernel parameters for a container:

set container name myapp sysctl parameter net.ipv4.ip_forward value 1
commit

Requires the corresponding capabilities.

Container Registries

Configuring a Registry

By default, VyOS uses Docker Hub (docker.io).

Adding an additional registry:

set container registry gitlab address registry.gitlab.com
commit

Authentication

For private registries:

set container registry myprivate address registry.example.com
set container registry myprivate authentication username myuser
set container registry myprivate authentication password mypassword
commit

Insecure Registry

For an HTTP registry (not recommended):

set container registry myregistry address registry.local:5000
set container registry myregistry disable-verify
commit

Mirror Registry

A Docker Hub mirror:

set container registry dockermirror mirror address mirror.gcr.io
commit

Logging

Logging Driver

By default, journald is used.

Changing the driver:

set container name myapp log-driver k8s-file
commit

Available drivers:

  • journald - systemd journal
  • k8s-file - Kubernetes-compatible files
  • none - no logging

Viewing Logs

show container log myapp

Logs are also available through journald:

journalctl -u vyos-container-myapp

Configuration Examples

Pi-hole DNS Server

Ad blocking and DNS filtering:

# Container network
set container network pihole prefix 172.21.0.0/24

# Pi-hole container
set container name pihole image docker.io/pihole/pihole:latest
set container name pihole network pihole address 172.21.0.10
set container name pihole restart always

# Ports
set container name pihole port dns-tcp source 5353
set container name pihole port dns-tcp destination 53
set container name pihole port dns-tcp protocol tcp

set container name pihole port dns-udp source 5353
set container name pihole port dns-udp destination 53
set container name pihole port dns-udp protocol udp

set container name pihole port web source 8080
set container name pihole port web destination 80
set container name pihole port web protocol tcp

# Environment
set container name pihole environment TZ value 'Europe/Moscow'
set container name pihole environment WEBPASSWORD value 'admin123'

# Volumes
set container name pihole volume config source /config/pihole/config
set container name pihole volume config destination /etc/pihole
set container name pihole volume config mode rw

set container name pihole volume dnsmasq source /config/pihole/dnsmasq.d
set container name pihole volume dnsmasq destination /etc/dnsmasq.d
set container name pihole volume dnsmasq mode rw

commit

Access the web interface at: http://<vyos-ip>:8080/admin

Zabbix Monitoring

A multi-container monitoring system:

# Container network
set container network zabbix prefix 172.22.0.0/24

# PostgreSQL database
set container name postgres image docker.io/postgres:14
set container name postgres network zabbix address 172.22.0.2
set container name postgres restart always

set container name postgres environment POSTGRES_DB value 'zabbix'
set container name postgres environment POSTGRES_USER value 'zabbix'
set container name postgres environment POSTGRES_PASSWORD value 'zabbix_password'

set container name postgres volume data source /config/zabbix/postgresql
set container name postgres volume data destination /var/lib/postgresql/data
set container name postgres volume data mode rw

# Zabbix Server
set container name zabbix-server image docker.io/zabbix/zabbix-server-pgsql:latest
set container name zabbix-server network zabbix address 172.22.0.3
set container name zabbix-server restart always

set container name zabbix-server environment DB_SERVER_HOST value '172.22.0.2'
set container name zabbix-server environment POSTGRES_DB value 'zabbix'
set container name zabbix-server environment POSTGRES_USER value 'zabbix'
set container name zabbix-server environment POSTGRES_PASSWORD value 'zabbix_password'

set container name zabbix-server port trapper source 10051
set container name zabbix-server port trapper destination 10051
set container name zabbix-server port trapper protocol tcp

# Zabbix Web Frontend
set container name zabbix-web image docker.io/zabbix/zabbix-web-nginx-pgsql:latest
set container name zabbix-web network zabbix address 172.22.0.4
set container name zabbix-web restart always

set container name zabbix-web environment ZBX_SERVER_HOST value '172.22.0.3'
set container name zabbix-web environment DB_SERVER_HOST value '172.22.0.2'
set container name zabbix-web environment POSTGRES_DB value 'zabbix'
set container name zabbix-web environment POSTGRES_USER value 'zabbix'
set container name zabbix-web environment POSTGRES_PASSWORD value 'zabbix_password'
set container name zabbix-web environment PHP_TZ value 'Europe/Moscow'

set container name zabbix-web port http source 8081
set container name zabbix-web port http destination 8080
set container name zabbix-web port http protocol tcp

commit

Access: http://<vyos-ip>:8081 (admin/zabbix)

Nginx Web Server

A static web server with a custom configuration:

set container network web prefix 172.23.0.0/24

set container name nginx image docker.io/nginx:latest
set container name nginx network web address 172.23.0.10
set container name nginx restart always

set container name nginx port http source 8080
set container name nginx port http destination 80
set container name nginx port http protocol tcp

set container name nginx port https source 8443
set container name nginx port https destination 443
set container name nginx port https protocol tcp

# Volumes
set container name nginx volume html source /config/www/html
set container name nginx volume html destination /usr/share/nginx/html
set container name nginx volume html mode ro

set container name nginx volume config source /config/www/nginx.conf
set container name nginx volume config destination /etc/nginx/nginx.conf
set container name nginx volume config mode ro

commit

Squid Proxy Server

An HTTP/HTTPS proxy:

set container network proxy prefix 172.24.0.0/24

set container name squid image docker.io/ubuntu/squid:latest
set container name squid network proxy address 172.24.0.10
set container name squid restart always

set container name squid port proxy source 3128
set container name squid port proxy destination 3128
set container name squid port proxy protocol tcp

set container name squid volume config source /config/squid/squid.conf
set container name squid volume config destination /etc/squid/squid.conf
set container name squid volume config mode ro

set container name squid volume cache source /config/squid/cache
set container name squid volume cache destination /var/spool/squid
set container name squid volume cache mode rw

commit

OpenVPN Client

A VPN client in a container for routing traffic:

set container network vpn prefix 172.25.0.0/24

set container name ovpn-client image docker.io/dperson/openvpn-client:latest
set container name ovpn-client network vpn address 172.25.0.10
set container name ovpn-client restart always

set container name ovpn-client capability net-admin

set container name ovpn-client volume config source /config/openvpn/client.ovpn
set container name ovpn-client volume config destination /vpn/client.ovpn
set container name ovpn-client volume config mode ro

set container name ovpn-client volume auth source /config/openvpn/auth.txt
set container name ovpn-client volume auth destination /vpn/auth.txt
set container name ovpn-client volume auth mode ro

set container name ovpn-client device source /dev/net/tun
set container name ovpn-client device destination /dev/net/tun

commit

Prometheus Monitoring

Metrics and monitoring:

set container network monitoring prefix 172.26.0.0/24

# Prometheus
set container name prometheus image docker.io/prom/prometheus:latest
set container name prometheus network monitoring address 172.26.0.10
set container name prometheus restart always

set container name prometheus port web source 9090
set container name prometheus port web destination 9090
set container name prometheus port web protocol tcp

set container name prometheus volume config source /config/prometheus/prometheus.yml
set container name prometheus volume config destination /etc/prometheus/prometheus.yml
set container name prometheus volume config mode ro

set container name prometheus volume data source /config/prometheus/data
set container name prometheus volume data destination /prometheus
set container name prometheus volume data mode rw

# Node Exporter (host metrics)
set container name node-exporter image docker.io/prom/node-exporter:latest
set container name node-exporter network monitoring address 172.26.0.11
set container name node-exporter restart always

set container name node-exporter port metrics source 9100
set container name node-exporter port metrics destination 9100
set container name node-exporter port metrics protocol tcp

# Grafana
set container name grafana image docker.io/grafana/grafana:latest
set container name grafana network monitoring address 172.26.0.12
set container name grafana restart always

set container name grafana port web source 3000
set container name grafana port web destination 3000
set container name grafana port web protocol tcp

set container name grafana volume data source /config/grafana
set container name grafana volume data destination /var/lib/grafana
set container name grafana volume data mode rw

set container name grafana environment GF_SECURITY_ADMIN_PASSWORD value 'admin123'

commit

Operational Commands

Viewing Containers

All containers:

show container

Example output:

NAME      STATE    IMAGE                           NETWORK
nginx     running  docker.io/library/nginx:latest  mynet
pihole    running  docker.io/pihole/pihole:latest  pihole

Container details:

show container nginx

Viewing Images

show container image

Viewing Networks

show container network

Example output:

NETWORK ID    NAME     DRIVER
abc123def456  mynet    bridge

Container Logs

show container log nginx

Last 50 lines:

show container log nginx tail 50

Restarting a Container

restart container nginx

Pulling an Image

add container image docker.io/nginx:alpine

Updating an Image

update container image nginx

Pulls a new version of the image (if available).

Deleting a Container

delete container name nginx
commit

Integration with VyOS

Firewall for Containers

Protecting access to containers:

# Allow access to nginx only from LAN
set firewall ipv4 forward filter rule 100 action accept
set firewall ipv4 forward filter rule 100 destination address 172.20.0.10
set firewall ipv4 forward filter rule 100 destination port 80
set firewall ipv4 forward filter rule 100 source address 192.168.1.0/24
set firewall ipv4 forward filter rule 100 protocol tcp

set firewall ipv4 forward filter rule 101 action drop
set firewall ipv4 forward filter rule 101 destination address 172.20.0.10
set firewall ipv4 forward filter rule 101 destination port 80
set firewall ipv4 forward filter rule 101 protocol tcp

commit

NAT for Containers

Containers with internet access through NAT:

# SNAT for the container network
set nat source rule 100 source address 172.20.0.0/16
set nat source rule 100 outbound-interface name eth0
set nat source rule 100 translation address masquerade

commit

DNAT for publishing a service:

# Forward port 80 of the external IP to the container
set nat destination rule 10 destination address 203.0.113.10
set nat destination rule 10 destination port 80
set nat destination rule 10 inbound-interface name eth0
set nat destination rule 10 protocol tcp
set nat destination rule 10 translation address 172.20.0.10
set nat destination rule 10 translation port 80

commit

Routing for Containers

A static route for the container network:

set protocols static route 172.20.0.0/16 interface eth1
commit

VRF Isolation

Containers in a separate VRF:

# Create a VRF
set vrf name CONTAINERS table 100
set vrf name CONTAINERS description 'Container network'

# Container network in the VRF
set container network mynet vrf CONTAINERS
set container network mynet prefix 172.20.0.0/16

commit

Integration with Cloud Platforms

Yandex Cloud

When deploying VyOS in Yandex Cloud, containers can be used to integrate with cloud services:

Container Registry integration:

# Using Yandex Container Registry
set container registry yandex address cr.yandex
set container registry yandex authentication username oauth
set container registry yandex authentication password '<yandex-oauth-token>'
commit

# Running a container from Yandex Container Registry
set container name myapp image cr.yandex/<registry-id>/myapp:latest
commit

Monitoring with Yandex Monitoring:

# Prometheus exporter for metrics in Yandex Monitoring
set container name unified-agent image cr.yandex/yc/unified-agent:latest
set container name unified-agent network monitoring
set container name unified-agent environment FOLDER_ID value '<folder-id>'
set container name unified-agent environment IAM_TOKEN value '<iam-token>'
commit

Logging to Yandex Cloud Logging:

# Fluent Bit for sending logs
set container name fluent-bit image cr.yandex/yc/fluent-bit:latest
set container name fluent-bit network monitoring
set container name fluent-bit volume config source /config/fluent-bit.conf
set container name fluent-bit volume config destination /fluent-bit/etc/fluent-bit.conf
set container name fluent-bit volume config mode ro
commit

VK Cloud

Integration with VK Cloud (Mail.ru Cloud Solutions):

VK Cloud Container Registry:

# Configuring the registry for VK Cloud
set container registry vkcloud address hub.mcs.mail.ru
set container registry vkcloud authentication username '<username>'
set container registry vkcloud authentication password '<password>'
commit

# Running a container from the VK Cloud Registry
set container name myapp image hub.mcs.mail.ru/<project>/myapp:latest
commit

S3-compatible storage:

# MinIO client for integration with VK Cloud S3
set container name minio-client image docker.io/minio/mc:latest
set container name minio-client network storage
set container name minio-client environment MC_HOST_vkcloud value 'https://<access-key>:<secret-key>@hb.vkcs.cloud'
commit

Troubleshooting

Container Will Not Start

Check the status:

show container myapp

Check the logs:

show container log myapp

Journald logs:

journalctl -u vyos-container-myapp -n 50

Image Will Not Pull

Check registry availability:

ping registry.example.com

Check DNS:

nslookup docker.io

Check authentication:

show container registry

Network Issues

Check the container network:

show container network

Check the container IP:

show container myapp

Ping from VyOS:

ping 172.20.0.10

Ports Are Not Reachable

Check port forwarding:

show configuration commands | grep "container name myapp port"

Check the firewall:

show firewall

Check NAT:

show nat source rules
show nat destination rules

Volume Issues

Check permissions:

ls -la /config/myapp

Make sure the directory exists:

mkdir -p /config/myapp

High Resource Usage

Check usage:

show container

Set limits:

set container name myapp cpu-quota 50
set container name myapp memory 512
commit

Security

Least Privilege

Run containers with minimal capabilities:

# Avoid
set container name myapp capability all

# Prefer
set container name myapp capability net-admin

Network Isolation

Use separate networks for different applications:

set container network web prefix 172.20.0.0/24
set container network db prefix 172.21.0.0/24

Read-only Volumes

Mount configuration as read-only:

set container name myapp volume config mode ro

Regular Updates

Update images to receive security patches:

update container image myapp
restart container myapp

Firewall Protection

Restrict access to containers through the firewall:

set firewall ipv4 forward filter rule 100 action accept
set firewall ipv4 forward filter rule 100 destination address 172.20.0.0/24
set firewall ipv4 forward filter rule 100 source address 192.168.1.0/24

set firewall ipv4 forward filter rule 999 action drop
set firewall ipv4 forward filter rule 999 destination address 172.20.0.0/24

Resource Limits

Prevent DoS by limiting resources:

set container name myapp cpu-quota 50
set container name myapp memory 512
commit

Performance

Resource Allocation

Plan resources for containers:

Recommendations:

  • Web server: 256-512 MB, CPU 25-50%
  • Database: 1024-2048 MB, CPU 50-100%
  • Monitoring: 512-1024 MB, CPU 25-50%

Storage Performance

For databases, use separate disks:

# Mount an SSD for the database
set container name postgres volume data source /mnt/ssd/postgres
set container name postgres volume data destination /var/lib/postgresql/data
set container name postgres volume data mode rw

Network Performance

Use MTU optimization:

set container network mynet mtu 9000

For jumbo frames on supported hardware.

Limitations

  • Podman runs in rootless mode with limitations
  • Some containers require privileged mode (all capabilities)
  • Graphical applications are not supported
  • Large containers (>1GB RAM) may affect VyOS performance
  • Containers restart when VyOS reboots

Best Practices

  1. Use /config - for persistent data
  2. Limit resources - set CPU and memory limits
  3. Least privilege - only the necessary capabilities
  4. Separate networks - isolate by function
  5. Firewall protection - control access
  6. Regular updates - update images
  7. Monitoring - track logs and resources
  8. Backups - include /config/containers in the backup
  9. Testing - verify containers before production
  10. Documentation - describe the purpose of containers

Additional Resources

Next Steps

  • Firewall - protecting containers
  • NAT - publishing services
  • VRF - isolating container networks
  • System - monitoring resources
Reviewed by OpenNix LLC · Last updated on