How to expose audio from Docker container to a Mac? - macos

I know it's possible by using pulse audio on a Linux host system But paprefs is built for linux not mac.

The Docker-for-Mac VM doesn't have any sound passthrough device, so there isn't anything that you could take advantage of from that angle. By contrast, a virtualbox or vmware fusion VM does have the ability to do passthrough audio.
I was able to get pulseaudio installed and working on OSX with the following command:
brew install pulseaudio
I was able to verify this worked by running the following, hearing sound come out of my speakers:
paplay cockatiel.wav
My next step is to find an image that has a copy of paplay. I found jess/pulseaudio, which appears to be intended to be a pulseaudio server, but I should be able to use it as a client as well.
I found the following guide on the Archlinux Wiki discussing setting up pulseaudio network sound: https://wiki.archlinux.org/index.php/PulseAudio/Examples#PulseAudio_over_network
I was able to adapt it to this situation by doing the following. I edited /usr/local/Cellar/pulseaudio/9.0/etc/pulse/default.pa on my mac, and uncommented the following two lines:
load-module module-esound-protocol-tcp
load-module module-native-protocol-tcp
I reran paplay cockatiel.wav on my mac to make sure my changes still worked. the pulseaudio daemon seems to start on demand, and passes its complaints back to paplay to be printed on my screen if I made a typo. I still have sound with those changes to default.pa, so I'm satisfied that my changes didn't break anything.
Next, I ran the pulseaudio client in a container like this:
docker run --rm -v $HOME:$HOME -w $HOME -it \
-e PULSE_SERVER=192.168.10.23 \
-e HOME=$HOME --entrypoint paplay \
jess/pulseaudio $HOME/cockatiel.wav
What this does is run a container with my local home directory as a volume. This serves two purposes. The first is the fact that my cockatiel.wav is located inside $HOME. The second is because both the client and the server need to have a copy of the same ~/.config/pulse/cookie file (per that archlinux wiki guide).
The PULSE_SERVER environment variable is the en0 IP address of my OSX host, so paplay knows what to connect to.
The HOME environment variable is necessary so paplay can find the same ~/.config/pulse/cookie file.
I was able to play sound from a container running on my docker-for-mac via pulseaudio.
As long as you get the ~/.config/pulse/cookie file to appear in the correct location, you should be able to play sound. You don't have to use a host volume to accomplish this-- you could also do a 'docker cp', or even COPY it into an image.

Install PulseAudio on the Mac:
brew install pulseaudio
Run the daemon:
pulseaudio --load=module-native-protocol-tcp --exit-idle-time=-1 --daemon
In your Docker container:
Install PulseAudio, e.g., apt-get install pulseaudio.
set the following environment variable: ENV PULSE_SERVER=docker.for.mac.localhost
When you run it, share your ~/.config/pulse directory with the container for authentication.
You can run a test to see if it's working like this:
docker run -it -e PULSE_SERVER=docker.for.mac.localhost -v ~/.config/pulse:/home/pulseaudio/.config/pulse --entrypoint speaker-test --rm jess/pulseaudio -c 2 -l 1 -t wav

Related

Acces Windows COM port from docker(linux container)

I need to have acces to windows com port(COM3) form docker linux contianer:
I tried like this:
docker run -d --name test_com_port -p 8090:80 --device=/dev/ttyACM14 --restart always test_com_port
docker run -d --name test_com_port -p 8090:80 –-device=COM3:/dev/ttyS2
--restart always test_com_port
docker run -d --name test_com_port -p 8090:80 –-device=//./COM3:/dev/ttyS2
--restart always test_com_port
but don't have any results. Also I visited microsoft tutorial but it is only for windows containers. Maybe some one have any solutions how to solve it?
hey there I was successfully able to map a windows serial device to a docker container, it was a long and tedious task but in the end I was successful. Any who has access to windows 10 with support for WSL 2 can follow these steps:
1.) Install WSL 2 with Ubuntu distro as it's easier to work with.
2.) On the windows host machine install this software called usbipd through command winget install usbipd for more information use this link
3.)Now we have to configure a few things in the Ubuntu distro so that the interfacing happens for that you will have to follow this link
4.)Once that is done you can now mount the device, before we start the mounting process make sure to plug-in the device to the windows host
5.)Before mounting you can check the list of available devices with usbipd wsl list. You will be able to see all the serial devices connected and now you can
interface or mount or attach using the command usbipd wsl attach --busid=<BUSID>
6.)Once the device is attached you can open the wsl Ububtu use the command lsusb to check all available serial devices which communicate over USB.
7.)Now the final step is to mount the device to docker container with command --device /dev/<available port>; ex doecker run -d --device=/dev/<available ports from liunx ubuntu distro> <container>

Playing sound in Docker container on WSL in Windows 11

Newer versions of Windows (build 21364 or later) enable GUI support in WSL2, including full audio support. This is pretty amazing.
Given that WSL2 now supports audio, how do we then get audio to work inside a Docker container running on Windows, using Docker's WSL2 engine?
On a Linux host, you can simply invoke a Docker image with e.g --device /dev/snd.
What is the equivalent command to run a sound-enabled Docker image from the Windows command line?
There is no /dev/snd or direct audio hardware emulation available in WSL, even in the new Windows 11 setup. Instead, the newest release of WSL achieves audio output by pointing PulseAudio clients to an external PulseAudio server via a socket in /mnt/wslg/. This server runs on yet another Linux distro calleed WSLg that runs inside Windows for the sole purpose of plumbing audio and graphical data between your WSL distro and Windows.
It looks a bit like this:
Docker container <-> WSL <-> WSLg <-> Windows 11
The actual PulseAudio server is located in WSLg. The location of the socket is stored in the environment variable PULSE_SERVER:
# On WSL
echo $PULSE_SERVER
/mnt/wslg/PulseServer
So, aside from making sure your Dockerfile has a basic PulseAudio installation (RUN apt-get install -y pulseaudio or equivalent), all you need to do is invoke the image like:
In WSL:
docker run -t -i -e "PULSE_SERVER=${PULSE_SERVER}" -v /mnt/wslg/:/mnt/wslg/ image_name
Or from the Windows command line like:
wsl docker run -t -i -e "PULSE_SERVER=/mnt/wslg/PulseServer" -v /mnt/wslg/:/mnt/wslg/ image_name
Or
docker run -t -i -e "PULSE_SERVER=/mnt/wslg/PulseServer" -v \\wsl$\Ubuntu\mnt\wslg:/mnt/wslg/ image_name

Disallow egress from Docker containers on Docker for Mac

I want to disable all outgoing connections that are initiated by docker containers to the outside world. I can do this in linux by adding a rule to the FORWARD chain in linux. How do I do this in Docker for Mac?
I found out that Docker for Mac uses an xhyve vm and that’s where docker0 interface lives. What interface in the host does this connect to? I used nettop on Mac and I see that Docker uses my en0 wireless interface. But, I’m not sure if Docker and xhyve are using the same interface.
Edit: Added docker-for-windows tag because they might have similar solutions (Hoping)
Edit 2: Docker for Mac has changed so the accepted solution changed a bit
Docker
$ docker run --net=host --privileged -ti alpine sh
# apk update && apk add iptables
# iptables -vnL
This and the rules could be turned into a Dockerfile and run with a -- restart option. I think on-failure might work to reapply the rules when Docker for Mac starts up.
Virtual Machine
To get to the linux VM:
mac$ brew install screen
mac$ screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
Since the move to linuxkit, this is not your average linux host, everything's a container:
linuxkit:~# ctr -n services.linuxkit tasks ls
TASK PID STATUS
acpid 925 RUNNING
diagnose 967 RUNNING
host-timesync-daemon 1116 RUNNING
ntpd 1248 RUNNING
vpnkit-forwarder 1350 RUNNING
docker-ce 1011 RUNNING
kubelet 1198 RUNNING
trim-after-delete 1303 RUNNING
vsudd 1398 RUNNING
Use runc to move into the docker-ce (or docker) namespace
linuxkit:~# runc --root /run/containerd/runc/default exec -t docker-ce /bin/sh
docker-ce # iptables -vnL
Note that rules will disappear after a restart of Docker for Mac. I haven't found the secret sauce for persisting system changes yet.
Use ctrl-a then d to exit the screen session otherwise you will bork the terminal.
OSX
For the easy but € option, use Little Snitch and block outbound connections on OSX from com.docker.supervisor via vpnkit.
Try Mac's pfctl command, it's kind of equivalent to iptables.
Here's man page: https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man8/pfctl.8.html

Running MPD server with Mopidy docker container, how do I play on Mac?

I'm running the Docker container stilllman/mopidy. I can access the Mopidy UI at http://localhost:6680 and can also control the music that is playing after installing mpc with homebrew. However, I cannot figure out how to hear the music that is playing. The container acknowledges the new MPD connection when I try to use the mpc command on my local mac terminal. I reach the same situation with Theremin (can control music but not hear).
I was successful by installing pulseaudio via homebrew on my Mac host and connecting my Docker container to it:
docker run -it -e PULSE_SERVER=docker.for.mac.localhost \
-v ~/.config/pulse:/home/pulseaudio/.config/pulse \
--entrypoint speaker-test \
--rm jess/pulseaudio -c 2 -l 1 -t wav
You could build a similar container running Mopidy and change output to pulse server output (should be in the documentation how to do it).
An alternative solution to using the brittle audio routing through Pulseaudio would be to use the Icecast output of Mopidy: https://docs.mopidy.com/en/latest/audio/#streaming-through-icecast
Once you setup the Icecast stream, on your host, you could use a browser or MPV to play the stream generated by Icecast.

Keyboard/Mouse are unresponsable when running x-org in a docker container

I want to create a docker image for a GUI application (e.g. Chrome) and I hope this GUI app could run at a bare Linux server without X server installed.
I know it is very easy to create and run a docker image just for X Window Client (The GUI application itself). This needs X server be installed and run at host.
sudo docker run -ti -v /tmp/.X11-unix:/tmp/.X11-unix xorg xterm -display :0
But for me, I need both X client and server run in docker container.
Here's my dockerfile:
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y xorg
And I run the image by command:
sudo docker run -i -t --rm -e DISPLAY=:0 --privileged xorg xinit
The X server could be started and my screen turns black, after a few seconds, the xterm window displays. BUT, I can't use keyboard and mouse. The screen seems like freezen
I have searched and tried many solutions but no one could fix this problem. (the virtual x-server is not I needed)
I have resolved this problem.
At first, I thought maybe x server in docker container cannot access host devices, and I spent much time on LXC/cgroup. For example, I changed the docker exec engine to LXC, and I added option '--lxc-conf='lxc.cgroup.devices.allow = c 13:* rwm', and I also created /dev/input/* in container.
All of these operations are unnecessary.
If we run docker container in privileged mode, all host devices will be added automatically. Or we can use options like '--device=/dev/input/mice' to share host device.
The real problem is that x server could not discovery and add device automatically. I don't know why. But we could modify x server's configuration and customize the device.
add file /etc/X11/xorg.conf.d/10-input.conf
Section "ServerFlags"
Option "AutoAddDevices" "False"
EndSection
Section "ServerLayout"
Identifier "Desktop"
InputDevice "Mouse0" "CorePointer"
InputDevice "Keyboard0" "CoreKeyboard"
EndSection
Section "InputDevice"
Identifier "Keyboard0"
Driver "kbd"
Option "Device" "/dev/input/event2"
EndSection
Section "InputDevice"
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/input/mice"
Option "ZAxisMapping" "4 5 6 7"
EndSection
and run docker container:
docker run -i -t -v /tmp/.X11-unix:/tmp/.X11-unix --rm --privileged ubuntu startx
At first make sure that proper input modules are installed:
RUN DEBIAN_FRONTEND='noninteractive' apt-get install -y --no-install-recommends xserver-xorg-input-evdev xserver-xorg-input-all
In modern Linux udev is responsible for managing device nodes (including USB keyboards) in the /dev tree. It uses /run/udev/data which isn't available inside your container even with -privileged option.
So you need to mount that folder explicitly using -v /run/udev/data:/run/udev/data like this:
docker run -i -t -v /tmp/.X11-unix:/tmp/.X11-unix --rm --privileged -v /run/udev/data:/run/udev/data ubuntu startx

Resources