Docker has the capabilities to create virtual machines, however the majority of it's use case right now is to host ephemeral containers, meaning they live short and aren't persistent. To make a Docker container behave more like a VM, it needs to have the following qualities:
- User Interface. For a lot of users, a default bash shell is not enough and a TUI or GUI is needed.
- Persistence. When you shut down and restart the VM, it should remember your file system structure.
A simple solution to this problem is to install an X server.
- Install the latest version of XQuartz
- Or use brew:
brew install --cask xquartz
- Or use brew:
- Launch XQuartz and in the menu, choose
XQuartz
->Preferences
->Security
- Check the box for
Allow connections from network clients
and restart XQuartz - In your macOS terminal, type
xhost + 127.0.0.1
- Install the latest version of VcXsrv
- Or use choco:
choco install vcxsrv
- Or use choco:
- Launch VcXsrv to start the setup
- Use all default settings, checking
✅ Disable access control
(wip)
This Dockerfile will run xterm
which is a simple GUI terminal.
FROM ubuntu:latest
RUN apt-get update && apt-get install -y xterm
CMD xterm
And now we can run our container, setting the DISPLAY
environment variable to host.docker.internal:0
.
$ docker build -t vm .
$ docker run -e DISPLAY=host.docker.internal:0 vm
Since there is no way to mount the entire /
filesystem to volume in Docker, we have to hand-select our persistent directories. Using the manpage for file-heirarchy
we can get a good idea of what needs to happen in our docker-compose.yml
:
version: "3.8"
services:
virtualmachine:
build: .
environment:
- "DISPLAY=host.docker.internal:0"
volumes:
- "./bin:/bin"
- "./etc:/etc"
- "./home:/home"
- "./lib:/lib"
- "./opt:/opt"
- "./usr:/usr"
- "./var:/var"