Showing results for 
Search instead for 
Did you mean: 

Setting up a local Docker development environment

We make heavy use of Docker internally for its fantastic tooling to help streamline and focus our processes that depend on containers. Recently we found the need to begin hacking on the Docker source to extend its APIs for improving our internal CI/CD workflow. During the development of our custom Docker APIs, I felt that the approach described in Docker’s documentation for setting up a development environment was great for those starting out with contributing, but it didn’t quite fit our needs for the following reasons:

  • all build-related processes are performed inside of a container, which didn’t exactly fit with our existing CM flow;
  • waiting for the dev container to build fresh slowed us down and bloated our dev environment by requiring Docker to build Docker source;
  • the development lifecycle is slightly encumbered due to the nature of needing the code to build Docker inside of a container – which can be solved using volumes, however we already had an established development workflow that uses Vagrant; and
  • when we’re ready to test in a production-like environment with our custom-built Docker, we needed an easy way to build and deploy in our internal cloud – we already had an established workflow for this, so consistency was important

To help alleviate our issues above, I decided to move the build steps outside of the dev container and directly into a RHEL 7.2 VM that we use for development (provisioned by Vagrant) – I use a Mac locally, but if you’re using RHEL directly you don’t necessarily need to use a VM. Please keep in mind that the process I use and describe below is for our internal workflows, and if you intend on contributing to Docker then you should be familiar with and follow Docker’s “Code contribution workflow” (

The entire process to setup a development environment pretty much mirrors what happens during the building of Docker’s development container. It will install various package dependencies, statically build a few required libraries, and set up the environment for building with Go – the steps are easily repeatable and automated using your favorite CM tool.

Install dependencies

Install the required dependencies. You may need to tweak these depending on your environment.

yum install -y golang btrfs-progs btrfs-progs-devel glibc-static

Build statically linked libraries

Here we grab the source for lvm2 and sqlite3 so we can build them manually while enabling them for static linking.

# lvm2
git clone -b v2_02_103 /usr/local/lvm2
cd /usr/local/lvm2
./configure --enable-static_link && make device-mapper && make install_device-mapper

# sqlite3
mkdir /usr/src/sqlite3
curl -sSL | tar -v -C /usr/src/sqlite3 -xz
cd /usr/src/sqlite3/sqlite-autoconf-3081002/
./configure --enable-static && make && make install


Prep environment for building Go

In this step, we’re going to grab Docker source from github and place it in the standard spot for Go programs. Feel free to use your own forked code and relocate the source to where it makes sense in your environment.

# grab docker source

mkdir -p /go/src/

git clone -b v1.9.1 /go/src/

Build docker

And the final step is to build the docker binary from the source we cloned in the previous step.

cd /go/src/

GOPATH=/go:/go/src/ hack/ binary

and the resulting binary should be available at bundles/1.9.1/binary/docker-1.9.1.

Wrapper script

I use a script similar to the following to quickly kick off various tasks while developing.


export GOPATH=/go:/go/src/

cd /go/src/

hack/ $@

and use it for building, linting, validating, running tests, etc. To find the available process you can check the docker/hack/make directory as most of the scripts in there are actual commands that can be used with the provided or using the wrapper above.

./ validate-lint

./ validate-gofmt

TESTFLAGS=' ^TestBuild$' ./ test-unit

./ binary

Recognize Your Peers
Content for Community-Ad