Remote Docker

June 20th, 2022

Remote Docker

Your Docker client (like the docker command) can be on a separate computer than the docker daemon. If you ever played with docker machine (depreciated), this is basically that idea.

Docker clients talk to Docker daemons through an API.

Example clients are the usual suspects that Docker users are familiar with: the docker and docker-compose commands (among others).

Since the Docker daemon just exposes an API, we can connect to it remotely! This is a feature we use at Chipper CI.

You can easily point your docker command to a remote host by setting a DOCKER_HOST environment variable:

# List running containers on host
DOCKER_HOST= docker ps

This of course assumes you can access that host, the daemon is listening on appropriate networks, and no network security is blocking that port from accepting external connections.

Remote Docker in Chipper

Chipper allows the use of Docker within builds by providing remote servers that have Docker installed on them.

This is for security, since builds are not run on dedicated servers (a feature we're looking at for the future). If you ran docker ps and saw other's customer data…well, that just wouldn't do.

So, each build that requests docker as a service gets a server assigned to that build.

⚠️ Docker is a paid feature in Chipper CI

version: 1

  php: 8.1
  node: 16

# Let us know you want Docker in this build
  - docker:

  - name: Setup
    cmd: echo "composer install, or something"

Under the Hood at Chipper

Under the hood, we have a auto-scaling group (ASG) with (you guessed it) servers. These servers have Docker on them, and are in a private network that the Chipper build servers can reach.

As a server is requested for a build, a server is "popped" out of the ASG, and used in that build. That Docker server is destroyed when the build is complete. The ASG, in the meantime, replaces the server taken out of the ASG. A new one becomes ready for another build.

A bit more interesting is that there's also a "warm-pool" of servers in that ASG. These are servers that have been created, bootstrapped, but then turned off. If extra servers are needed, these are spun up and used in a similar way. "Warm" servers have faster boot-times than "fresh" servers, and so extra demand for Docker servers are able to be met fairly quickly this way.

Using Docker Remotely

There are some caveats to run Docker remotely (whether in Chipper or outside of it). Docker is literally running on a separate server, so you can imagine some things can get weird - for example, file sharing.

Docker build works!

First, the good news. Running docker build works great. The COPY and ADD keywords will be able to copy your local code files into a Docker image when running docker build commands.

This lets the vapor deploy command work (if they use the Docker runtime), since Vapor is able to build files into the resulting Docker image.

You can also build your own custom images, if that's part of your CI process.

No localhost

More good news (or at least, not bad news). You can still use Docker to provide some extra services that you may want in your CI pipeline.

Normally you'd expose ports for a given Docker service and use [localhost](http://localhost) to call them:

docker run -p 1337:1337 my-image:latest

# nope
curl localhost:1337/v1/some/api

In our case, Docker is not run locally, so [localhost](http://localhost) won't work. However, we know the address of the Docker server, and we can use that!

docker run -p 1337:1337 my-image:latest

# yes!
curl $DOCKER_HOST_IP:1337/v1/some/api

Again, this assumes the host allows connections on port 1337 from wherever you are making a curl request to.

No file system sharing

Mounting directories into your Docker container simply won't work. There's no magic networking configuration (on Chipper's end) to connect 2 different server's file system. In theory that's possible, but it's a relatively strange setup to find in the wild.

That means the following won't work:

# nope
docker run \
    -v $(pwd):/var/www/html \
    -p 80:80 some-image:latest

As a result, many docker-compose configurations (which often share local volumes into a container) are likely to fail in Chipper CI.

If you need to run a container that sees your code files, you'll need to get files into the container via docker build, and then run the resulting image as a new container.

More information on using Docker in Chipper CI is available here, including a list of environment variables we setup for you when using Docker.