Automatically reconnect to USB files on running container?

I’m working on configuring a Ubuntu 22.04 LTS system to function as a server for a custom app, running in a Docker Compose container.

This is my yaml file:

version: "3.9"
services:
    production:
        image: customapp:v17.2.5
        container_name: customapp
        restart: unless-stopped
        tty: true
        network_mode: "host"
        volumes:
        - /production/app-data/production-data:/data
        - /production/app-data/backupdrv:/data/backupdrv
        - /production/app-data/certs:/etc/certs/<ssl cert files>

As you can see, a few volumes are linked, one of these is the /backupdrv directory. This is a directory on a USB stick where our app stores and re-stores backups.

The problem I’m running into is that if the USB stick isn’t mounted when the Docker container is started, the backup files aren’t accessible. Makes sense of course, but they remain inaccessible even after you plug in the USB stick post-Docker start.

We will be deploying this server twice, one main unit and a secondary server in case the first one ever breaks down. In order to get the secondary server up and running, our client will need to plug the USB stick with the backup files from one server into the other. This is why we need the Docker container to dynamically pick up when these USB files are available. We don’t want to have to teach our client to manually restart the server in case they need to swap the backup USB stick.

Outside of Docker, I’ve tried to trigger a ‘docker compose restart’ command using a udev rule and while that DOES seem to restart the Docker container, the USB files end up not being connected. The only way the USB files are picked up properly is if I manually run the restart script from a terminal on the server or via SSH.

Does anyone know if there’s a way for Docker to re-initialize (USB) volumes while the container is already running?

AFAIK the mounting of the host folders only happens during container startup, so there would be no way to enable it later.

The only workaround I see could be to create a link to the USB on the host and mount that link. Maybe the link is mounted without files and showing files when USB is inserted. I am not a Linux expert, so you need to try. Report back when it works.

I did some more digging into triggering scripts when you connect USB devices in Linux using udev rules.
Turns out my earlier experiment with those failed because it triggered on when the USB stick was INSERTED, not mounted. When I added a few sleep commands in my script I started noticing the USB stick wasn’t actually getting mounted as long as the scripts were running, but only afterwards.

In the end I solved it by doing this:

sudo nano /etc/udev/rules.d/99-usb-trigger.rules

SUBSYSTEM=="block", KERNEL=="sd*", ENV{DEVTYPE}=="disk", ATTRS{idVendor}=="2009", ATTRS{idProduct}=="7100", ACTION=="change", ENV{ID_FS_TYPE}=="ext4", RUN+="/bin/bash -c '/path/to/script/usb-test.sh'"

sudo udevadm control --reload-rules

The idVendor and idProduct values are different for every USB device, you can figure them out via the lsusb command, the values will be shown as idVendor:idProduct. This ensures the udev rule only triggers when this specific USB drive is mounted.

The usb-test.sh script then contains the following:

cd /docker-compose-folder/
docker compose restart 
wall "Docker has been restarted!"
exit 0

So far this has consistently restarted and properly linked the files on the USB drive to the docker container.

Turns out this was more of an excercise in Linux tinkering, rather than Docker, but it works! :smiley:

1 Like