I was looking for an answer to your question, but ironically found a question I have an answer to (how to run docker tests quickly). If you really want fast tests, you should ideally avoid rebuilding the container at all when you run them. But wait, how to get the new source code onto the container? Volumes my friend, volumes. Here's how I've set this up:
docker-compose.dev.yml:
backend-test:
volumes:
- .:/path/to/myapp
Where /path/to/myapp is the path in the image, of course. You'll have to explicitly pass in this image for dev:
docker-compose up -f docker-compose.dev.yml
But now, when you run your tests, you're not going to use docker-compose anymore, you're going to use docker exec:
docker exec -it backend-test go test
If you do this right, your src dir in the backend-test container will always be up to date because it's in fact a mounted volume. Attaching to a running container and running tests should prove far faster than spinning up a new one each time.
EDIT: Commenter correctly pointed out that this only avoids rebuilding the image when you're dependencies haven't changed (no need go get
). The nice thing is that it not only avoids rebuilding, but it also avoids restarting. When I'm testing like this, and I add a dependency, I typically just go get
directly from my test console. It can be a bit tricky to get go get
to work within your container, but one way is to forward your ssh agent through to your container by mounting SSH_AUTH_SOCK. Sadly, you can't mount volumes during build, so you may need to include some kind of deploy key in your image if you want your build target to be able to pull fresh dependencies before running tests. However, The main point of my answer was to separate out the build and test, to avoid the full build until you're ready to generate the final artifact.
That said, I think I might understand that I'm not answering the question in the way that you asked it. In ruby, the answer would be as simple as copying the Gemfile and Gemfile.lock, and running bundle install --deploy
, before copying over the code you've changed. Personally I don't mind the cost of rebuilding when I add dependencies, since 99% of my changes still won't involve a rebuild. That said, you might look into using golang's new Bundler inspired dependency manager: dep. With dep installed, I'm pretty sure you can just copy your Gopkg.toml
and Gopkg.lock
into your workdir, run dep ensure
, and then copy your code. This will only pull dependencies when the Gopkg has been updated - otherwise docker will be able to reuse the cached layer with your previous dependencies installed. Sorry for the long edit!
vendor/
, just copy in your GOPATH. – Kravits