Overlaying a file in a Docker container allows you to replace a file inside the container with your own custom version. This is useful when you need to customize configuration files, such as settings.yml, without modifying the Docker image itself.

Overview

File overlaying uses Docker bind mounts to replace files in the container with files from your host system. This technique is particularly useful for:

  • Custom configuration files - Override default settings.yml with your own settings
  • Custom themes - Replace theme files or assets
  • Custom scripts - Override application scripts with custom versions
  • Testing configurations - Test different configurations without rebuilding images

Important: When you overlay a file, the host file completely replaces the container file. Changes to the host file are immediately reflected in the container (and vice versa). The original container file is no longer accessible.

Common Use Case: Overlaying settings.yml

The most common use case is overlaying the settings.yml configuration file to customize Password Pusher settings.

Download Default Configuration

Before creating your custom configuration, download the default settings.yml file:

Download settings.yml

Modify it to your needs, then mount it into the container.

File Location in Container

Inside the Password Pusher Docker container:

  • Configuration file: /opt/PasswordPusher/config/settings.yml
  • Application root: /opt/PasswordPusher/

Using Docker Compose (Recommended)

If you’re using docker-compose.yml, add a bind mount to the volumes section:

services:
  pwpush:
    image: docker.io/pglombardo/pwpush:stable
    volumes:
      # Overlay settings.yml with custom configuration
      - type: bind
        source: /path/to/your/settings.yml
        target: /opt/PasswordPusher/config/settings.yml
      # Other volumes (database, storage, etc.)
      - pwpush-storage:/opt/PasswordPusher/storage
    ports:
      - "80:80"
      - "443:443"

Using relative paths:

If your settings.yml is in the same directory as docker-compose.yml:

services:
  pwpush:
    image: docker.io/pglombardo/pwpush:stable
    volumes:
      - type: bind
        source: ./settings.yml
        target: /opt/PasswordPusher/config/settings.yml
        read_only: true  # Optional: prevent container from modifying the file

Note: The read_only: true option prevents the container from modifying the file, which is recommended for configuration files.

Using Docker Run

If you’re using docker run directly, use the --mount option:

docker run -d \
  --name pwpush \
  --mount type=bind,source=/path/to/your/settings.yml,target=/opt/PasswordPusher/config/settings.yml,readonly \
  -p "80:80" \
  -p "443:443" \
  -v pwpush-storage:/opt/PasswordPusher/storage \
  pglombardo/pwpush:stable

Command Breakdown

  • docker run -d: Runs the container in detached mode (background)
  • --mount type=bind,source=...,target=...,readonly: Creates a bind mount
    • type=bind: Specifies a bind mount (host file/directory)
    • source=/path/to/your/settings.yml: Path to your file on the host
    • target=/opt/PasswordPusher/config/settings.yml: Path inside the container
    • readonly: Optional - prevents container from modifying the file
  • -p "80:80" -p "443:443": Maps container ports to host ports
  • pglombardo/pwpush:stable: The Docker image to use

How It Works

When you use a bind mount to overlay a file:

  1. File Replacement: The host file completely replaces the container file at the target path
  2. Bidirectional Sync: Changes to the host file are immediately visible in the container
  3. Persistence: The overlay persists across container restarts (as long as the host file exists)
  4. Original File: The original container file is no longer accessible

Example Flow:

Host: /home/user/custom-settings.yml
         ↓ (bind mount)
Container: /opt/PasswordPusher/config/settings.yml

Any changes to /home/user/custom-settings.yml on the host are immediately reflected in the container at /opt/PasswordPusher/config/settings.yml.

Other Files You Can Overlay

While settings.yml is the most common, you can overlay other files as well:

Custom Themes

volumes:
  - type: bind
    source: ./custom-theme.css
    target: /opt/PasswordPusher/app/assets/stylesheets/custom.css

Custom Scripts

volumes:
  - type: bind
    source: ./custom-script.sh
    target: /opt/PasswordPusher/bin/custom-script.sh

Custom Locale Files

volumes:
  - type: bind
    source: ./config/locales/custom.yml
    target: /opt/PasswordPusher/config/locales/custom.yml

Warning: Overlaying application code files may break functionality or cause issues during upgrades. Only overlay files you understand and have tested.

Best Practices

File Paths

  • Use absolute paths for clarity and reliability
  • Use relative paths (relative to docker-compose.yml) for portability
  • Verify paths exist before starting the container

File Permissions

  • Ensure the host file has appropriate read permissions
  • Use read_only: true for configuration files to prevent accidental modifications
  • Check that the container user can read the file

Version Control

  • Keep your custom configuration files in version control (Git)
  • Document why you’re overlaying specific files
  • Test changes in a development environment first

Configuration Priority

Remember: Environment variables always take precedence over settings.yml. If you set both, environment variables will override the YAML file values.

For more information, see Configuration Strategies.

Backup Original Files

Before overlaying, you may want to extract the original file from the container:

# Extract original settings.yml
docker create --name temp-container pglombardo/pwpush:stable
docker cp temp-container:/opt/PasswordPusher/config/settings.yml ./original-settings.yml
docker rm temp-container

Troubleshooting

File Not Found

Symptoms: Container fails to start or file doesn’t appear in container.

Solutions:

  1. Verify source path exists:
    ls -la /path/to/your/settings.yml
    
  2. Check path is absolute (for Docker Run):
    # Use absolute path
    docker run ... --mount type=bind,source=$(pwd)/settings.yml,...
    
  3. Verify file permissions:
    chmod 644 /path/to/your/settings.yml
    

Container Won’t Start

Symptoms: Container exits immediately after starting.

Solutions:

  1. Check container logs:
    docker compose logs pwpush
    # or
    docker logs <container_id>
    
  2. Verify YAML syntax (for settings.yml):
    # Test YAML syntax
    python3 -c "import yaml; yaml.safe_load(open('settings.yml'))"
    
  3. Check file encoding: Ensure the file uses UTF-8 encoding

Changes Not Reflecting

Symptoms: Changes to host file don’t appear in container.

Solutions:

  1. Restart the container:
    docker compose restart pwpush
    
  2. Check mount is active:
    docker compose exec pwpush ls -la /opt/PasswordPusher/config/settings.yml
    
  3. Verify file is actually mounted:
    docker compose exec pwpush cat /opt/PasswordPusher/config/settings.yml | head -5
    

Permission Denied

Symptoms: Container can’t read the overlaid file.

Solutions:

  1. Check file permissions:
    ls -la /path/to/your/settings.yml
    
  2. Make file readable:
    chmod 644 /path/to/your/settings.yml
    
  3. Check SELinux/AppArmor (if applicable):
    # For SELinux
    chcon -Rt svirt_sandbox_file_t /path/to/your/settings.yml
    

Complete Example

Here’s a complete docker-compose.yml example with a custom settings.yml overlay:

services:
  pwpush:
    image: docker.io/pglombardo/pwpush:stable
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      # Overlay custom settings.yml
      - type: bind
        source: ./config/settings.yml
        target: /opt/PasswordPusher/config/settings.yml
        read_only: true
      # Persistent storage
      - pwpush-storage:/opt/PasswordPusher/storage
    environment:
      PWPUSH_MASTER_KEY: 'your-encryption-key-here'
      TLS_DOMAIN: 'pwpush.example.com'

volumes:
  pwpush-storage:

Directory structure:

.
├── docker-compose.yml
├── config/
│   └── settings.yml  (your custom configuration)
└── ...

See Also

Updated: