simple docker development environments

Fork me on GitHub



Docker rocks


Docker Compose rocks


I found that more often than not, I wanted to put my development environment inside of Docker, not just my running code. My editor has plugins that help me browse documentation and check my syntax, but none of that works without installing additional stuff, and Docker has made me quite averse to installing anything on my host system.

So, I started stringing together Docker commands to do what I wanted, and I grew frustrated at all the copy/paste, and thought: There’s gotta be a better way.

Skeg is the result.

It’s a little bit of software that helps me develop my code inside of a Docker container. Some example commands:

  • skeg run -t go myapp - run a go 1.6 environment for the current directory
  • skeg list - list all environments
  • skeg destroy myapp - destroy an environment

If you’re interested in how it does this, see the nitty gritty details.

  1. Go to the releases page.
  2. Download the latest release for your platform (and verify)
  3. Make sure it’s executable and in your path.


Create and connect to an environment:

user@host $ cd projects/myapp
user@host $ skeg create -t python -v 3.5 myapp
user@host $ skeg connect myapp
user@myapp $ ls
user@myapp $ touch myapp/
user@myapp $ python3 -V
Python 3.5.1+
user@myapp $ exit
user@host $ skeg destroy myapp
user@host $ ls

Selecting a base image

To select a base image, either:

  1. Use --type (and optionally --version) to select a pre-configured image
  2. Use --image to specify the base image directly


  • --type go - select the default version (1.6) of the pre-configured Go image.
  • --type python --version 2.7 - select the 2.7 version of the pre-configure Python image.
  • --image nate/aws - use a custom-built image

Pre-configured Images

Currently, go, clojure, and python are baked in. More will come.

$ skeg images --base
go: Golang Image
    1.6 (preferred)
clojure: Clojure image
    java8 (preferred)
python: Python base image
    both (preferred)

All Commands


  • create - Creates an environment.
  • connect - Connect to an environment.
  • destroy - Destroys an environment and its home directory.
  • rebuild - Rebuilds an environment, preserving the environment’s home directory.
  • run - Creates an environment and immediately connects to it.
  • start - Starts an environment.
  • stop - Stops an environment.


  • inspect - Shows details about an environment as a JSON dump.
  • list - Lists existing environments.

Image Management

  • images - Lists base images or user specific images.
  • build - Build a user specific image (rarely used)


  • version - Prints the version

Here’s what skeg does under the hood when an environment is created:

Command: skeg create -t python -v 3.5 myapp

  1. Ensure that the skegio/python:3.5 image is pulled.
  2. Ensure that the skeg ssh key is present. If not, one is generated.
  3. Create a directory in ~/skegs/myapp
  4. Populate the ~/skegs/myapp/.ssh/authorized_keys file with the skeg public ssh key
  5. Build an image based on skegio/python:3.5 which includes a user matching the host user.
  6. Start a container running sshd that mounts ~/skegs/myapp in as the user’s home directory and the current directory in as a subdirectory.

Then, to connect:

Command: skeg connect myapp

  1. Execute ssh into the container using the private skeg ssh key

Do I have to use one of the pre-configured images?

Not at all. You can create your own image and use it by specifying the -i flag to skeg create or skeg run. For now, your image needs to be based on skegio/base (like nate/aws), but that will change as skeg gets more sophisticated.

Why does skeg run the container as a long running process and connect over SSH rather than only for the lifetime of a process?

Development environments live longer than a single process, and they often involve many processes. Juggling these processes within an SSH session is a well understood problem with great solutions (like tmux), so for familiarity skeg takes the same approach.

Also, there are many times where additional software needs to be installed and daemons run to try something out. A long running container is perfect for these situations. Skeg offers a rebuild command, which will destroy and create the docker container with the same environment home directory, making it easy to reset back to a known state.