I am running the PHP internal web server inside a Docker container based on Alpine 3.8.
This serves a simple page, which is:
<!DOCTYPE html>
<html>
<head>
<title>Test page</title>
</head>
<body>
<div>
This is a 'hello world' for my CD container.
</div>
<p>
Version: <?php echo getenv('CD_DEMO_VERSION') ?>
</p>
<p>
GUID: <?php echo file_get_contents(__DIR__ . '/guid.txt') ?>
</p>
</body>
</html>
I have this in a CircleCI build process, and a PHPUnit reads the HTML using simplexml_load_string()
in order to check it is working. Most of the time it is fine, but occasionally it is adding control-character cruft either to the start or the end of the HTML, causing the HTML parsing to fail. I would say this happens 10% of the time, so it is hard to replicate. It does not seem to happen locally.
In this build process I am waiting for the web server to start up, so I don't think there is a race-condition happening here.
If the cruft occurs at the start, it looks like this (my output swaps carriage returns to the ⏎
symbol, this is not seen by the XML processor):
^@^@<html>⏎ <head>⏎ <title>Test page</title>⏎ </head>⏎ <body>⏎ <div>⏎ This is a 'hello world' for my CD container.⏎ </div>⏎ <p>⏎ Version: </p>⏎ <p>⏎ GUID: 47294362a6154e9a5397a9f9b72cefe1d349ec2e31de12e6084746a084e4e4ef </p>⏎ </body>⏎</html>
If the cruft appears at the end, it looks like this:
<!DOCTYPE html>⏎<html>⏎ <head>⏎ <title>Test page</title>⏎ </head>⏎ <body>⏎ <div>⏎ This is a 'hello world' for my CD container.⏎ </div>⏎ <p>⏎ Version: </p>⏎ <p>⏎ GUID: a721f44d05e93debb593eef135fc664fb6b0d3aa6a04d50af7f17339d0d75399 </p>⏎ </body>⏎</html>⏎^@^@
I don't know if these are actual circumflexes and at symbols, or whether this is just how the random stuff is rendered to my screen.
It looks like the web server is serving a UTF-8 character set header.
I think my PHPUnit test is relevant, so I will add it here. Due to a way in which CircleCI works, I cannot publish a Docker port on the outside of a container, so I am using docker exec
to do an HTTP operation from the inside:
public function testApp()
{
// Get the page and convert it to an XML object
$html = $this->getWebPage();
// CI is giving me some parsing issues, so let's see it
echo str_replace("
", "⏎", $html);
$doc = simplexml_load_string($html);
$message = trim((string) $doc->body->div);
$this->assertEquals(
"This is a 'hello world' for my CD container.",
$message
);
}
protected function getWebPage()
{
$output = $return = null;
$command = sprintf(
'docker exec -ti %s php -r "echo file_get_contents(\'http://localhost\');"',
escapeshellarg($this->getRepoName())
);
exec($command, $output, $return);
// Check return value first
if ($return)
{
throw new RuntimeException(
sprintf(
'Returned a failure exit code %d on Docker operation',
$return
)
);
}
$imploded = implode(PHP_EOL, $output);
return $imploded;
}
Update
I have updated to Apache 2.4.x inside Alpine 3.8, and to my great surprise, I get exactly the same problem. So, it turns out not to be the PHP web server.
I have also tried Alpine 3.7, same result again. I tried Ubuntu 18.10, same again.
I have tried php -r
with file_get_contents()
and wget
as HTTP devices inside the container.
I am now minded to think that capturing stdout from docker exec
is at fault. I assume that if I set up my tests in another image and run the containers with Docker Compose, it will probably work. Or, I could use docker exec
, write to a container file, and then fish the file out with docker cp
.
It'd still be fascinating to know what is going wrong, though.