Skip to content

Docker Compose

This guide shows how to use Docker Compose to run a flexFS mount as a sidecar container alongside your application containers. The sidecar pattern keeps the FUSE mount in a dedicated container that shares its filesystem with the application containers via a shared volume.

Docker Compose sidecar architecture: flexfs-mount container performs FUSE mount into a shared volume, application container reads and writes from the shared volume, and flexfs-mount connects via HTTPS to Object Storage Docker Compose sidecar architecture: flexfs-mount container performs FUSE mount into a shared volume, application container reads and writes from the shared volume, and flexfs-mount connects via HTTPS to Object Storage
services:
flexfs-mount:
image: flexfs-mount:latest
cap_add:
- SYS_ADMIN
devices:
- /dev/fuse
security_opt:
- apparmor=unconfined
volumes:
- /tmp/flexfs-shared:/mnt/data:rshared
- ./creds:/etc/flexfs/creds:ro
command: >
start <volume-name> /mnt/data
--foreground
--credsFile /etc/flexfs/creds
restart: unless-stopped
healthcheck:
test: ["CMD", "mountpoint", "-q", "/mnt/data"]
interval: 10s
timeout: 5s
retries: 3
application:
image: your-application:latest
volumes:
- /tmp/flexfs-shared:/data:rshared
depends_on:
flexfs-mount:
condition: service_healthy

There is no published mount.flexfs container image, so the flexfs-mount:latest image the compose file names is one you build. Create a build directory holding the mount binary and the Dockerfile shown below, then build it:

Terminal window
mkdir -p flexfs-image
cp /sbin/mount.flexfs flexfs-image/
# save the Dockerfile from "Using a dedicated flexFS image" as flexfs-image/Dockerfile
docker build -t flexfs-mount:latest ./flexfs-image

Alternatively, replace the service’s image: with build: ./flexfs-image and let Compose build it — see Using a dedicated flexFS image.

Terminal window
cat > creds <<EOF
adminAddr = "<admin-addr>"
token = "<volume-token>"
EOF
chmod 600 creds

chmod 600 is required, not advisory: flexFS refuses to read a credentials file that grants any permission to its group or to other users. Ownership is not checked, so a file created by a non-root user works when bind-mounted into a container that runs as root.

Create it and mark it shared, so the FUSE mount made inside the sidecar propagates to the application container:

Terminal window
mkdir -p /tmp/flexfs-shared
sudo mount --bind /tmp/flexfs-shared /tmp/flexfs-shared
sudo mount --make-rshared /tmp/flexfs-shared
Terminal window
docker compose up -d
Terminal window
# Check mount sidecar health
docker compose ps
# Verify mount inside the application container
docker compose exec application ls /data

The image built in step 1 comes from this Dockerfile:

FROM ubuntu:24.04
RUN apt-get update && apt-get install -y fuse3 ca-certificates && rm -rf /var/lib/apt/lists/*
COPY mount.flexfs /sbin/mount.flexfs
RUN chmod +x /sbin/mount.flexfs
ENTRYPOINT ["/sbin/mount.flexfs"]

Then reference it in docker-compose.yml:

services:
flexfs-mount:
build: ./flexfs-image
cap_add:
- SYS_ADMIN
devices:
- /dev/fuse
security_opt:
- apparmor=unconfined
volumes:
- /tmp/flexfs-shared:/mnt/data:rshared
- ./creds:/etc/flexfs/creds:ro
command: >
start <volume-name> /mnt/data
--foreground
--credsFile /etc/flexfs/creds

To mount multiple flexFS volumes, add additional sidecar services:

services:
flexfs-input:
image: flexfs-mount:latest
cap_add:
- SYS_ADMIN
devices:
- /dev/fuse
security_opt:
- apparmor=unconfined
volumes:
- /tmp/flexfs-input:/mnt/data:rshared
- ./creds-input:/etc/flexfs/creds:ro
command: start input-volume /mnt/data --foreground --credsFile /etc/flexfs/creds
healthcheck:
test: ["CMD", "mountpoint", "-q", "/mnt/data"]
interval: 10s
timeout: 5s
retries: 3
flexfs-output:
image: flexfs-mount:latest
cap_add:
- SYS_ADMIN
devices:
- /dev/fuse
security_opt:
- apparmor=unconfined
volumes:
- /tmp/flexfs-output:/mnt/data:rshared
- ./creds-output:/etc/flexfs/creds:ro
command: start output-volume /mnt/data --foreground --credsFile /etc/flexfs/creds
healthcheck:
test: ["CMD", "mountpoint", "-q", "/mnt/data"]
interval: 10s
timeout: 5s
retries: 3
application:
image: your-application:latest
volumes:
- /tmp/flexfs-input:/input:rshared
- /tmp/flexfs-output:/output:rshared
depends_on:
flexfs-input:
condition: service_healthy
flexfs-output:
condition: service_healthy

Create each host directory and mark it shared before starting, as in the single-volume setup:

Terminal window
for d in /tmp/flexfs-input /tmp/flexfs-output; do
mkdir -p "$d"
sudo mount --bind "$d" "$d"
sudo mount --make-rshared "$d"
done

To mount a volume as read-only, add --ro to the mount command:

command: start <volume-name> /mnt/data --foreground --credsFile /etc/flexfs/creds --ro

docker compose down stops the application containers before the sidecars they depend on. The mount.flexfs process then receives SIGTERM, writes out pending data, unmounts the filesystem, finishes pending uploads, and exits. If a process still has a file open under the mount, the unmount fails and the mount keeps serving. Docker kills the container when its stop grace period (10 seconds by default) ends, and writes not yet uploaded at that point can be lost. Set stop_grace_period on the sidecar service to allow time for uploads to finish:

services:
flexfs-mount:
stop_grace_period: 2m