vind
, the name comes from VM IN Docker, is a tool to create and manage a cluster of containers that look and work like virtual machines, on Docker (and Podman).
The container, or called Machine in vind
, runs systemd
as PID 1 and a SSH daemon that can be used to log into.
Such VM-like container behaves very much like a "normal" VM, it's even possible to run dockerd
in it.
Note:
vind
is a rebuild on top of weaveworks' footloose, which was archived in year 2023. Kudos to the original developers!
vind
binaries can be downloaded from this repo's release page.
On ARM chip:
curl -Lo vind.tar.gz https://github.com/brightzheng100/vind/releases/download/v0.1.1/vind_0.1.1_darwin_arm64.tar.gz
tar -xvf vind.tar.gz && chmod +x vind
sudo mv vind /usr/local/bin/
On Intel chip:
curl -Lo vind.tar.gz https://github.com/brightzheng100/vind/releases/download/v0.1.1/vind_0.1.1_darwin_amd64.tar.gz
tar -xvf vind.tar.gz && chmod +x vind
sudo mv vind /usr/local/bin/
curl -Lo vind.tar.gz https://github.com/brightzheng100/vind/releases/download/v0.1.1/vind_0.1.1_linux_amd64.tar.gz
tar -xvf vind.tar.gz && chmod +x vind
sudo mv vind /usr/local/bin/
There are some simple concepts in vind
:
Machine
: A Machine is a VM-like container that is created by the configuredMachineSet
's specification.MachineSet
: A MachineSet is a set of Machines that share the same configuration specification. One MachineSet can have 1 or more replicas, each of which represents a Machine. Each Machine in the MachineSet has its own index, starting from 0.Cluster
: Cluster is the top level of objects invind
. A Cluster is a group of MachineSet(s), which has a unique name and authentication SSH key pair for the underlying Machines. The SSH key pair can be generated automatically if not exists, or you can generate it and assign to the cluster through the configuration YAML file.
There is a need to refer to the config file for vind
actions, which is in YAML format.
There is a lookup sequence while looking for such a configuration:
- Explicitly specified by
--config
or-c
parameter while running the command. - Explicitly exported system variable namely
VIND_CONFIG
. For example,export VIND_CONFIG=/path/to/file.yaml
parameter while running the command. - Current folder's
vind.yaml
, if any.
$ vind -h
A tool to create containers that look and work like virtual machines, on Docker.
Usage:
vind [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
config Manage cluster configuration
cp Copy files or folders between a machine and the host file system
create Create a cluster
delete Delete a cluster
help Help about any command
show Show all running machines or some specific machine(s) by the given machine name(s).
ssh SSH into a machine
start Start all cluster machines or specific machine(s) by given name(s)
stop stop all cluster machines or specific machine(s) by given name(s)
version Print vind version
Flags:
-c, --config string Cluster configuration file
-h, --help help for vind
Use "vind [command] --help" for more information about a command
vind
reads a description of the Cluster
to create and manage its Machines
from a YAML file, vind.yaml
by default.
An alternate name can be specified on the command line with the --config
or -c
option, or through the VIND_CONFIG
environment variable.
The config
command helps with creating the initial config file:
$ vind config create --replicas 3
INFO[0000] Creating config file vind.yaml
$ cat vind.yaml
cluster:
name: cluster
privateKey: cluster-key
machineSets:
- name: test
replicas: 3
spec:
backend: docker
image: brightzheng100/vind-ubuntu:22.04
name: node%d
portMappings:
- containerPort: 22
You may try vind config create -h
to see what can be configured through the command, or simply update the YAML file manually if you want to further customize it.
Create the vind
cluster:
$ vind create
INFO[0000] Pulling image: brightzheng100/vind-ubuntu:22.04 ...
INFO[0005] Creating machine: cluster-test-node0 ...
INFO[0005] Starting machine test-node0...
INFO[0006] Creating machine: cluster-test-node1 ...
INFO[0006] Starting machine test-node1...
INFO[0006] Creating machine: cluster-test-node2 ...
INFO[0006] Starting machine test-node2...
At first time, it may take 1 minute or so to pull the Docker image and then create the machines. The creation of the machines typically takes just a few seconds.
Note: since we've created the
vind.yaml
byvind config create --replicas 3
in above step, we need not to specify it in this step's command. The same applies to the rest of commands.
You may use show
command to display the cluster details.
$ vind show
Output:
CONTAINER NAME MACHINE NAME PORTS IP IMAGE CMD STATE BACKEND
cluster-test-node0 test-node0 35827->22 10.88.0.21 brightzheng100/vind-ubuntu:22.04 /sbin/init Running docker
cluster-test-node1 test-node1 34929->22 10.88.0.22 brightzheng100/vind-ubuntu:22.04 /sbin/init Running docker
cluster-test-node2 test-node2 34237->22 10.88.0.23 brightzheng100/vind-ubuntu:22.04 /sbin/init Running docker
Actually there are just some Docker containers.
Here, let's understand a bit on the naming, by given cluster-test-node0
in our case: {CLUSTER_NAME}-{MACHINE_SET}-{MACHINE WITH INDEX}.
cluster
is really the Cluster name, which can be any sensible name specified in YAML file'scluster.name
.test
is the MachineSet's name.node{n}
is the Machine's name with index. Typically, we need to specify the machine with a desired index pattern, likenode%d
, ornode-%d
.
SSH into a machine with vind ssh [USER@]<MACHINE_NAME>
, which is the combination of MachineSet's name and Machine's name.
$ vind ssh test-node0
root@test-node0:~# ps fx
PID TTY STAT TIME COMMAND
1 ? Ss 0:00 /sbin/init
15 ? Ss 0:00 /lib/systemd/systemd-journald
30 ? Ss 0:00 /lib/systemd/systemd-logind
32 ? Ss 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
63 ? Ss 0:00 \_ sshd: root@pts/1
81 pts/1 Ss 0:00 \_ -bash
87 pts/1 R+ 0:00 \_ ps fx
66 ? Ss 0:00 /lib/systemd/systemd --user
67 ? S 0:00 \_ (sd-pam)
Note: the machine user name can be other user, instead of
root
, if that's prepared in the Docker image and is specified in the YAML file.
You can stop one, or some specific machines, or all if nothing is specified.
To stop test-node1
:
$ vind stop test-node1
INFO[0000] Stopping machine: cluster-test-node1 ...
Or stop all machines in the cluster -- it will detect whether the machine is in stopped
state:
$ vind stop
INFO[0000] Stopping machine: cluster-test-node0 ...
INFO[0000] Machine cluster-test-node1 is already stopped...
INFO[0000] Stopping machine: cluster-test-node2 ...
You can start one, or some specific machines, or all if nothing is specified.
To start test-node1
:
$ vind start test-node1
INFO[0000] Starting machine: test-node1 ...
Or start all machines in the cluster -- it will detect whether the machine is in started
state:
$ vind start
INFO[0000] Starting machine: test-node0 ...
INFO[0000] Machine test-node1 is already started...
INFO[0000] Starting machine: test-node2 ...
Copying files / folders between the host and machine can be useful.
- Copy a file from the machine to host:
$ vind cp test-node1:/etc/resolv.conf .
$ ls -l resolv.conf
-rw-r--r-- 1 brightzheng staff 43 Jan 7 17:54 resolv.conf
- Copy a file from the host to the machine:
$ vind cp README.md test-node1:/root/
$ vind ssh test-node1
root@test-node1:~# ls -l
total 4
-rw-r--r--. 1 501 dialout 107 Jan 5 05:07 README.md
Once the VM job is done, the machines can be easily deleted too.
$ vind delete
INFO[0000] Machine test-node0 is started, stopping and deleting machine...
INFO[0000] Machine test-node1 is started, stopping and deleting machine...
INFO[0001] Machine test-node2 is started, stopping and deleting machine...
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
I've created a series of Docker images, covering Ubuntu, CentOS, Debian, Fedora, Amazon Linux, by inheriting from original footloose
's legacy with necessary enhancements (e.g. multi-arch build). Each of which will act like the VM by following some industrial practices.
You may refer to images/README.md for what have been prepared and how to customize.
Under the hood, vind
orchestrates the docker
commands while having some logic on top.
Since podman
is docker
compatible, at least in the commands that vind
uses, podman
is also supported.
To make it work, what we need to do is to create a softlink from docker
to podman
.
For example, in my Mac:
$ which podman
/opt/homebrew/bin/podman
$ ln -s `which podman` /usr/local/bin/docker
$ which docker
/usr/local/bin/docker
That's it, and vind
will be working friendly with podman
as it will treat podman
as Docker.
Docker in Docker container is tricky but as promised, it's totally possible in vind
.
What we need to do is to enable privileged: true
like ./demo/docker-in-vind.yaml.
Then you're good to go to install Docker like you do in normal Linux, by following official doc here.
Even vind
offers cp
command to streamline the folders / files sync up between host and machines, it would be great if the host file system is automatically bind mounted into the vind
machines.
This is achievable by defining a special bind mount like this, which simply says that the root file system, which is /
, is bind mounted to vind
machine's /host
:
volumes:
- type: bind
source: /
destination: /host
You may refer to ./demo/ubunt-2.yaml for the usage.
Once you've done so, after vind ssh
, the command will try to automatically redirect to where you're in the current host folder. For example:
$ pwd
/Users/brightzheng/development/go/projects/vind/demo
$ ls
README.md cluster-key cluster-key.pub demo.cast demo.sh ubuntu-1.yaml ubuntu-2.yaml
$ vind create -c ubuntu-2.yaml
$ vind ssh normal-node0 -c ubuntu-2.yaml
INFO[0000] SSH into machine [normal-node0] with user [root]
INFO[0000] Trying to cd into: /host/Users/brightzheng/development/go/projects/vind/demo
root@normal-node0:/host/Users/brightzheng/development/go/projects/vind/demo# ls
README.md cluster-key cluster-key.pub demo.cast demo.sh ubuntu-1.yaml ubuntu-2.yaml
Your issues, PRs, feedback, and whatever makes sense to making vind
better is always welcome!