Network Shares
Many industrial sites keep their files on a NAS or a Windows file server on the local network — scan results go to \\nas\production, reports are read from a shared folder, machines exchange files through SMB. An IronFlock app can mount such a share directly into its containers, so your code reads and writes it like a local directory.
This is the on-premises counterpart to File Storage: File Storage is the platform’s managed object storage, a network share is the customer’s own file server on the customer’s own LAN. Use a share when the files must land in the customer’s existing infrastructure.
Two protocols are supported: SMB/CIFS (Windows file servers, virtually every NAS) and NFS (common on Linux-based servers).
How it works
The mount is declared as a named volume in your app’s docker-compose.yml, using Docker’s built-in local volume driver. The Docker engine on the device performs the mount itself when your containers start — nothing has to be installed on the device, and the device user never touches a command line.
The share’s address and credentials are not written into your compose file. They are ${VARIABLE} placeholders, filled per device from app parameters — the same mechanism as every other per-device setting. Users configure the share in the app’s Parameters form on each device (or once per device group), and restart the app.
Declaring the volume
Add a named volume with driver_opts to your docker-compose.yml and mount it into the services that need it:
services:
app:
build: .
volumes:
- netshare:/mnt/share
restart: unless-stopped
volumes:
netshare:
# Docker volumes keep the settings they were created with. Putting the
# revision parameter into the volume name means: bump the revision, restart
# the app, and a fresh volume with the current settings is created.
name: "${APP_NAME}_share_r${SHARE_REV:-1}"
driver: local
driver_opts:
type: cifs
device: "//${SHARE_HOST}/${SHARE_NAME}"
o: "username=${SHARE_USER},password=${SHARE_PASSWORD},vers=3.0,uid=1000,gid=1000"Your code then works with /mnt/share as an ordinary directory.
The pieces worth understanding:
| Field | Meaning |
|---|---|
device | The share address: //server/sharename for SMB |
o | Mount options, comma-separated. vers=3.0 selects the SMB protocol version; uid/gid decide which container user owns the files — match them to the user your process runs as |
name | The volume’s identity on the device. Docker never changes an existing volume, so the settings revision is part of the name — see below |
${VAR:-fallback} | Compose interpolation with a default. Give every placeholder a default (even an empty one) so the file always parses |
APP_NAME is one of the standard variables the platform provides automatically; it scopes the volume name to your app.
Making it configurable
Declare the placeholders in .ironflock/env-template.yml so users get a proper form — with the password masked as a secret:
SHARE_HOST:
label: "File server (IP or hostname)"
type: text
defaultValue: ""
description: "The SMB server or NAS on the device's local network."
SHARE_NAME:
label: "Share name"
type: text
defaultValue: ""
SHARE_USER:
label: "Username"
type: text
defaultValue: ""
SHARE_PASSWORD:
label: "Password"
type: text
secret: true
defaultValue: ""
SHARE_REV:
label: "Storage settings revision"
type: numeric
defaultValue: 1
description: "Increase by 1 whenever you change one of the settings above, then restart the app."On each device, the user fills in the form under the app’s Parameters, saves, and restarts the app. Setting the parameters at the device-group level configures a whole fleet against the same file server in one step.
Changing settings later
Docker creates a volume the first time it is used and keeps its settings from that moment on — editing the parameters alone does not re-point an existing volume. That is what the revision parameter is for: after changing any share setting, the user increases the revision by 1 and restarts the app. The new volume name makes Docker create the mount freshly with the current values.
Nothing on the file server is affected by any of this: the volume is only a mount definition. Creating it, recreating it under a new revision, or uninstalling the app never deletes files on the share.
NFS
For an NFS server, the same pattern with different driver_opts:
volumes:
netshare:
name: "${APP_NAME}_share_r${SHARE_REV:-1}"
driver: local
driver_opts:
type: nfs
device: ":${SHARE_PATH}"
o: "addr=${SHARE_HOST},nfsvers=4"SHARE_PATH is the exported path (e.g. /exports/production), addr the server. Prefer NFSv4 (nfsvers=4) — it needs only the one option and no extra services on the device.
Device support
| Device type | SMB/CIFS | NFS |
|---|---|---|
| Linux devices (custom Linux installation) | ✓ | ✓ |
| Windows devices (Docker Desktop) | ✓ | ✓ |
| FlockOS devices | not yet available | not yet available |
On Windows devices the mount happens inside Docker Desktop’s Linux environment, which ships both protocol clients — it works out of the box, including reaching SMB servers on the device’s LAN. On Linux devices the standard distribution kernels bring the protocol support; no packages need to be installed. Support on FlockOS requires an operating system update that is not yet released — talk to us if you need it there.
Mounting requires an up-to-date device agent; agents update themselves automatically.
Good to know
- Unconfigured devices: until the parameters are filled in, the app fails to start with a mount error in its live logs. If your app must also run without a share, don’t mount one unconditionally — read the parameters in your code and skip the share-dependent features instead.
- Credentials: create a dedicated account on the file server with access to just this share, and use that in the parameters. The password is masked in the platform UI but is handed to the device that performs the mount — treat it as device-local material, not as a global admin credential.
- No commas in passwords: the SMB options travel as a comma-separated string, so a password containing a comma breaks the mount. Choose the share account’s password accordingly.
- Server address: use an IP address or a name the site’s DNS resolves. mDNS names like
nas.localare often not resolvable from inside the Docker engine. - Firewall: the device reaches the file server on TCP 445 (SMB) or TCP 2049 (NFS). On segmented factory networks, make sure that path is open.
- File ownership (SMB): files appear inside the container owned by the
uid/gidfrom the mount options. If your process runs as a non-root user, set them to that user, or writes will fail.