This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Container Implementation
Relevant source files
This page documents the Docker container's internal structure, build process, and runtime behavior. It explains how the docker-sshfs image is constructed from a base Ubuntu system and configured to run both SSHFS and Samba services within a single container.
For step-by-step instructions on building and running the container, see Getting Started. For detailed line-by-line Dockerfile analysis, see Dockerfile Breakdown. For configuration file details, see Configuration Reference.
Purpose and Scope
The docker-sshfs container serves as an isolated environment that bridges SSH and SMB protocols without requiring macFUSE installation on the host macOS system. This page covers:
- Container base image and package dependencies
- Build-time configuration and setup
- Internal directory structure and symbolic links
- User accounts and permission model
- Service startup and process management
The container is built from Dockerfile:1-34 and configured to run as a single-process service with smbd as the main foreground process.
Sources: Dockerfile:1-34 README.md:1-90
Container Base Architecture
Diagram: Container Build Stages and Component Relationships
The container is constructed in layers, with each build stage producing artifacts used by subsequent stages. The Dockerfile2 specifies ubuntu:latest as the base image, which provides the Linux kernel interface and standard utilities. Package installation at Dockerfile:5-6 adds SSHFS and Samba along with their dependencies (FUSE libraries, OpenSSH client).
Sources: Dockerfile:1-34
Build Process Overview
| Build Stage | Dockerfile Lines | Action | Artifacts Created |
|---|---|---|---|
| Base Image | Dockerfile2 | Pull ubuntu:latest | Linux OS environment |
| Package Install | Dockerfile:5-6 | apt-get install sshfs samba | SSHFS client, Samba server binaries |
| User Creation | Dockerfile9 | Create sshuser account | Non-root user (UID 1000) |
| Directory Setup | Dockerfile:12-15 | Create /remote and /samba-share | Mount points |
| Config Copy | Dockerfile18 | Copy smb.conf to /etc/samba/ | Samba configuration |
| Permissions | Dockerfile21 | chmod 777 /samba-share | World-writable share |
| FUSE Config | Dockerfile24 | Enable user_allow_other | Cross-user mount access |
| Port Exposure | Dockerfile27 | EXPOSE 139 445 | SMB port metadata |
| Symbolic Link | Dockerfile30 | ln -s /remote /samba-share/remote | Integration point |
| Entry Point | Dockerfile33 | Set CMD for smbd | Process definition |
The build process is deterministic and produces an image containing all necessary components. The container does not require external volume mounts for its core functionality, as all configuration is baked into the image at build time.
Sources: Dockerfile:1-34
Component Integration Map
Diagram: Runtime Component Interactions
The container implements a two-process model where smbd runs as the main container process (PID 1) and sshfs is spawned manually by users via docker exec. The symbolic link at Dockerfile30 creates the integration point between these processes, allowing smbd to serve files that sshfs has mounted from the remote server.
Sources: Dockerfile:1-34 README.md:41-50
Privileged Container Requirements
The container must run with the --privileged flag as specified in README.md31 This requirement stems from FUSE's need for device access:
| Capability | Required For | Alternative |
|---|---|---|
| Device Access | FUSE /dev/fuse device | None - FUSE requires device access |
| Mount Operations | Creating mount points in container namespace | None - fundamental to SSHFS |
| Process Management | FUSE background processes | None - needed for daemon operation |
The README.md31 command docker run --privileged grants the container access to host devices, specifically /dev/fuse, which SSHFS requires to implement the FUSE filesystem driver. Without privileged mode, SSHFS mount operations fail with permission errors.
While this increases the container's privileges, the security risk is mitigated by:
- Port binding to
127.0.0.1only (README.md31) - Guest-only access configuration in
smb.conf - No sensitive data stored in the container itself
Sources: README.md31 Dockerfile:1-34
Build-Time vs Runtime Operations
Diagram: Build vs Runtime Operations Timeline
A critical design decision is that SSHFS mounting happens at runtime , not build time. The Dockerfile:1-34 only creates the infrastructure (directories, symbolic links, configurations), while actual remote filesystem mounting occurs via user commands after the container is running (README.md:41-50). This separation allows:
- Dynamic remote server configuration (no hardcoded endpoints)
- Multiple mount/unmount cycles without container restart
- SSH credential handling outside the container image
The CMD at Dockerfile33 defines smbd --foreground --no-process-group --debug-stdout as the container's main process, ensuring Samba starts automatically but SSHFS requires manual invocation.
Sources: Dockerfile33 README.md:30-50
Key Implementation Details
Non-Root User (sshuser)
The Dockerfile9 line useradd -m sshuser && echo "sshuser:sshpass" | chpasswd creates a non-root user for SSHFS operations. This user:
- Has UID 1000 and GID 1000 (standard first non-system user)
- Owns SSHFS mount processes
- Is forced by Samba via
force user = sshuserinsmb.conf - Has password
sshpass(for internal use if needed)
The UID/GID values (1000) are referenced in mount commands at README.md49 as -o uid=1000,gid=1000, ensuring file ownership consistency between SSHFS-mounted files and Samba-served files.
World-Writable Share Directory
The Dockerfile21 command chmod -R 777 /samba-share makes the Samba root directory world-writable. This permission is necessary because:
smbdruns as root but accesses files assshuser(viaforce user)sshfsmounts files owned by UID 1000 (sshuser)- Without 777 permissions, Samba cannot traverse the directory
The commented-out line Dockerfile20 shows an alternative approach using chown, which was replaced with the more permissive chmod 777.
FUSE Configuration
The Dockerfile24 line echo "user_allow_other" >> /etc/fuse.conf modifies the system-wide FUSE configuration to enable the allow_other mount option. Without this:
- SSHFS mounts would only be accessible to the mounting user
smbd(running as root, accessing as sshuser) couldn't read the mounted files- The symbolic link integration would fail
This setting is referenced in mount commands at README.md49 as -o allow_other.
Symbolic Link Strategy
The Dockerfile30 command ln -s /remote /samba-share/remote creates a symbolic link before any SSHFS mount exists. This pre-created link:
- Points to an empty
/remotedirectory initially - Becomes populated when SSHFS mounts to
/remote - Allows Samba to serve SSHFS-mounted content without reconfiguration
This is a zero-copy integration technique - files are not duplicated, just made accessible through multiple paths.
Sources: Dockerfile9 Dockerfile:20-21 Dockerfile24 Dockerfile30 README.md49
Port Exposure and Networking
Diagram: Port Configuration Flow
The Dockerfile27 EXPOSE 139 445 directive is metadata only - it does not actually bind or forward ports. Actual port mapping occurs at runtime via README.md31 with -p 127.0.0.1:139:139 -p 127.0.0.1:445:445, which:
- Maps container ports 139 and 445 to host localhost
- Restricts access to
127.0.0.1(not0.0.0.0) - Requires container IP for actual connections (localhost forwarding doesn't work with macOS SMB client)
Port 139 provides NetBIOS session service, while port 445 handles direct SMB over TCP. Both are required for full Samba functionality.
Sources: Dockerfile27 README.md31
Service Lifecycle and Process Management
The Dockerfile33 CMD directive defines the container's main process:
CMD ["smbd", "--foreground", "--no-process-group", "--debug-stdout"]
| Flag | Purpose | Consequence |
|---|---|---|
--foreground | Run in foreground (don't daemonize) | Container stays alive |
--no-process-group | Don't create new process group | Proper signal handling |
--debug-stdout | Log to stdout instead of files | Docker logs capture output |
This configuration ensures smbd runs as PID 1 and the container lifecycle matches the Samba service lifecycle. When smbd exits, the container stops. The process handles SIGTERM for graceful shutdown.
Unlike typical system deployments where Samba runs as a background daemon, this container runs Samba as the primary foreground process, following Docker best practices for single-service containers.
Sources: Dockerfile33
Image Layers and Size
The Docker image consists of multiple layers corresponding to Dockerfile instructions:
- Base
ubuntu:latestlayer (~30-80 MB depending on version) apt-get updatemetadata layer (~40 MB)sshfsandsambapackage layers (~80 MB combined)- User creation layer (minimal)
- Directory creation layers (minimal)
- Configuration file layers (< 1 MB)
- Permission modification layers (minimal)
The final image size is approximately 200-250 MB. Most space is consumed by:
- Ubuntu base system
- Samba binaries and libraries
- FUSE and SSHFS utilities
- OpenSSH client dependencies
The Dockerfile:5-6 package installation is the largest layer due to dependency trees for both sshfs (requiring libfuse2, openssh-client) and samba (requiring numerous libraries for SMB protocol implementation).
Sources: Dockerfile:1-34
Summary
The docker-sshfs container is a purpose-built environment that combines SSHFS and Samba in a single image. Key characteristics:
- Base : Ubuntu Linux with standard package manager
- Services : SSHFS (user-invoked) and Samba (auto-start)
- Integration : Symbolic link + FUSE
allow_other+ forced user identity - Security : Privileged mode for FUSE, localhost-only ports
- Lifecycle : Foreground
smbdas PID 1, manual SSHFS mounting
The implementation prioritizes simplicity over optimization - all configuration is static except the remote mount target. This design allows the container to work without environment variables, config mounts, or complex orchestration.
For detailed analysis of each Dockerfile instruction, see Dockerfile Breakdown. For internal directory structure details, see Filesystem Layout. For user and permission specifics, see User and Permissions. For service startup details, see Service Lifecycle.
Sources: Dockerfile:1-34 README.md:1-90