bindings

rfswift bindings

Dynamically add or remove volume mounts and device bindings to running containers.

Synopsis

# Add volume binding
rfswift bindings add -c CONTAINER -s SOURCE -t TARGET

# Add device binding  
rfswift bindings add -d -c CONTAINER -s SOURCE -t TARGET

# Remove volume binding
rfswift bindings rm -c CONTAINER -s SOURCE -t TARGET

# Remove device binding
rfswift bindings rm -d -c CONTAINER -s SOURCE -t TARGET

The bindings command allows you to add or remove volume mounts and device mappings to containers without restarting them. This is part of RF Swift’s dynamic container management features and works identically with both Docker and Podman.


Subcommands

bindings add

Add a new volume mount or device binding to a container.

Options:

Flag Description Required Example
-c, --container STRING Container ID or name Yes -c my_container
-s, --source STRING Source path/device Optional* -s ~/captures
-t, --target STRING Target path in container Yes -t /root/captures
-d, --devices Manage device (not volume) No -d
If source is omitted, source equals target.

bindings rm

Remove an existing volume mount or device binding from a container.

Options:

Flag Description Required Example
-c, --container STRING Container ID or name Yes -c my_container
-s, --source STRING Source path/device Optional* -s ~/captures
-t, --target STRING Target path in container Yes -t /root/captures
-d, --devices Manage device (not volume) No -d
If source is omitted, source equals target.

Examples

Volume Bindings

Add volume mount:

rfswift bindings add -c my_container \
  -s ~/captures \
  -t /root/captures

Add multiple volumes:

rfswift bindings add -c sdr_work -s ~/data -t /root/data
rfswift bindings add -c sdr_work -s ~/scripts -t /root/scripts
rfswift bindings add -c sdr_work -s ~/configs -t /root/.config

Add read-only volume:

rfswift bindings add -c container \
  -s ~/reference-data \
  -t /root/reference:ro

Remove volume mount:

rfswift bindings rm -c my_container \
  -s ~/captures \
  -t /root/captures

Device Bindings

Add USB device:

rfswift bindings add -d -c sdr_work \
  -s /dev/bus/usb \
  -t /dev/bus/usb

or more simply if the target and source are the same:

rfswift bindings add -d -c sdr_work \
 -t /dev/bus/usb
If you know you will plug and unplug devices, just use the volume by turning off the -d switch.

Add USB serial device:

rfswift bindings add -d -c analysis \
  -s /dev/ttyUSB0 \
  -t /dev/ttyUSB0

How Bindings Work

Dynamic Mounting

When you add a binding to a running container:

  1. Container configuration updated by the active engine (Docker or Podman)
  2. Namespace modified to include new mount/device
  3. Immediate access — no restart needed
  4. Persists until removed or container deleted
  graph LR
    A[Host Directory/Device] -->|Bind Mount| B[Container Namespace]
    B -->|Access| C[Container Process]
    C -->|Read/Write| A

Volume vs Device Bindings

Volume Bindings (without -d):

  • Mount host directories into container
  • Share files between host and container
  • Two-way sync (changes visible on both sides)
  • Use for: data, configs, scripts
  • Can be used to share devices and resists hot-(un)plug

Device Bindings (with -d):

  • Expose hardware devices to container
  • Direct device access
  • Requires proper permissions (cgroups)
  • Use for: SDR, serial, USB devices
  • Not hot-(un)plug resistant

Docker processes bindings through the Docker daemon. The daemon handles namespace modifications and device cgroup rules on behalf of the container.

  • Device bindings require the Docker daemon to have access to the host device
  • Cgroup rules are applied via the daemon’s cgroup driver
  • No additional user-level configuration needed beyond group membership (docker group)

Podman processes bindings directly in user space (no daemon involved). In rootless mode, there are a few differences to be aware of:

  • Volume ownership: Files created inside the container may appear owned by your UID on the host (mapped through the user namespace). Use podman unshare chown if you need to fix permissions.
  • Device access: Some /dev devices require the host user to have read/write permissions. Check with ls -l /dev/your_device and add your user to the appropriate group (e.g., dialout, plugdev).
  • USB passthrough: Binding /dev/bus/usb as a volume (without -d) is often the most reliable approach in rootless mode.
  • Cgroup v2: RF Swift auto-detects cgroup version and applies device access rules accordingly.

Bindings vs Initial Mount

Comparison

Feature Runtime Bindings Initial Mount (run -b)
When After creation At creation
Restart needed ❌ No N/A (during creation)
Modification ✅ Can add/remove ❌ Fixed
Performance Same Same
Use case Dynamic needs Known requirements
Engine support Docker ✅ Podman ✅ Docker ✅ Podman ✅

When to Use Each

Use runtime bindings when:

  • ✅ Requirements change during work
  • ✅ Hot-plugging devices
  • ✅ Temporary data access
  • ✅ Testing different configurations
  • ✅ Adding forgotten mounts

Use initial -b flag when:

  • ✅ Requirements known upfront
  • ✅ Permanent mounts needed
  • ✅ Creating container fresh
  • ✅ Documenting standard setup

Example:

# Initial mount at creation
rfswift run -i sdr_full -n work \
  -b /pathto/scripts:/root/scripts

# Later add more dynamically
rfswift bindings add -c work -s /pathto/captures -t /root/captures

# Add device when plugged in
rfswift bindings add -d -c work -s /dev/bus/usb -t /dev/bus/usb

Troubleshooting

Binding Not Visible in Container

Problem: Added binding but can’t see it in container

Solutions:

# Check if binding was actually added
docker inspect container | grep -A5 Binds

# Try accessing directly
rfswift exec -c container
ls -la /path/to/binding
exit

# Remove and re-add with correct paths
rfswift bindings rm -c container -s source -t target
rfswift bindings add -c container -s source -t target
# Check if binding was actually added
podman inspect container | grep -A5 Binds

# Try accessing directly
rfswift exec -c container
ls -la /path/to/binding
exit

# Remove and re-add with correct paths
rfswift bindings rm -c container -s source -t target
rfswift bindings add -c container -s source -t target

Device Access Denied

Problem: Device binding added but access denied in container

Solutions:

# Add device binding
rfswift bindings add -d -c container -s /dev/device -t /dev/device

# Add cgroup rule for device access
rfswift cgroups add -c container -r "c 189:* rwm"

# Check device major:minor numbers
ls -l /dev/device
# Example: crw-rw---- 1 root dialout 189, 0

# Add rule for correct major number
rfswift cgroups add -c container -r "c 189:* rwm"
# Ensure your user is in the docker group
groups $USER | grep docker

# If not, add and re-login
sudo usermod -aG docker $USER
newgrp docker
# Check host-level device permissions
ls -l /dev/ttyUSB0
# crw-rw---- 1 root dialout 188, 0 ...

# Add your user to the device group
sudo usermod -aG dialout $USER
newgrp dialout

# For broad USB access in rootless mode, bind as volume instead
rfswift bindings add -c container \
-s /dev/bus/usb \
-t /dev/bus/usb

# If using cgroup v2, RF Swift handles device rules automatically
# but you can verify:
cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers

Permission Denied on Volume

Problem: Can’t write to mounted volume

Solutions:

# Check host directory permissions
ls -ld ~/data

# Fix permissions
chmod 755 ~/data

# Or use capabilities
rfswift capabilities add -c container -p DAC_OVERRIDE
# Check host directory permissions
ls -ld ~/data

# Fix permissions
chmod 755 ~/data

# Podman rootless: files may be mapped to a different UID
# Use podman unshare to fix ownership
podman unshare chown -R 0:0 ~/data

# Or use the :Z/:z SELinux label options if on Fedora/RHEL
rfswift bindings add -c container \
-s ~/data \
-t /root/data:z

Source Path Not Found

Error: source path does not exist

Solutions:

# Check source path exists
ls -la /path/to/source

# Create directory if needed
mkdir -p ~/data

# Use absolute path
rfswift bindings add -c container \
  -s /home/user/data \
  -t /root/data

Cannot Remove Binding

Problem: rm command fails

Solutions:

# Check exact paths used
docker inspect container | grep -A10 Binds

# Use same source and target as when added
rfswift bindings rm -c container \
-s /exact/source/path \
-t /exact/target/path

# If still fails, recreate container (last resort)
# Check exact paths used
podman inspect container | grep -A10 Binds

# Use same source and target as when added
rfswift bindings rm -c container \
-s /exact/source/path \
-t /exact/target/path

# If still fails, recreate container (last resort)

Device Not Found

Problem: Device doesn’t exist at specified path

Solutions:

# Check device exists
ls -l /dev/bus/usb

# Check device name pattern
ls -l /dev | grep rtl

# On some systems, udev rules may rename devices
# Check dmesg for the actual device path
dmesg | tail -20

Related Commands

  • run - Create containers with initial bindings
  • engine - Select container engine (Docker/Podman)
  • cgroups - Manage device permissions
  • capabilities - Manage container capabilities
  • exec - Access container after adding bindings

🔌
Hot-Plugging: The bindings command enables hot-plugging devices and volumes without container restart. Perfect for SDR work where devices are frequently connected/disconnected!
Device Permissions: Adding device bindings (-d flag) usually requires corresponding cgroup rules. Use rfswift cgroups add to grant device access after adding the binding.
Volumes vs Devices: Use bindings add without -d for directories/files (volumes), and with -d for hardware devices like SDRs, USB devices, serial ports, etc. Both modes work identically with Docker and Podman.
Last updated on