Jun 11, 2014
Prelude
Yesterday I finished my first 30-day streak on GitHub. Most of contributions were to Docker – the biggest opensource project on Go. I learned a lot in this month, and it was really cool. I think that this is mostly because of Go language. I’ve been programming on Python for five years and I was never so excited about open source, because Python is not even half so fun as Go.
1. Tools
There are a lot of tools for go, some of them just are “must have”.
Goimports - like
go fmt
but with cool imports handling, I really think that go fmt
needs to
be replaced with Goimports
in future Go versions.
Vet - analyzes code for some suspicious constructs. You can find with it: bad format strings, unreachable code, passing mutex by value and etc. PR about vet erros in Docker.
Golint - checks code for google style guide.
2. Editor
I love my awesome vim with awesome vim-go plugin, which is integrated with tools mentioned above. It formats code for me, adds needed imports, removes unused imports, shows documentation, supports tagbar and more. And my favourite - go to definition. I really suffered without it :) With vim-go my development rate became faster than I could imagine. You can see my config in my dotfiles repo.
3. Race detector
This is one of the most important and one of the most underestimated thing. Very useful and very easy to use. You can find description and examples here. I’ve found many race conditions with this tool (#1, #2, #3, #4, #5).
4. Docker specific
Docker has very smart and friendly community. You can always ask for help about hacking in #docker-dev on Freenode. But I’ll describe some simple tasks that appears when you try to hack docker first time.
Tests
There are three kinds of tests in docker repo:
unit
- unit tests(ah, we all know what unit tests are, right?). These tests spreaded all over repository and can be run bymake test-unit
. You can run tests for one directory, specifying it inTESTDIRS
variable. For exampleTESTDIRS="daemon" make test-unit
will run tests only for daemon directory.
integration-cli
- integration tests, that use external docker commands (for exampledocker build
,docker run
, etc.). It is very easy to write this kind of tests and you should do it if you think that your changes can change Docker’s behavior from client’s point of view. These tests are located inintegration-cli
directory and can be run bymake test-integration-cli
. You can run one or more specific tests with settingTESTFLAGS
variable. For exampleTESTFLAGS="-run TestBuild" make test-integration-cli
will run all tests whose names starts with
TestBuild
.integration
- integration tests, that use internal docker datastructures. It is deprecated now, so if you want to write tests you should preferintegration-cli
orunit
. These tests are located inintegration
directory and can be run bymake test-integration
.
All tests can be run by make test
.
Build and run tests on host
All make
commands execute in docker container, it can be pretty annoying to
build container just for running unit tests for example.
So, for running unit test on host machine you need canonical Go
workspace. When it’s ready you can
just do symlink to docker repo in src/github.com/dotcloud/docker
. But we still
need right $GOPATH
, here is the trick:
export GOPATH=<workspace>/src/github.com/dotcloud/docker/vendor:<workspace>
And then, for example you can run:
go test github.com/dotcloud/docker/daemon/networkdriver/ipallocator
Some tests require external libs for example libdevmapper
, you can disable
it with DOCKER_BUILDTAGS
environment variable. For example:
export DOCKER_BUILDTAGS='exclude_graphdriver_devicemapper exclude_graphdriver_aufs'
For fast building dynamic binary you can use this snippet in docker repo:
export AUTO_GOPATH=1
export DOCKER_BUILDTAGS='exclude_graphdriver_devicemapper exclude_graphdriver_aufs'
hack/make.sh dynbinary
I use that DOCKER_BUILDTAGS
for my btrfs
system, so if you use aufs
or
devicemapper
you should change it for your driver.
Race detection
To enable race detection in docker I’m using patch:
diff --git a/hack/make/binary b/hack/make/binary
index b97069a..74b202d 100755
--- a/hack/make/binary
+++ b/hack/make/binary
@@ -6,6 +6,7 @@ DEST=$1
go build \
-o "$DEST/docker-$VERSION" \
"${BUILDFLAGS[@]}" \
+ -race \
-ldflags "
$LDFLAGS
$LDFLAGS_STATIC_DOCKER
After that all binaries will be with race detection. Note that this will slow docker a lot.
Docker-stress
There is amazing docker-stress from Spotify for Docker load testing. Usage is pretty straightforward:
./docker-stress -c 50 -t 5
Here 50 clients are trying to run containers, which will alive for five seconds.
docker-stress
uses only docker run
jobs for testing, so I prefer also to run in
parallel sort of:
docker events
while true; do docker inspect $(docker ps -lq); done
while true; do docker build -t test test; done
and so on.
Useful links
You definitely need to read Contributing to Docker and Setting Up a Dev Environment. I really don’t think that something else is needed for Docker hacking start.
Conclusion
This is all that I wanted to tell you about my first big opensource experience. Also, just today Docker folks launched some new projects and I am very excited about it. So, I want to invite you all to the magical world of Go, Opensource and, of course, Docker.