Skip to content

Ensure reliable /etc/hosts handling for EasyEngine in containerized environments #445

@dinhngocdung

Description

@dinhngocdung

Description:

This change ensures that EasyEngine can reliably handle /etc/hosts entries when deployed in Docker or containerized environments, without affecting functionality on host systems.

Context:

When EasyEngine is run inside a container, its attempt to update the host system's /etc/hosts file via a mounted volume may silently fail due to permission or compatibility issues in the Filesystem()->dumpFile() method.

-> Deploy Easyengine-Docker

/**
 * Removes entry of the site from /etc/hosts
 *
 * @param string $site_url site name.
 *
 */
function remove_etc_hosts_entry( $site_url ) {
	$fs = new Filesystem();

	$hosts_file = file_get_contents( '/etc/hosts' );

	$site_url_escaped = preg_replace( '/\./', '\.', $site_url );
	$hosts_file_new   = preg_replace( "/127\.0\.0\.1\s+$site_url_escaped\n/", '', $hosts_file );

	$fs->dumpFile( '/etc/hosts', $hosts_file_new );
}

Objective:

Not to change existing behavior, but to ensure consistent and reliable operation of the remove_etc_hosts_entry function across environments, especially in container deployments.

Modifications:

Refactored remove_etc_hosts_entry in src/helper/site-utils.php to use PHP's native file I/O operations with added safety and compatibility:

  • Replaced Filesystem()->dumpFile() with file_put_contents() and file_get_contents().
  • Added LOCK_EX to ensure atomic writes.
  • Used stream_context_create with 'file' => ['privileged' => true] to improve write permissions handling in volume-mounted /etc/hosts.
  • Implemented preg_quote() to safely match hostnames.
  • Included explicit error handling for file read/write failures.

Benefits:

  • Container Compatibility: Improves EasyEngine’s robustness when run in Docker or similar environments.
  • Backward-Safe: Function continues to work without modification on traditional (host-level) deployments.
  • Resilience: Adds clear error messages in case of failure, reducing silent breakages.

Testing:

  • Verified successful read/write operations to /etc/hosts in:

    • Docker container with volume-mounted /etc/hosts
    • Host-level execution without container

Updated Function:

/**
 * Removes entry of the site from /etc/hosts
 *
 * @param string $site_url site name.
 *
 */
function remove_etc_hosts_entry($site_url) {
    $hosts_file = @file_get_contents('/etc/hosts');
    if ($hosts_file === false) {
        throw new Exception("Failed to read /etc/hosts");
    }

    $site_url_escaped = preg_quote($site_url, '/');
    $hosts_file_new = preg_replace("/127\.0\.0\.1\s+$site_url_escaped\n/", '', $hosts_file);

    $context = stream_context_create([
        'file' => ['privileged' => true]
    ]);

    $result = file_put_contents('/etc/hosts', $hosts_file_new, LOCK_EX, $context);
    if ($result === false) {
        throw new Exception("Failed to update /etc/hosts");
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions