When using PHP inside a Docker container on Windows (e.g. using DDEV), symbolic links that are created inside the container (e.g. by composer) do not seem to work correctly with PHP's file streams.
Scenario
Imagine the following PHP code
<?php
mkdir('demo-base-directory');
symlink('demo-base-directory', 'demo-symbolic-link');
var_dump(glob('demo-*', GLOB_ONLYDIR));
If executed inside the container, it outputs only demo-base-directory, however demo-symbolic-link is missing (the very same example works as expected on Linux/Unix systems inside Docker containers)
array(1) {
  [0]=>
  string(19) "demo-base-directory"
}
When viewing the symbolic link in the host system (e.g. using cat demo-symbolic-link in Windows PowerShell) it shows
XSym
0019
0df68e8650ddca993c28277a5cfa3dcd
demo-base-directory
There have been other reports to Docker for Windows about symlink emulation - I could not reproduce this behavior for files using fgets or file_get_contents but for the mentioned glob invocation, see
Shared volumes are mounted in a Linux-based Docker container on a Windows host system as Samba/CIFS mount like this:
//10.0.75.1/C on /var/www/html type cifs (rw,relatime,vers=3.02,sec=ntlmsspi,cache=strict,username=olly,domain=OLIVERHADERB9D8,uid=0,noforceuid,gid=0,noforcegid,addr=10.0.75.1,file_mode=0755,dir_mode=0777,iocharset=utf8,nounix,serverino,mapposix,nobrl,mfsymlinks,noperm,rsize=1048576,wsize=1048576,echo_interval=60,actimeo=1)
Mount option mfsymlinks refers to Minshall+French symlinks
Workaround
Instead of creating symbolic links inside the container, creating them outside (directly in Windows) solves the problem.
Using plain mklink in cmd.exe
del demo-symbolic-link
mklink /d demo-symbolic-link demo-base-directory
output
symbolic link created for demo-symbolic-link <<===>> demo-base-directory
Using plain mklink via cmd in PowerShell
del demo-symbolic-link
cmd /c mklink /d demo-symbolic-link demo-base-directory
output
symbolic link created for demo-symbolic-link <<===>> demo-base-directory
side note: New-Item -ItemType SymbolicLink could not be resolved using glob(..., GLOB_ONLYDIR in PHP - using mklink /d here as well 
Using Git-Bash for Windows
I had to execute the following while executing Git-Bash as administrator. Setting the environment variable with export is important here - see Enable native NTFS symbolic links for Cygwin
rm demo-symbolic-link
export MSYS=winsymlinks:nativestrict
ln -s demo-base-directory/ demo-symbolic-link
Helper tools
I've created helper tool examples that search for Samba XSym pointers in a particular directory (TYPO3 related, public/typo3conf/ext/) and "upgrade" the XSym pointers to proper symlinks - probably admin privileges are required when executing those scripts:
Results
Executing the PHP example from above again now outputs both expected items
array(2) {
  [0]=>
  string(19) "demo-base-directory"
  [1]=>
  string(18) "demo-symbolic-link"
}
Question
Working inside a Docker container and having to adjust symbolic links manually on the host system is really just a workaround - not a solution. At which level could this be enhanced and optimized in order to create proper symbolic links using the Docker container only?
It seems this could be resolved at different layers:
- PHP's globinvocation (especially for flakyGLOB_ONLYDIRflag)
- glibc's globimplementation (especially for Minshall+French symlinksXSym)
- Docker not using Samba/CIFS for volume sharing
Updates
- switched from mklink /j(junction) tomklink /d(symlinked directory) since removing the linked junction removed it's origin as well
- PowerShell's symlink cmdlet New-Item -ItemType SymbolicLink(instead of previousNew-Item -ItemType Junction) then again could not be resolved usingglob(..., GLOB_ONLYDIRin PHP - as a result, usingcmd /c mklink /dhere
- added Samba/CIFS mount information
 
    