Build Brev Yourself
How & why I stopped using Docker on my Mac
Why you shouldn't run Docker on your Mac
Sometimes Docker on your laptop sucks. Itâs inconvenient to install on your new Apple Silicon and casually eats 11.23 GB of RAM. Docker Mac incurs significant performance penalties since it depends on VMs. Docker Linux, however, does not suffer from this constraint. Hereâs one weird trick to improve Mac performance that docker doesnât want you to know about.
Run docker remotely in 2 easy steps:
- Run Docker daemon on a remote computer
- Connect your local Docker client to the remote daemon
Run Docker daemon on a remote computer
You will need a remote computer running with SSH access. Most cloud providers have guides on how to do this (AWS, AZURE, GCP). Next, install Docker on this remote computer.
A simple way to do this
If youâd like to create a pre-configured Linux computer, you can use Brev, which has ssh, Docker, and docker-compose installed by default. You will need to install the CLI.
Connect your local Docker client to the remote daemon
For the tutorialâs sake, I will use a Brev environment named âbrev-environmentâ as my remote computer.
Docker can connect to the remote Docker computer by using the environment variable DOCKER_HOST. Out of the box, docker supports SSH as a connection protocol.
export SSH_CONNECTION_STRING=brev-environment-b4qd
export DOCKER_HOST=ssh://${SSH_CONNECTION_STRING}
docker -H ${DOCKER_HOST} ps
Heads up
If you are not using brev your SSH_CONNECTION_STRING may look more like --> user@X.X.X.X
Key Verification Failed?
key verification failed. --> if you get this error, you may need to run ssh ${SSH_CONNECTION_STRING}
and accept the key fingerprint
You can also pass the Docker host in as a CLI argument
docker -H ${DOCKER_HOST} ps
Improve Client Performance
The Docker ssh protocol creates a new connection for each command. This operation can sometimes be slow. You can re-use an ssh connection by forwarding the docker endpoint to your local computer. The docker API, by default, is exposed as a UNIX socket.
export CONTEXT_NAME=remote-example
export LOCAL_SOCKET_DIR=${HOME}/remote-docker-sockets/${CONTEXT_NAME}
mkdir -p ${LOCAL_SOCKET_DIR}
export LOCAL_SOCKET_PATH=${LOCAL_SOCKET_DIR}/docker.sock
ssh -L ${LOCAL_SOCKET_PATH}:/var/run/docker.sock ${SSH_CONNECTION_STRING} -N &
Docker.sock: Address already in use?
docker.sock: Address already in use --> to fix this run rm ${LOCAL_SOCKET_PATH}
Change the Docker host to point to the locally forwarded unix file.
export DOCKER_HOST=unix://${LOCAL_SOCKET_PATH}
Globally configure the remote connection with Docker contexts
To permanently use this configuration, you can export the env variable DOCKER_HOST in your shell config(.zshrc, .bashrc), or you could use Docker contexts which allow you to switch between different Docker hosts easier.
export CONTEXT_NAME=remote-example
docker context create ${CONTEXT_NAME} --
docker "host=${DOCKER_HOST}"
docker context ls # see all contexts
docker context use ${CONTEXT_NAME} # set as global default
Use Docker!
You can now use Docker as if itâs running on your local computer!
Set your Docker context.
docker context use ${CONTEXT_NAME} # set context
docker run hello-world # run image
git clone https://github.com/brevdev/example-k8s-docker-compose-plus.git docker-example && cd docker-example
docker-compose up # run docker-compose services
docker build . # build images
Pushing, pulling, and running large Docker images is vastly improved since you can take advantage of data center network speed!
docker run hello-world
Docker containers can be built faster on remote computers since you can provision powerful machines in the cloud. You can also trust that your lengthy builds wonât be interrupted by a dead battery or wifi outage!
git clone https://github.com/brevdev/example-k8s-docker-compose-plus.git docker-example && cd docker-example # example repodocker build.
Run your dev helper services.
# working directory = docker-example
docker-compose up -d
docker-compose exec nginx sh
Bad CPU type in executable?
fork/exec /usr/local/bin/docker-compose-v1: bad CPU type in executable --> you may need to run softwareupdate --install-rosetta if you're on Apple Silicon
Next Steps & Tradeoffs
Running remote Docker isnât entirely a free lunch.
Networking
One of the first things you may want to do is connect to one of your Docker containers over the network. Since it runs on a remote computer, you can not simply access it at localhost:X000. You must forward the desired ports from your local computer to your remote computer to access a port.
Port forwarding can be achieved with SSH.
export REMOTE_PORT=3002
export LOCAL_PORT=3002
docker run -p ${REMOTE_PORT}:80 -d nginx
ssh -T -L ${LOCAL_PORT}:127.0.0.1:${REMOTE_PORT} ${SSH_CONNECTION_STRING} -N &
curl localhost:${LOCAL_PORT}
Port forward with the Brev CLI
If using brev you can also use the port-forward command brev port-forward -p ${LOCAL_PORT}:${REMOTE_PORT} ${BREV_NAME}
Another issue you may encounter is building Docker images with large local contexts. Moving large files over the network can result in poor performance. Moving more of your development assets onto the remote computer fixes this problem and is the standard approach at Brev.
Volumes/Mounts
Since Docker is running on a remote computer, the Docker daemon will make file volumes and mounts on the remote computer, not the local computer. You can use the following tools if you intend to sync files between your local computer and the remote one.
- scp
- sshfs
- rsync
- mutagen
Besides using these tools, moving more of your development assets into the remote computer removes many file sync issues.
Extra Management and Context
Working across multiple computers (local and remote) increases cognitive load. You need to know, in all contexts, what filesystem and network youâre currently working on and how to interface between them. Managing connections and keys yourself can quickly become tedious. Finally, I want to mention that running cloud computers can become quite costly if you are not actively managing and tracking computer type and usage.
If these problems interest you check out Brev; itâs what we work on full-time!