Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GitHub

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 StageDockerfile LinesActionArtifacts Created
Base ImageDockerfile2Pull ubuntu:latestLinux OS environment
Package InstallDockerfile:5-6apt-get install sshfs sambaSSHFS client, Samba server binaries
User CreationDockerfile9Create sshuser accountNon-root user (UID 1000)
Directory SetupDockerfile:12-15Create /remote and /samba-shareMount points
Config CopyDockerfile18Copy smb.conf to /etc/samba/Samba configuration
PermissionsDockerfile21chmod 777 /samba-shareWorld-writable share
FUSE ConfigDockerfile24Enable user_allow_otherCross-user mount access
Port ExposureDockerfile27EXPOSE 139 445SMB port metadata
Symbolic LinkDockerfile30ln -s /remote /samba-share/remoteIntegration point
Entry PointDockerfile33Set CMD for smbdProcess 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:

CapabilityRequired ForAlternative
Device AccessFUSE /dev/fuse deviceNone - FUSE requires device access
Mount OperationsCreating mount points in container namespaceNone - fundamental to SSHFS
Process ManagementFUSE background processesNone - 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.1 only (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 = sshuser in smb.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:

  1. smbd runs as root but accesses files as sshuser (via force user)
  2. sshfs mounts files owned by UID 1000 (sshuser)
  3. 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.

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 /remote directory 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 (not 0.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"]
FlagPurposeConsequence
--foregroundRun in foreground (don't daemonize)Container stays alive
--no-process-groupDon't create new process groupProper signal handling
--debug-stdoutLog to stdout instead of filesDocker 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:

  1. Base ubuntu:latest layer (~30-80 MB depending on version)
  2. apt-get update metadata layer (~40 MB)
  3. sshfs and samba package layers (~80 MB combined)
  4. User creation layer (minimal)
  5. Directory creation layers (minimal)
  6. Configuration file layers (< 1 MB)
  7. 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 smbd as 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