Toxiproxy is cool TCP proxy server shipped both as utility and Docker container. I’ve found it particularly useful for integration testing. You can simply run this dockerized proxy server in test suites which needs one – say you want to write collection of integration tests of how your software behaves when packets are being lost, or connection with peer got big latency. You can do all of these and much more with toxiproxy.
Now within this post, I describe quite specific scenario. I want to ilustrate a way how to make 2 docker containers can talk to each other and show example of simple toxiproxy configuration.
So here we go: I want to run ElasticSearch database as container, but I want to simulate some network issues while accessing it from my local machine.
1 |
<code>docker pull shopify/toxiproxy</code> |
Toxiproxy provides it’s HTTP API through port 8474. Unless you explicitely specify, this port will be exposed on random port on your docker-machine. So let’s just map it to the same port using -p argument. Also, we have to pick a port which we will use to access ES through the proxy. Let it be 42001 and let’s expose it out to the same port as well.
1 |
<code>docker run -p 8474:8474 -p 42001:42001 shopify/toxiproxy</code> |
Now let’s run ElastiSearch container as well and expose port 9200 so we can check its data.
1 |
docker run -p 9200:9200 elasticsearch |
The last thing left to do is to tell ToxiProxy where to redirect data. So let’s tell toxiproxy to listen on port 42001 and redirect all TCP packget flowing in to ElasticSearch exposed port 9200 on Docker VM.
1 2 |
DOCKER_HOST_IP=$(echo $DOCKER_HOST | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b") curl -XPOST "$DOCKER_HOST_IP":8474/proxies -d "{ \"name\": \"proxy_es\", \"listen\": \"0.0.0.0:42001\", \"upstream\": \"$DOCKER_HOST_IP:9200\", \"enabled\": true}" |
Now you should be able to talk to ES via the proxy. Let’s give it a shot:
1 |
curl -XGET "$DOCKER_HOST_IP":42001/_cat |
Great. Now you can use toxiproxy HTTP API to specify the way it should interfere data flowing through. For instance, you can make toxiproxy to delay all data after establishing the connection by certain amount of time – in this case 4000 miliseconds.
1 |
curl -XPOST "$DOCKER_HOST_IP":8474/proxies/proxy_es/toxics -d '{ "name":"delay_data", "type":"latency", "stream":"downstream", "toxicity":100, "attributes": { "latency":4000, "jitter":0} }' |
This setup might be useful when you want to just experiment with toxiproxy manually. Things can be actually much simpler if you use Docker for OSX
instead of Docker toolbox
. That’s because Docker for OSX does not actually runs VM, so you don’t have to expose ports manually – all services running in Docker containers are accessible directly from localhost.
Even better, you don’t have to run ToxiProxy in container at all if you don’t wan to – ToxiProxy is also shipped via brew as service you can just run on your localhost.
Also, eventually you will probably want to use toxiproxy as sort of man-in-the-middle between two docker containers. In that case, you can leverage linking docker containers – feature which basically injects into one container information about other containers.