How to Install a Docker Machine on a MacOS

Docker is a means to run containerized applications on a host to have reliable solutions to deploy it. According to Docker’s “What is a Container” article, “A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another”. Docker itself “uses the Linux kernel and features of the kernel, like Cgroups and namespaces, to segregate processes so they can run independently”. On MacOS, Docker is run using a Linux Virtual Machine and relies on sub-components: HyperKit, VPNKit, and DataKit to support its functionalities. 

The following is a writeup to enable the use of docker-machine as an alternate solution to start a VM with the docker components to get access to CLI.

Setting up Your Environment

To begin, you will need to have both VirtualBox and HomeBrew installed and running. Instructions on installation can be found at Oracle VM VirtualBox and The Missing Package Manager for macOS (or Linux) — Homebrew respectively. Once both are operating, you will need to set up the following Docker components:

brew install docker-machine docker docker-compose

You will then need to use VirtualBox to create a default VM (“default” is the expected name for most docker-machine commands; for simplicity’s sake, we will continue to refer to the VM as such). The VM specs of the below example are 3x CPUs, 8GB of memory, and 40G of disk space, but you may adjust these parameters as needed.

docker-machine create --virtualbox-cpu-count "3" --virtualbox-memory "8192" --virtualbox-disk-size "40000" default

Then, confirm your VM is accessible via docker-machine with:

docker-machine env

If the configuration of this command is successful, then you are ready for the next step. Now, you will want to set your shell up to be able to use the docker CLI. To do so, configure with the following command lines:

eval $(docker-machine env)

export DOCKER_HOST_IP=`echo ${DOCKER_HOST} | cut -d '/' -f 3 | cut -d ':' -f 1`

DOCKER_HOST_IP will contain the IP of the VM, and can be used to set up a “port forward” (socat) later.

Testing

Next, you will want to test the docker CLI to make sure it is working properly. To do this, enter

docker ps -a

then run the hello-world container with

docker run --rm hello-world

Implementing Ports

To test an exposed service (i.e. nginx web server), run:

docker run -it --rm -d -p 8080:80 --name web nginx

This will start the container in demon mode [-d], which allows you to access it from http://DOCKER_HOST_IP:8080 using a web browser.

Now, we will “port forward” - access the host/port of DOCKER_HOST_IP - with the following socat command line:

socat tcp:${DOCKER_HOST_IP}:8080 tcp-l:8080

Alternate Route

Should you wish for more permanent and direct map ports from the VM to your host, you can also save the following script as vbox_port_forward.sh and run it any time after creating your Docker VM:

#!/bin/bash

DM_PORT=$1

re='^[0-9]{2,}$'

if [ -z "$DM_PORT" ]; then

    echo "error: port to map is required" >&2; exit 1

    exit 1

elif ! [[ $DM_PORT =~ $re ]] ; then

   echo "error: port must be a number" >&2; exit 1

Fi

DM_NAME=${2:-"default"}

VBoxManage modifyvm "$DM_NAME" --natpf1 "tcp-port${DM_PORT},tcp,,${DM_PORT},,${DM_PORT}";

VBoxManage modifyvm "$DM_NAME" --natpf1 "udp-port${DM_PORT},udp,,${DM_PORT},,${DM_PORT}";

Running the following would then map port 8080 from default to the localhost. 

vbox_port_forward.sh 80 default

To map a range, just loop over the script. The following example would map ports 8000-9000 on default to the same ports on localhost:

for i in {8000...9000}; do vbox_port_forward.sh $i default; done

To kill the socat “port forward”, enter docker ps -a followed by a docker kill on the first four digits of the CONTAINER ID. The --rm on the docker command line (docker rm) will ensure the socat’s deletion.

Before we begin the next section, please note that the above docker-machine create command runs with the default parameter that allows the sharing of the user’s home directory. That said, keep in mind that docker -v will be limited to what is shared to the VM.

Volume Mounts and Miscellany

Next, we will mount the “path of current working directory” (pwd) as /dmc in the running container and create a file within it. To do so, enter this command line: 

docker run -v `pwd`:/dmc --rm -it ubuntu:20.04

touch /dmc/testfile

When you exit the container, you will see a test file with the permissions of your user (although within the container, the process runs as root).

Calling docker-machine help will provide additional commands of interest, including stop, start, and upgrade. In particular, remember that after a reboot, you will need to restart the VM using docker-machine start and confirm that your shell has performed the eval $(docker-machine env) after the docker-machine has started.

Previous
Previous

DMC Receives 2021 Platinum HIRE Vets Award from U.S. Department of Labor

Next
Next

Solving Problems at the Frontier of AI Safety