diff --git a/.env b/.env
new file mode 100644
index 0000000000000000000000000000000000000000..7c84e9ef4e2f8bee0c4c3b37482bfb61ab71e089
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+COMPOSE_PROJECT_NAME=sciencebeam-gym
+IMAGE_TAG=develop
diff --git a/.travis.yml b/.travis.yml
index b5027ce9d3c6dba5fea38bb720685bad85ef43f4..451e3babbf6e991495e488dce604d0edbe003d43 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,8 +5,8 @@ services:
   - docker
 
 before_install:
-  - docker build -t elife/sciencebeam-gym .
+  - docker-compose -f docker-compose.yml -f docker-compose.ci.yml build
 
 script:
-  - ./project_tests.sh
+  - docker-compose -f docker-compose.yml -f docker-compose.ci.yml run --rm sciencebeam-gym ./project_tests.sh
 
diff --git a/Dockerfile b/Dockerfile
index 7013974c04892ac58360b601bd0dc96d9b80a69b..181da0847ead08dde347d16208420ab451b2ab4b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,12 @@
 FROM python:2.7.14-stretch
+
 ENV PROJECT_HOME=/srv/sciencebeam-gym
 
+ENV VENV=${PROJECT_HOME}/venv
+RUN virtualenv ${VENV}
+ENV PYTHONUSERBASE=${VENV} PATH=${VENV}/bin:$PATH
+
 WORKDIR ${PROJECT_HOME}
-RUN virtualenv venv
 
 COPY requirements.prereq.txt ${PROJECT_HOME}/
 RUN venv/bin/pip install -r requirements.prereq.txt
diff --git a/Jenkinsfile b/Jenkinsfile
index 6c7e82809439e0751df3a39f8712e9e07c4104fe..a2f088a9b55e3c4938c76a88911ead58ff9096b2 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,25 +1,29 @@
 elifeLibrary {
     def commit
+
     stage 'Checkout', {
         checkout scm
         commit = elifeGitRevision()
     }
 
-    stage 'Build image', {
-        sh 'docker build -t elife/sciencebeam-gym .'
-    }
+    node('containers-jenkins-plugin') {
+        stage 'Build images', {
+            checkout scm
+            dockerComposeBuild(commit)
+        }
 
-    stage 'Run tests', {
-        elifeLocalTests './project_tests.sh'
+        stage 'Project tests', {
+            dockerComposeRun(
+                "sciencebeam-gym",
+                "./project_tests.sh",
+                commit
+            )
+        }
     }
 
     elifeMainlineOnly {
         stage 'Merge to master', {
             elifeGitMoveToBranch commit, 'master'
         }
-
-        stage 'Downstream', {
-            build job: '/dependencies/dependencies-sciencebeam-update-sciencebeam-gym', wait: false, parameters: [string(name: 'commit', value: commit)]
-        }
     }
 }
diff --git a/docker-compose.ci.yml b/docker-compose.ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e47999541684ebaece4fe3c45a9471fe8f361f99
--- /dev/null
+++ b/docker-compose.ci.yml
@@ -0,0 +1,4 @@
+version: '3'
+
+# to add images that are only used for tests
+services: {}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..667ce276d63dfcee185410f858c4ee0efe9ec177
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,8 @@
+version: '3'
+
+services:
+    sciencebeam-gym:
+        build:
+            context: .
+            dockerfile: Dockerfile
+        image: elifesciences/sciencebeam-gym:${IMAGE_TAG}
diff --git a/project_tests.sh b/project_tests.sh
index e24ca94271bb82c37586647cd423d5d452f53a85..9584518bfaa9d763fcca5e5020eaf5c2cb992c84 100755
--- a/project_tests.sh
+++ b/project_tests.sh
@@ -1,4 +1,6 @@
 #!/bin/bash
 set -e
 
-docker run --rm elife/sciencebeam-gym /bin/bash -c 'venv/bin/pip install pytest nose && venv/bin/pytest sciencebeam_gym'
+pip install -r requirements.dev.txt
+
+pytest sciencebeam_gym