testing with docker
DESCRIPTION
Presentation at the Portland Docker Meetup on June 17, 2014.TRANSCRIPT
Testing with Docker Tom Offermann
@toffermann June 17, 2014
Introduction
‣What’s the Problem? Testing in Varied Environments !
‣Our Solution Step-by-Step Explanation
Presentation Overview
‣What’s the Problem? Testing in Varied Environments !
‣Our Solution Step-by-Step Explanation
Presentation Overview
What’s the Problem?
What Does New Relic Do?
What’s the Problem?
What’s the Problem?
Is Best!
What’s the Problem?
Python
versions
What’s the Problem?
Python
versionsframeworks
What’s the Problem?
Python
versionsframeworksdatabases
What’s the Problem?
Python
versionsframeworksdatabases
da
ta
ba
se
c
lie
nts
What’s the Problem?
Python
versionsframeworksdatabases
da
ta
ba
se
c
lie
nts
How do we test all of these scenarios?
‣What’s the Problem? Testing in Varied Environments !
‣Our Solution Step-by-Step Explanation
Presentation Overview
‣What’s the Problem? Testing in Varied Environments !
‣Our Solution Step-by-Step Explanation
Presentation Overview
Our Solution
✤ Create Docker Images
✤ Run a Test Container
✤ Packnsend
Our Solution
✤ Create Docker Images
✤ Run a Test Container
✤ Packnsend
Create Docker Images# Dockerfile for memcached!!FROM ubuntu:12.04!!RUN apt-get update!RUN apt-get install -y memcached!!EXPOSE 11211!ENTRYPOINT ["memcached"]!CMD ["-p", "11211"]!USER daemon!
Create Docker Images$ tree python_agent/docker !!python_agent/docker!...!!"" mysql!# $"" Dockerfile!!"" postgresql!# $"" Dockerfile!...!$"" redis! $"" Dockerfile!
Our Solution
✤ Create Docker Images
✤ Run a Test Container !✤ Packnsend
Our Solution
✤ Create Docker Images
✤ Run a Test Container • Install testing tools
!✤ Packnsend
Testing Tools
x 4
Testing Tools
x 4tox
Testing Tools
x 4tox virtualenv
Our Solution
✤ Create Docker Images
✤ Run a Test Container • Install testing tools• Copy source code
!✤ Packnsend
Copy Source Code
Technique #1: Pull!!!$ docker run test-image test.sh \!! --repo http://github.com/nr/python-agent \!! tox -c tests/tox.ini!!
Copy Source Code
Technique #1: Pull!!!$ docker run test-image test.sh \!! --repo http://github.com/nr/python-agent \!! tox -c tests/tox.ini!!
Downside: Requires commit to git repository
Copy Source Code
Technique #2: Host-Mounted Volume!!!$ docker run -v /path/to/repo:/code \!! test-image test.sh tox!!
Copy Source Code
Technique #2: Host-Mounted Volume!!!$ docker run -v /path/to/repo:/code \!! test-image test.sh tox!!
Downside: Problematic with boot2docker
Copy Source Code
Technique #3: Docker ADD to Image!!!$ DATA_DIR=`mktemp -d $TMPDIR/packnsend.XXXXXXXX`!!$ git checkout-index --prefix=$DATA_DIR/ -a!
Copy Source CodeTechnique #3: Docker ADD to Image!!# Dockerfile for Test Image!# Copy to $DATA_DIR!FROM python-base!!RUN chown -R guest.users /data!RUN chmod 0755 /data!USER guest!ENV HOME /home/guest!!ADD . /data!VOLUME /data!
Copy Source CodeTechnique #3: Docker ADD to Image!!# Dockerfile for Test Image!# Copy to $DATA_DIR!FROM python-base!!RUN chown -R guest.users /data!RUN chmod 0755 /data!USER guest!ENV HOME /home/guest!!ADD . /data!VOLUME /data!
Copy Source Code
Technique #3: Docker ADD to Image!!!$ IMG_NAME="packnsend-`date '+%Y%m%d%H%M%S'`-$$"!!$ cd $DATA_DIR && ! docker build --rm -t $IMG_NAME .!
Our Solution
✤ Create Docker Images
✤ Run a Test Container • Install testing tools• Copy source code• Use service containers
!✤ Packnsend
Use Service Containers
Linking Docker Containers!!!$ docker run -d --name db mysql!!$ docker run -d --link db:db —name test $IMG_NAME!
Use Service Containers
Linking Docker Containers!!!DB_PORT_3306_TCP_ADDR=172.17.0.5!DB_PORT_3306_TCP_PORT=3306!DB_PORT_3306_TCP_PROTO=tcp!DB_PORT_3306_TCP=tcp://172.17.0.5:3306!DB_PORT=tcp://172.17.0.5:3306!
Use Service ContainersLinking Docker Containers!!$ docker run -d \! --name $DATA_IMAGE_NAME \! --link packnsend-gearmand:gearmand \! --link packnsend-memcached:memcached \! --link packnsend-postgresql:postgresql \! --link packnsend-mysql:mysql \! --link packnsend-devpi:devpi \! --link packnsend-squid:squid \! --link packnsend-mongodb:mongodb \! --link packnsend-redis:redis \! $IMG_NAME!
Our Solution✤ Create Docker Images for Services
✤ Running a Test Container • Install testing tools• Copy source code• Use services• Run test command
!✤ Packnsend
Run Test Command!$ docker run -d \! --name $DATA_IMAGE_NAME \! --link packnsend-gearmand:gearmand \! --link packnsend-memcached:memcached \! --link packnsend-postgresql:postgresql \! --link packnsend-mysql:mysql \! --link packnsend-devpi:devpi \! --link packnsend-squid:squid \! --link packnsend-mongodb:mongodb \! --link packnsend-redis:redis \! $DATA_IMAGE_NAME !! tox -c tests/tox.ini!
Our Solution
✤ Create Docker Images for Services
✤ Running a Test Container !✤ Packnsend
Packnsendpacknsend: COMMAND [arg...]!!Run Commands:! run Run command on test container.! run -i Run command interactively.! shell Launch a shell on test container.!!Management Commands:!! init Pull images, if authorized, else build.! build Build base images.! push Push base images.! pull Pull base images.! start Start base containers.! stop Stop base containers.! cleanup Delete base images.!
Packnsend
Demo!
Our Solution
✤ Create Docker Images for Services
✤ Running a Test Container
✤ Packnsend • Launcher Script
!
Launcher Script!#!/bin/sh!!. /data/docker/environ!!"$@" > /data/out.log 2>&1!!STATUS=$?!!cp /data/out.log /tmp/out.log!!exit `expr $STATUS`!
Launcher Script!#!/bin/sh!!. /data/docker/environ # Set Env Vars!!"$@" > /data/out.log 2>&1!!STATUS=$?!!cp /data/out.log /tmp/out.log!!exit `expr $STATUS`!
Source Environ# Add environment variables!export PACKNSEND_DB_USER=db_user!!# Munge existing environment variables!# We have this form!# DEVPI_PORT=tcp://172.17.0.6:3141!!if test -n "$DEVPI_PORT"!then!! BASE=`echo $DEVPI_PORT | sed -e ’s/tcp/http/'`!! PATH=packnsend/testing/+simple/!! export PIP_INDEX_URL=$BASE/$PATH!fi
Launcher Script!#!/bin/sh!!. /data/docker/environ!!"$@" > /data/out.log 2>&1 # Log Output!!STATUS=$?!!cp /data/out.log /tmp/out.log!!exit `expr $STATUS`!
Launcher Script!#!/bin/sh!!. /data/docker/environ!!"$@" > /data/out.log 2>&1!!STATUS=$? # Capture Exit Code!!cp /data/out.log /tmp/out.log!!exit `expr $STATUS`!
Our Solution
✤ Create Docker Images for Services
✤ Running a Test Container
✤ Packnsend • Launcher Script• Automatic Cleanup
Automatic Cleanup!cleanup_containers()!{!! docker kill $CONTAINER_ID!! docker rm --volumes $CONTAINER_ID!!! docker rmi $IMAGE_ID!!! rm -r $DATA_DIRECTORY!}!
Automatic Cleanup!cleanup_containers()!{!! docker kill $CONTAINER_ID!! docker rm --volumes $CONTAINER_ID!!! docker rmi $IMAGE_ID!!! rm -r $DATA_DIRECTORY!}!
Our Solution
✤ Create Docker Images
✤ Run a Test Container
✤ Packnsend • Launcher Script• Automatic Cleanup• Remote Docker Daemon
!
Remote Docker Daemon!# SSH Tunnel!!$ export EC2=<ec2 address>!$ ssh -f ubuntu@$EC2 -L 14243:$EC2:2375 -N !!!# Set DOCKER_HOST environment variable!!$ export DOCKER_HOST="localhost:14243"
Our Solution
✤ Create Docker Images
✤ Run a Test Container
✤ Packnsend • Launcher Script• Automatic Cleanup• Remote Docker Daemon• Parallel Tests
!
Parallel Tests# test_commands.txt!packnsend run tox -c tests/tox1.ini!packnsend run tox -c tests/tox2.ini!packnsend run tox -c tests/tox3.ini!packnsend run tox -c tests/tox4.ini!packnsend run tox -c tests/tox5.ini!packnsend run tox -c tests/tox6.ini!...!!# Run tests in parallel!!$ cat test_commands.txt | parallel!
Conclusion
Testing with Docker Tom Offermann
@toffermann June 17, 2014