Я пытаюсь запустить Xvfb в контейнере Docker, но он не работает с ошибкой:
$ Xvfb :0 -nolisten tcp -screen 0 1024x768x24
_XSERVTransSocketUNIXCreateListener: ...SocketCreateListener() failed
_XSERVTransMakeAllCOTSServerListeners: server already running
(EE)
Fatal server error:
(EE) Cannot establish any listening sockets - Make sure an X server isn't already running(EE)
Согласно strace, он пытается связать сокет UNIX по адресу /tmp/.X11-unix/X0:
bind(4, {sa_family=AF_UNIX, sun_path=@"/tmp/.X11-unix/X0"}, 20) = -1 EADDRINUSE (Address already in use)
Однако файл еще не существует в контейнере (проверено ls -l /tmp/.X11-unix).
Если я использую другой номер экрана, например :1, программа завершается успешно.
Этот контейнер работает в режиме --network host, и /tmp/.X11-unix/X0 существует на хосте. Создает ли это какую-то проблему, когда контейнер и хост не могут иметь сокет UNIX по одному и тому же пути, даже если этот сокет не виден в контейнере?


Это захватывающая ошибка! Вы столкнулись с конфликтом имен в абстрактном пространстве имен сокета домена UNIX. Сокеты домена UNIX в Linux могут быть созданы в двух местах: во-первых, в обычной VFS, которую можно проверить с помощью ls; другое - это «абстрактное пространство имен», где имена сокетов начинаются с '\0' (да, буквальный нулевой байт) и очищаются, когда программа, создающая сокет, завершает работу.
Теперь ваш вызов strace показывает, что он пытается прослушивать имя сокета в абстрактном пространстве имен, показывая значение поля sun_path, начинающееся с @. Это не совсем понятно, но так оно и есть...
Вот как он показывает «обычный» сокет с поддержкой VFS:
:; strace -e bind socat UNIX-LISTEN:/tmp/asf-testing-hi STDOUT
bind(5, {sa_family=AF_UNIX, sun_path = "/tmp/asf-testing-hi"}, 21) = 0
А вот сокет в абстрактном пространстве имен:
:; strace -e bind socat ABSTRACT-LISTEN:/tmp/asf-testing-hi STDOUT
bind(5, {sa_family=AF_UNIX, sun_path=@"/tmp/asf-testing-hi"}, 22) = 0
Ну вот и знак @.
Возвращаясь к исходной проблеме, похоже, что абстрактные пространства имен сокетов домена unix ограничены сетевым пространством имен , что означает, что использование режима «хост» гарантированно приведет к конфликтам. Что вам, вероятно, нужно сделать, так это настроить отдельное сетевое пространство имен для этого контейнера и создать мост для каждого сетевого интерфейса на хосте, который вы хотите, чтобы контейнер был доступен. Я считаю, что у https://stackunderflow.dev/p/network-namespaces-and-docker/ может быть достойный учебник по тому, как сделать это вручную. Надеюсь это поможет!