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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions