Repository: scionproto/scion
Pull request #3721 (2020-04-20 09:57:21)

docker: remove docker.sh & perapp structure
* docker: remove perapp structure

* have a flat docker file that is responsible
for building the container images.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/scionproto/scion/3721)
<!-- Reviewable:end -->



Patch:
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
index 05a1ea52c..927bdcf7c 100644
--- a/.buildkite/pipeline.yml
+++ b/.buildkite/pipeline.yml
@@ -105,11 +105,10 @@ steps:
         - exit_status: 255 # Forced agent shutdown
   - label: ":docker: Integration: end2end_integration"
     command:
-    - bazel run //docker/perapp:prod
     - ./scion.sh topology -t -d -c topology/Tiny.topo
     - ./scion.sh run
     - docker-compose -f gen/scion-dc.yml -p scion up -d $(docker-compose -f gen/scion-dc.yml config --services | grep tester)
-    - sleep 5
+    - sleep 10
     - ./bin/cert_req_integration -d -log.console warn
     - ./bin/pp_integration -d -log.console warn
     - ./bin/scmp_integration -d -log.console warn
@@ -125,7 +124,6 @@ steps:
   - label: ":docker: Integration: end2end_integration full topology"
     if: build.message !~ /\[doc\]/
     command:
-    - bazel run //docker/perapp:prod >/dev/null 2>&1
     - ./scion.sh topology -t -d
     - ./scion.sh run
     - docker-compose -f gen/scion-dc.yml -p scion up -d $(docker-compose -f gen/scion-dc.yml config --services | grep tester)
diff --git a/WORKSPACE b/WORKSPACE
index 3d42d444d..618b1a382 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -36,6 +36,18 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
 
 gazelle_dependencies()
 
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+http_archive(
+    name = "rules_pkg",
+    urls = [
+        "https://github.com/bazelbuild/rules_pkg/releases/download/0.2.5/rules_pkg-0.2.5.tar.gz",
+        "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.2.5/rules_pkg-0.2.5.tar.gz",
+    ],
+    sha256 = "352c090cc3d3f9a6b4e676cf42a6047c16824959b438895a76c2989c6d7c246a",
+)
+load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
+rules_pkg_dependencies()
+
 # Docker rules
 http_archive(
     name = "io_bazel_rules_docker",
@@ -43,6 +55,7 @@ http_archive(
     strip_prefix = "rules_docker-0.12.1",
     urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.12.1/rules_docker-v0.12.1.tar.gz"],
 )
+
 load("@io_bazel_rules_docker//repositories:repositories.bzl", container_repositories = "repositories")
 
 container_repositories()
@@ -170,6 +183,7 @@ container_pull(
     name = "ubuntu16",
     registry = "index.docker.io",
     repository = "library/ubuntu",
+    digest = "sha256:a98d9dcf3a34b2b78e78c61d003eb4d7a90d30fd54451686e2f0bd2ef5f602ac",
     tag = "16.04",
 )
 
diff --git a/acceptance/lib.sh b/acceptance/lib.sh
index 198686fe2..2964c697e 100644
--- a/acceptance/lib.sh
+++ b/acceptance/lib.sh
@@ -27,11 +27,11 @@ stop_infra() {
 }
 
 build_docker_tester() {
-    ./docker.sh tester
+    make -C docker test
 }
 
 build_docker_perapp() {
-    make -C docker/perapp bazel
+    make -C docker prod debug
 }
 
 artifacts_dir() {
diff --git a/acceptance/sig_failover/BUILD.bazel b/acceptance/sig_failover/BUILD.bazel
index c9fdd1398..f6b53f1e3 100644
--- a/acceptance/sig_failover/BUILD.bazel
+++ b/acceptance/sig_failover/BUILD.bazel
@@ -16,7 +16,7 @@ sh_test(
 
 container_image(
     name = "dispatcher1",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/1-ff00_0_110/dispatcher/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -28,7 +28,7 @@ container_image(
 
 container_image(
     name = "dispatcher2",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/1-ff00_0_111/dispatcher/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -40,7 +40,7 @@ container_image(
 
 container_image(
     name = "sig1",
-    base = "//docker/perapp:sig_debug",
+    base = "//docker:sig_debug",
     files = [
         "testdata/1-ff00_0_110/sig/cfg.json",
         "testdata/1-ff00_0_110/sig/sig.toml",
@@ -56,7 +56,7 @@ container_image(
 
 container_image(
     name = "sig2",
-    base = "//docker/perapp:sig_debug",
+    base = "//docker:sig_debug",
     files = [
         "testdata/1-ff00_0_111/sig/cfg.json",
         "testdata/1-ff00_0_111/sig/sig.toml",
diff --git a/acceptance/sig_short_exp_time/BUILD.bazel b/acceptance/sig_short_exp_time/BUILD.bazel
index 974fd31a9..e54d09fcd 100644
--- a/acceptance/sig_short_exp_time/BUILD.bazel
+++ b/acceptance/sig_short_exp_time/BUILD.bazel
@@ -16,7 +16,7 @@ sh_test(
 
 container_image(
     name = "dispatcher1",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/1-ff00_0_110/dispatcher/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -28,7 +28,7 @@ container_image(
 
 container_image(
     name = "dispatcher2",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/1-ff00_0_111/dispatcher/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -40,7 +40,7 @@ container_image(
 
 container_image(
     name = "sig1",
-    base = "//docker/perapp:sig_debug",
+    base = "//docker:sig_debug",
     files = [
         "testdata/1-ff00_0_110/sig/cfg.json",
         "testdata/1-ff00_0_110/sig/sig.toml",
@@ -56,7 +56,7 @@ container_image(
 
 container_image(
     name = "sig2",
-    base = "//docker/perapp:sig_debug",
+    base = "//docker:sig_debug",
     files = [
         "testdata/1-ff00_0_111/sig/cfg.json",
         "testdata/1-ff00_0_111/sig/sig.toml",
diff --git a/acceptance/topo_cs_reload/BUILD.bazel b/acceptance/topo_cs_reload/BUILD.bazel
index b35be4ba0..d0f0bde3b 100644
--- a/acceptance/topo_cs_reload/BUILD.bazel
+++ b/acceptance/topo_cs_reload/BUILD.bazel
@@ -23,7 +23,7 @@ go_test(
 
 container_image(
     name = "dispatcher",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -34,7 +34,7 @@ container_image(
 
 container_image(
     name = "cs",
-    base = "//docker/perapp:cs_debug",
+    base = "//docker:cs_debug",
     files = [
         "testdata/cs.toml",
         "//acceptance/topo_common:topology",
diff --git a/acceptance/topo_sd_reload/BUILD.bazel b/acceptance/topo_sd_reload/BUILD.bazel
index 1c8fddda7..561461f5c 100644
--- a/acceptance/topo_sd_reload/BUILD.bazel
+++ b/acceptance/topo_sd_reload/BUILD.bazel
@@ -21,7 +21,7 @@ go_test(
 
 container_image(
     name = "dispatcher",
-    base = "//docker/perapp:dispatcher_debug",
+    base = "//docker:dispatcher_debug",
     files = ["testdata/disp.toml"],
     entrypoint = [
         "/app/dispatcher",
@@ -32,7 +32,7 @@ container_image(
 
 container_image(
     name = "sciond",
-    base = "//docker/perapp:sciond_debug",
+    base = "//docker:sciond_debug",
     files = [
         "testdata/sd.toml",
         "//acceptance/topo_common:topology",
diff --git a/doc/BUILD.bazel b/doc/BUILD.bazel
new file mode 100644
index 000000000..76829dc39
--- /dev/null
+++ b/doc/BUILD.bazel
@@ -0,0 +1,1 @@
+exports_files(["PathPolicy.md"])
diff --git a/docker.sh b/docker.sh
deleted file mode 100755
index 1786a16dd..000000000
--- a/docker.sh
+++ /dev/null
@@ -1,247 +0,0 @@
-#!/bin/bash
-
-ORG=scionproto
-branch=
-build_dir=
-image_tag=
-
-get_params() {
-    # If we're on a local branch, use that. If we're on a detached HEAD from a
-    # remote branch, or from a bare rev id, use that instead.
-    branch=$(LC_ALL=C git status | head -n1 |
-    awk '/^On branch|HEAD detached at/ {print $NF}')
-    build_dir="docker/_build/$branch"
-    image_tag=$(echo "$branch" | tr '/' '.')
-}
-
-cmd_base() {
-    set -e
-    set -o pipefail
-    get_params
-    copy_tree
-    docker_build "base"
-    docker tag scion_base:latest "$ORG/scion_base:pending"
-    touch docker/_build/scion_base.stamp
-}
-
-cmd_build() {
-    set -e
-    set -o pipefail
-    get_params
-    copy_tree
-    docker_build
-}
-
-cmd_tester() {
-    set -eo pipefail
-    bazel run //docker/testimages:scion_testing_bundle
-    docker build -f "docker/testimages/Dockerfile.sig_accept" -t "scion_sig_acceptance" docker/testimages
-}
-
-copy_tree() {
-    set -e
-    set -o pipefail
-    echo "Copying current working tree for Docker image"
-    echo "============================================="
-    mkdir -p "${build_dir:?}"
-    # Just in case it's sitting there from a previous run
-    rm -rf "${build_dir}/scion.git/"
-    git ls-files | rsync -a --files-from=- . "${build_dir}/scion.git/"
-    echo
-}
-
-docker_build() {
-    set -e
-    set -o pipefail
-    local suffix="$1"
-    local image_name="scion${suffix:+_$suffix}"
-    local conf_rel="docker/Dockerfile${suffix:+.$suffix}"
-    local conf="${build_dir:?}/scion.git/$conf_rel"
-    local tag="$image_name:${image_tag:?}"
-    local log="$build_dir/build${suffix:+_$suffix}.log"
-    [ -n "$suffix" ] || local build_args="--build-arg SCION_UID=$(id -u) --build-arg SCION_GID=$(id -g) --build-arg DOCKER_GID=$(getent group docker | cut -f3 -d:) --build-arg GIT_VERSION=$(./tools/git-version) --build-arg GIT_TAG=$(git tag -l --points-at HEAD)"
-    echo "Building ${suffix:+$suffix }Docker image"
-    echo "=========================="
-    echo "Image: $tag"
-    echo "Config: $conf_rel"
-    echo "Log: $log"
-    echo "=========================="
-    echo
-    docker build $DOCKER_ARGS -f "$conf" -t "$tag" $build_args "$build_dir/scion.git" | tee "$log"
-    docker tag "$tag" "$image_name:latest"
-    touch docker/_build/scion.stamp
-}
-
-cmd_clean() {
-    if [ -z "$1" -o "$1" = "cntrs" ]; then
-        stop_cntrs
-        del_cntrs
-    fi
-    [ -z "$1" -o "$1" = "images" ] && del_imgs
-    rm -rf docker/_build/
-}
-
-common_args() {
-    local args="-h scion $DOCKER_ARGS"
-    args+=" -v /var/run/docker.sock:/var/run/docker.sock"
-    args+=" -v $SCION_MOUNT/gen:/home/scion/go/src/github.com/scionproto/scion/gen"
-    args+=" -v $SCION_MOUNT/logs:/home/scion/go/src/github.com/scionproto/scion/logs"
-    args+=" -v $SCION_MOUNT/gen-certs:/home/scion/go/src/github.com/scionproto/scion/gen-certs"
-    args+=" -v $SCION_MOUNT/gen-cache:/home/scion/go/src/github.com/scionproto/scion/gen-cache"
-    args+=" -v $SCION_MOUNT/traces:/home/scion/go/src/github.com/scionproto/scion/traces"
-    args+=" -v $SCION_MOUNT/htmlcov:/home/scion/go/src/github.com/scionproto/scion/python/htmlcov"
-    args+=" -v $SCION_MOUNT/metrics:/home/scion/go/src/github.com/scionproto/scion/metrics"
-    args+=" -e SCION_OUTPUT_BASE=$SCION_MOUNT"
-    args+=" -e SCION_UID=$(id -u)"
-    args+=" -e SCION_GID=$(id -g)"
-    args+=" -e SCION_PWD=${PWD}"
-    args+=" -e DOCKER_GID=$(getent group docker | cut -f3 -d:)"
-    args+=" -e SCION_USERSPEC=$(id -un):$(id -gn)"
-    args+=" -u root"
-    args+=" -e DOCKER0=$(./tools/docker-ip)"
-    echo $args
-}
-
-cmd_run() {
-    set -e
-    SCION_MOUNT=${SCION_MOUNT:-$(mktemp -d /tmp/scion_out.XXXXXX)}
-    echo "SCION_MOUNT directory: $SCION_MOUNT"
-    local img=${SCION_IMG:-scion}
-    local args=$(common_args)
-    args+=" -i -t --rm --entrypoint=/docker-entrypoint.sh"
-    setup_volumes
-    docker run $args "$img" "$@"
-}
-
-cmd_start() {
-    set -e
-    SCION_MOUNT=${SCION_MOUNT:-$(mktemp -d /tmp/scion_out.XXXXXX)}
-    echo "SCION_MOUNT directory: $SCION_MOUNT"
-    local img=${SCION_IMG:-scion}
-    local cntr=${SCION_CNTR:-scion}
-    if docker container inspect "$cntr" &>/dev/null; then
-        echo "Removing stale $cntr container"
-        ./tools/quiet docker rm -f "$cntr"
-    fi
-    local args=$(common_args)
-    args+=" --name $cntr"
-    setup_volumes
-    ./tools/quiet docker container create $args "$img" -c "tail -f /dev/null"
-    ./tools/quiet docker start "$cntr"
-    # Adjust ownership of mounted dirs
-    docker exec "$cntr" /docker-entrypoint.sh
-}
-
-cmd_exec() {
-    local cntr=${SCION_CNTR:-scion}
-    docker exec -it -u scion "$cntr" bash -l -c "$*"
-}
-
-cmd_stop() {
-    local cntr=${SCION_CNTR:-scion}
-    echo "Stopping $cntr container"; ./tools/quiet docker stop "$cntr";
-    echo "Removing $cntr container"; ./tools/quiet docker rm "$cntr";
-}
-
-setup_volumes() {
-    set -e
-    for i in gen logs gen-certs gen-cache traces htmlcov metrics; do
-        mkdir -p "$SCION_MOUNT/$i"
-        # Check dir exists, and is owned by the current (effective) user. If
-        # it's owned by the wrong user, the docker environment won't be able to
-        # write to it.
-        [ -O "$SCION_MOUNT/$i" ] || { echo "Error: '$SCION_MOUNT/$i' dir not owned by $LOGNAME"; exit 1; }
-    done
-    # Make sure the socket dirs have the correct permissions. Unlike for the volumes we try to fix
-    # the permissions if necessary.
-    local disp_dir="/run/shm/dispatcher"
-    [ -d "$disp_dir" ] || mkdir "$disp_dir"
-    [ $(stat -c "%U" "$disp_dir") == "$LOGNAME" ] || { sudo -p "Fixing ownership of $disp_dir - [sudo] password for %p: " chown $LOGNAME: "$disp_dir"; }
-    local sciond_dir="/run/shm/sciond"
-    [ -d "$sciond_dir" ] || mkdir "$sciond_dir"
-    [ $(stat -c "%U" "$sciond_dir") == "$LOGNAME" ] || { sudo -p "Fixing ownership of $sciond_dir - [sudo] password for %p: " chown $LOGNAME: "$sciond_dir"; }
-}
-
-stop_cntrs() {
-    local running
-    running=$(docker ps -q)
-    if [ -n "$running" ]; then
-        echo
-        echo "Stopping running containers"
-        echo "==========================="
-        docker stop $running
-    fi
-}
-
-del_cntrs() {
-    local stopped
-    stopped=$(docker ps -aq)
-    if [ -n "$stopped" ]; then
-        echo
-        echo "Deleting stopped containers"
-        echo "==========================="
-        docker rm $stopped
-    fi
-}
-
-del_imgs() {
-    local images
-    images=$(docker images | awk '/^<none>/ {print $3}')
-    if [ -n "$images" ]; then
-        echo
-        echo "Deleting unamed images"
-        echo "======================"
-        docker rmi $images
-    fi
-}
-
-cmd_help() {
-	cat <<-_EOF
-	Usage:
-	    $PROGRAM base
-	    $PROGRAM build
-	    $PROGRAM tester
-	    $PROGRAM run
-	        Run the Docker image.
-	    $PROGRAM start
-	        Start a Docker container.
-	    $PROGRAM exec
-	        Execute a command in a running container.
-	    $PROGRAM stop
-	        Stop the Docker container.
-	    $PROGRAM clean
-	        Remove all Docker containers and all generated images.
-	    $PROGRAM help
-	        Show this text.
-	_EOF
-}
-
-
-PROGRAM="${0##*/}"
-COMMAND="$1"
-ARG="$2"
-
-[ $(id -u) -eq 0 ] && { echo "Error: running as root is not allowed!" && exit 1; }
-
-if ! ( groups | grep -q "\<docker\>"; ); then
-    echo "Error: you must be in the 'docker' group"
-    exit 1
-fi
-
-if ! type -p docker &>/dev/null; then
-    echo "Error: you don't have docker installed. Please see docker/README.md"
-    exit 1
-fi
-
-case $COMMAND in
-    base)               cmd_base ;;
-    build)              cmd_build ;;
-    tester)             cmd_tester ;;
-    clean)              shift; cmd_clean "$@" ;;
-    run)                shift; cmd_run "$@" ;;
-    start)              cmd_start ;;
-    exec)               shift; cmd_exec "$@" ;;
-    stop)               shift; cmd_stop "$@" ;;
-    help)               cmd_help ;;
-    *)                  cmd_help ;;
-esac
diff --git a/docker/perapp/BUILD.bazel b/docker/BUILD.bazel
similarity index 50%
rename from docker/perapp/BUILD.bazel
rename to docker/BUILD.bazel
index 16a9011bb..8c6977676 100644
--- a/docker/perapp/BUILD.bazel
+++ b/docker/BUILD.bazel
@@ -1,23 +1,66 @@
 load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
 load(":scion_app.bzl", "scion_app_base", "scion_app_images")
+load(":tester.bzl", "build_tester_image")
+load(":sig_tester.bzl", "build_sigtester_image")
+
+container_bundle(
+    name = "prod",
+    images = {
+        "scion_border:latest": ":border_prod",
+        "scion_cs:latest": ":cs_prod",
+        "scion_dispatcher:latest": ":dispatcher_prod",
+        "scion_sciond:latest": ":sciond_prod",
+        "scion_sig_nocap:latest": ":sig_prod",
+    },
+)
+
+container_bundle(
+    name = "debug",
+    images = {
+        "scion_border_debug:latest": ":border_debug",
+        "scion_cs_debug:latest": ":cs_debug",
+        "scion_dispatcher_debug:latest": ":dispatcher_debug",
+        "scion_sciond_debug:latest": ":sciond_debug",
+        "scion_sig_nocap_debug:latest": ":sig_debug",
+    },
+)
+
+container_bundle(
+    name = "test",
+    images = {
+        "scion_sig_acceptance_nocap:latest": ":scion_sig_acceptance_nocap",
+        "scion_tester:latest": ":scion_tester",
+    },
+)
+
 
 scion_app_base()
+build_tester_image()
+build_sigtester_image()
 
 scion_app_images(
     name = "border",
-    binary = "//go/border:border",
     appdir = "/app",
+    binary = "//go/border:border",
+    entrypoint = [
+        "/app/border",
+        "-config",
+        "/share/conf/br.toml",
+    ],
     workdir = "/share",
-    entrypoint = ["/app/border", "-config", "/share/conf/br.toml"],
 )
 
 
 scion_app_images(
     name = "cs",
-    binary = "//go/cs:cs",
     appdir = "/app",
+    binary = "//go/cs:cs",
+    entrypoint = [
+        "/app/cs",
+        "-config",
+        "/share/conf/cs.toml",
+    ],
     workdir = "/share",
-    entrypoint = ["/app/cs", "-config", "/share/conf/cs.toml"],
 )
 
 scion_app_images(
@@ -34,39 +77,24 @@ scion_app_images(
 
 scion_app_images(
     name = "sciond",
-    binary = "//go/sciond:sciond",
     appdir = "/app",
+    binary = "//go/sciond:sciond",
+    entrypoint = [
+        "/app/sciond",
+        "-config",
+        "/share/conf/sd.toml",
+    ],
     workdir = "/share",
-    entrypoint = ["/app/sciond", "-config", "/share/conf/sd.toml"],
 )
 
 scion_app_images(
     name = "sig",
-    binary = "//go/sig:sig",
     appdir = "/app",
+    binary = "//go/sig:sig",
+    entrypoint = [
+        "/app/sig",
+        "-config",
+        "/share/conf/sig.toml",
+    ],
     workdir = "/share",
-    entrypoint = ["/app/sig", "-config", "/share/conf/sig.toml"],
-)
-
-# To generate the images: bazel run //docker/perapp:prod
-container_bundle(
-    name = "prod",
-    images = {
-        "scion_border:latest":     ":border_prod",
-        "scion_cs:latest":         ":cs_prod",
-        "scion_dispatcher:latest": ":dispatcher_prod",
-        "scion_sciond:latest":     ":sciond_prod",
-        "scion_sig_nocap:latest":  ":sig_prod",
-    },
-)
-
-container_bundle(
-    name = "debug",
-    images = {
-        "scion_border_debug:latest":     ":border_debug",
-        "scion_cs_debug:latest":         ":cs_debug",
-        "scion_dispatcher_debug:latest": ":dispatcher_debug",
-        "scion_sciond_debug:latest":     ":sciond_debug",
-        "scion_sig_nocap_debug:latest":  ":sig_debug",
-    },
 )
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index a903950ef..000000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM scion_base:latest
-ARG SCION_UID
-ARG SCION_GID
-ARG DOCKER_GID
-ARG GIT_VERSION
-ARG GIT_TAG
-
-ENV GIT_VERSION=${GIT_VERSION}
-ENV GIT_TAG=${GIT_TAG}
-
-# Make sure the scion user has the same UID/GID as the user on the host
-USER root
-RUN usermod -u ${SCION_UID:?} scion
-RUN groupmod -g ${SCION_GID:?} scion
-# Make sure the docker group has the same GID as the group on the host
-RUN groupmod -g ${DOCKER_GID:?} docker
-RUN find ~scion -not -user scion -execdir chown scion {} \+
-
-USER scion
-# Now copy over the current branch
-COPY --chown=scion:scion . $BASE/
-
-# Restore the python dependency cache from scion_base
-RUN tar xf /scioncache/python_local.tar.gz -C ~
-
-# Restore the cache of Bazel dependencies
-# Bazel creates timestamps 10 years in the future, so let's not warn about that.
-RUN tar xf /scioncache/bazel.tar.gz -C ~ --warning=no-timestamp
-
-# Make sure dependencies haven't been changed since scion_base was rebuilt
-RUN docker/deps_check
diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base
deleted file mode 100644
index b60fa9070..000000000
--- a/docker/Dockerfile.base
+++ /dev/null
@@ -1,92 +0,0 @@
-FROM ubuntu:16.04
-ENV HOME /home/scion
-ENV BASE /home/scion/go/src/github.com/scionproto/scion
-ENV GOPATH $HOME/go
-ENV PATH $HOME/bin:/usr/local/go/bin:$GOPATH/bin:$HOME/.local/bin:$PATH
-
-WORKDIR $BASE
-
-# Use eatmydata to speed up a lot of the building
-RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y eatmydata sudo && apt-get clean
-RUN set -ex; \
-    ln -s /usr/bin/eatmydata /usr/local/bin/apt-get; \
-    ln -s /usr/bin/eatmydata /usr/local/bin/dpkg; \
-    ln -s /usr/bin/eatmydata /usr/local/bin/pip; \
-    ln -s /usr/bin/eatmydata /usr/local/bin/pip3
-
-RUN useradd -u 30041 -s /bin/bash scion
-RUN groupadd -g 939 --system docker
-RUN usermod -aG docker scion
-RUN echo "scion ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/scion
-
-# Provide tmpfs at /run/shm while inside non-privileged docker
-RUN ln -s /dev/shm /run/shm
-
-USER scion
-RUN sudo chown -R scion: $HOME
-
-#################################################################################
-## Install dependencies
-#################################################################################
-
-COPY env/common.sh env/
-
-# Debian packages
-COPY env/debian env/debian
-RUN sudo apt-get update && APTARGS=-y env/debian/deps && sudo apt-get clean
-
-# Install Bazel
-COPY tools/install_bazel install_bazel
-RUN sudo ./install_bazel && rm install_bazel
-
-# Prepare a directory for caching
-RUN sudo mkdir -p /scioncache;
-
-# Pip packages
-COPY env/pip3 env/pip3
-RUN set -ex; \
-    env/pip3/deps; \
-    sudo tar czf /scioncache/python_local.tar.gz --owner=scion -C ~ .local; \
-    rm -r ~/.cache/pip ~/.local
-
-# Dependencies managed by Bazel.
-COPY WORKSPACE .
-COPY tool_deps.bzl .
-COPY go_deps.bzl .
-COPY tools/fetch.sh tools/
-RUN set -ex ; \
-    tools/fetch.sh > BUILD.bazel ; \
-    bazel fetch --noshow_progress //:fetch 2>&1 ; \
-    rm -rf /home/scion/.cache/bazel/_bazel_scion/*/external/*/\.git ; \
-    sudo tar czf /scioncache/bazel.tar.gz --owner=scion -C ~ .cache/bazel; \
-    sudo rm -r ~/.cache/bazel; \
-    sudo rm -r ./*
-
-# Install docker and docker-compose
-COPY tools/install_docker install_docker
-RUN sudo ./install_docker && rm install_docker && sudo usermod -aG docker scion
-
-# Install su-exec
-ARG SU_EXEC_COMMIT=e9664105e1f0b48024e52f454c6b78d15b5daa57
-RUN set -ex; mkdir su-exec; \
-    curl -sSL https://github.com/anapaya/su-exec/archive/${SU_EXEC_COMMIT}.tar.gz | tar xz -C su-exec --strip-components=1; \
-    make -C su-exec; sudo mv su-exec/su-exec /sbin/; \
-    rm -r su-exec;
-
-#################################################################################
-## Dependencies are now installed, carry on with the rest.
-#################################################################################
-
-# Install bash config
-COPY docker/profile $HOME/.profile
-# Install basic screen config
-COPY docker/screenrc $HOME/.screenrc
-
-# Fix ownership one last time. Chown is an expensive operation in terms of docker
-# image size so chown only the files that belong to different users.
-RUN sudo find $HOME -not -user scion -execdir chown scion {} \+
-
-COPY docker/docker-entrypoint.sh /
-
-CMD []
-ENTRYPOINT ["/bin/bash", "-l"]
diff --git a/docker/Makefile b/docker/Makefile
new file mode 100644
index 000000000..c05d68468
--- /dev/null
+++ b/docker/Makefile
@@ -0,0 +1,21 @@
+.PHONY: clean apps debug prod test
+
+apps: prod test
+
+debug:
+	bazel run -c dbg //docker:debug
+	docker image build -t "scion_sig_debug:latest" -f dockerfiles/sig.debug .
+	docker image remove scion_sig_nocap_debug
+
+prod:
+	bazel run -c opt //docker:prod
+	docker image build -t "scion_sig:latest" -f dockerfiles/sig.prod .
+	docker image remove scion_sig_nocap
+
+test:
+	bazel run //docker:test
+	docker build -t "scion_sig_acceptance:latest" -f dockerfiles/sig_accept .
+	docker image remove scion_sig_acceptance_nocap scionproto/docker-caps
+
+clean:
+	docker image ls --filter reference=scion* -q | xargs docker image rm
diff --git a/docker/README.md b/docker/README.md
deleted file mode 100644
index f94938b31..000000000
--- a/docker/README.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# SCION Docker testing image
-
-This directory, along with the top-level docker.sh script and Dockerfile, provide a hermetic build
-and test environment for SCION.
-
-The docker image is a basic ubuntu environment, with your git working tree, and all scion
-dependencies installed. A full build from scratch will take 5-10mins on a fast machine with a
-decent net connection. Subsequent rebuilds are much faster; if you haven't changed `env/`, a
-rebuild takes <= 15s.
-
-The `scion_base` docker image contains all the dependencies of scion, and so it needs to be
-regenerated any time the dependencies change. It is built via:
-
-```bash
-./docker.sh base
-```
-
-The `scion` docker image contains a snapshot of your working tree, and is layered on top of the
-`scion_base` image (and hence should be rebuilt if `scion_base` changes). It is built via:
-
-```bash
-./docker.sh build
-```
-
-To run the `scion` docker image:
-
-```bash
-./docker.sh run
-```
-
-This will drop you into a bash shell, in a stripped down ubuntu environment. Your current working
-tree has been copied into the image **at build time**. First build and create a topology
-`make -s; ./scion.sh topology`, then you can use `./scion.sh run` to start the SCION processes.
-
-If you would like to execute commands from the outside of the container, use
-
-```bash
-./docker.sh start
-./docker.sh exec CMD
-./docker.sh stop
-```
-
-`./docker.sh` `run` and `start` will mount the `gen`, `logs` and `gen-certs` directories from a
-temp directory. You can pass your own directory with `SCION_MOUNT`.
-
-```bash
-SCION_MOUNT=/tmp/scion_out ./docker.sh run "./scion.sh"
-```
-
-or
-
-```bash
-SCION_MOUNT=/tmp/scion_out ./docker.sh start
-./docker.sh exec ./scion.sh topology -d
-./docker.sh exec ./integration/integration_test.sh
-./docker.sh stop
-```
-
-Make sure you collect any relevant data from the container before running `./docker.sh stop` as
-this stops and removes the container. The temp directory will still be available.
-
-See `./docker.sh help` for further commands/usage.
-
-## Notes
-
-- As `docker.sh` copies your _working tree_, if you're trying to test a commit before sending for
-  review/etc, make sure your working directory is clean before building the image. Any new files
-  must be at least added to git, even if you haven't committed them, otherwise docker.sh will skip
-  them.
diff --git a/docker/deps_check b/docker/deps_check
deleted file mode 100755
index d58d85c44..000000000
--- a/docker/deps_check
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-ret=0
-
-check() {
-    echo "Check: $@"
-    # If a check errors, exit immediately.
-    output=$("$@") || { echo "ERROR: non-zero result"; exit 1; }
-    if [ -n "$output" ]; then
-        # If a `check` produced any output, count it as a failure.
-        ret=$((ret+1))
-        echo "$output"
-    fi
-}
-
-for f in env/*/check; do
-    check "$f"
-done
-
-if [ $ret -ne 0 ]; then
-    echo "============================================================"
-    echo "ERROR: outdated dependencies, scion_base needs to be rebuilt"
-    echo "============================================================"
-fi
-exit $ret
diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh
deleted file mode 100755
index 66b522d10..000000000
--- a/docker/docker-entrypoint.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# Change the current uid to SCION_UID, gid to SCION_GID and fix file permissions
-if [ $SCION_UID -ne $(id -u scion) ] || [ $SCION_GID -ne $(id -g scion) ]; then
-    echo "Run chown on ~scion"
-    chown -R ${SCION_UID:?}:${SCION_GID:?} ~scion
-fi
-if [ $SCION_UID -ne $(id -u scion) ]; then
-    echo "Run usermod scion"
-    usermod -u ${SCION_UID:?} scion
-fi
-if [ $SCION_GID -ne $(id -g scion) ]; then
-    echo "Run groupmod scion"
-    groupmod -g ${SCION_GID:?} scion
-fi
-if [ $DOCKER_GID -ne $(getent group docker | cut -f3 -d:) ]; then
-    # Change docker gid to DOCKER_GID
-    echo "Run groupmod docker"
-    groupmod -g ${DOCKER_GID:?} docker
-fi
-
-SU_EXEC_USERSPEC=scion /sbin/su-exec bash -l "$@"
diff --git a/docker/perapp/Makefile b/docker/perapp/Makefile
deleted file mode 100644
index ad71d348e..000000000
--- a/docker/perapp/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-DOCKER_ARGS += --no-cache
-ifndef DEBUG
-DOCKER_ARGS += -q
-endif
-
-ALL_TARGETS = base apps debug
-.PHONY: $(ALL_TARGETS)
-all: $(ALL_TARGETS)
-hashes/scion: ../_build/scion.stamp
-	./docker_hash scion
-
-.PHONY: clean
-clean:
-	@rm -f hashes/*; \
-	for i in $(APP_TARGETS) $(BASE_TARGETS) $(DEBUG_TARGETS); do \
-		./remove_image $$i latest; \
-	done; \
-	docker image prune -f
-
-# Base images
-BASE_TARGETS = app_builder
-.PHONY: $(BASE_TARGETS)
-base: $(BASE_TARGETS)
-
-app_builder: hashes/app_builder
-hashes/app_builder: base/Dockerfile.builder hashes/scion
-	DOCKER_ARGS="$(DOCKER_ARGS)" ./docker_build $@ $< files/
-
-# App images
-APP_TARGETS = bazel
-.PHONY: $(APP_TARGETS)
-apps: $(APP_TARGETS)
-
-bazel:
-	./build-images.sh prod
-	DOCKER_ARGS="$(DOCKER_ARGS)" ./docker_build hashes/sig app/Dockerfile.sig
-
-# Debug images
-DEBUG_TARGETS = bazel_debug
-.PHONY: $(DEBUG_TARGETS)
-debug: $(DEBUG_TARGETS)
-
-bazel_debug:
-	./build-images.sh debug
-	DOCKER_ARGS="$(DOCKER_ARGS)" ./docker_build hashes/sig_debug debug/Dockerfile.sig
diff --git a/docker/perapp/README.md b/docker/perapp/README.md
deleted file mode 100644
index 1cde2535f..000000000
--- a/docker/perapp/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Per-application Docker images for SCION
-
-Per-application Docker images for SCION
-
-## Images
-
-- Build base images {app_builder, debug}: `make base`
-- Build app images: `make apps`
-- Build debug images: `make debug`
-
-Build all images: `make all`. Build bazel images: `make bazel`.
-
-### Base Images
-
-- app_builder: Contains compiled app binaries
-- debug: `strace` and toybox
-
-### App Images
-
-Following the list of images built by Bazel:
-
-- border: Runs `/app/border`
-- beacon_srv: Runs `/app/beacon_srv`
-- cert_srv: Runs `/app/cert_srv`
-- dispatcher: Runs `/app/dispatcher`
-- path_srv: Runs `/app/path_srv`
-- sciond: Runs `/app/sciond`
-- sig: Runs `/app/sig`
-
-### Debug images
-
-One image for each of the base and app images, combined with the debug image.
-
-## Running environment (and su-exec)
-
-There are several constraints in how the images work:
-
-1. Containers shouldn't run as root, or have suid binaries in them.
-1. File-based access is needed when running to connect to the dispatcher, read config
-   files, write logs, etc. This means the container needs to run as a specific user in
-   order to have the correct permissions.
-1. The dispatcher socket needs to be available to processes running directly on the
-   host (e.g. `scmp`, `showpaths -p`). This means we can't run everything in a
-   docker volume independant of the host environment.
-1. The user (i.e. uid+gid(s)) that the container process will run as is not known at
-   build time, because it depends on the host environment it is deployed on top of.
-
-The simple approach would be to do something like this:
-
-```bash
-docker run -v /etc/passwd:/etc/passwd -v /etc/group:/etc/group -u $LOGNAME <image>
-```
-
-Unfortunately the `-u` flag takes effect before the volumes get mounted, causing
-the user change to fail.
-
-This is solved by using [su-exec](https://github.com/anapaya/su-exec) as the entrypoint.
-`su-exec` runs as `root`, after docker has finished creating the container. This means
-the volumes are already mounted. `su-exec` reads from the `SU_EXEC_USERSPEC` environment
-variable (in the form `user[:group]`), changes to the specified user/group, and then
-exec's its cmdline arguments (in this case the image's service binary).
-
-```bash
-docker run -v /etc/passwd:/etc/passwd -v /etc/group:/etc/group -e SU_EXEC_USERSPEC=$LOGNAME <image>
-```
diff --git a/docker/perapp/base/Dockerfile.builder b/docker/perapp/base/Dockerfile.builder
deleted file mode 100644
index f0e87f4fa..000000000
--- a/docker/perapp/base/Dockerfile.builder
+++ /dev/null
@@ -1,3 +0,0 @@
-FROM scion:latest
-COPY bazelrc.quiet ~/.bazelrc
-RUN make -s GODEPS_SKIP=1 GOGEN_SKIP=1 all setcap && bazel clean
diff --git a/docker/perapp/build-images.sh b/docker/perapp/build-images.sh
deleted file mode 100755
index 85e75a3a0..000000000
--- a/docker/perapp/build-images.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-# This tools builds the perapp images.
-
-set -ex
-
-ROOTDIR=$(dirname "$0")/../..
-
-STAGE=${1:-prod}
-
-# Build the binaries.
-# This will fetch everything that haven't been fetched yet.
-bazel build //:scion
-
-# Build the images and push them to local docker repository.
-bazel run //docker/perapp:$STAGE
diff --git a/docker/perapp/docker_build b/docker/perapp/docker_build
deleted file mode 100755
index 3b9a41295..000000000
--- a/docker/perapp/docker_build
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -e
-
-target="$(basename ${1:?})"
-shift
-dfile="${1:?}"
-shift
-src="${1}"
-
-img="scion_$target"
-tag="$img:latest"
-
-if [ -n "$src" ]; then
-    # Allowing out of build context Dockerfile for 17.06+
-    # see https://github.com/docker/compose/issues/4926#issuecomment-343002431
-    docker build -t "$tag" $DOCKER_ARGS -f - "$src" < "$dfile"
-else
-    docker build -t "$tag" $DOCKER_ARGS - < "$dfile"
-fi
-./docker_hash "$img"
diff --git a/docker/perapp/docker_hash b/docker/perapp/docker_hash
deleted file mode 100755
index a34a08d9c..000000000
--- a/docker/perapp/docker_hash
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -e
-
-mkdir -p hashes
-
-img="${1}"
-out="hashes/${1#scion_}"
-tag="$img:latest"
-
-h="$(docker image ls "$tag" --format '{{ .ID }}')"
-if [ ! -f "$out" ] || [ "$h" != "$(cat "$out")" ]; then
-    echo "$h" > "$out"
-    echo "$out updated to $h"
-else
-    echo "$out up to date"
-fi
diff --git a/docker/perapp/files/bazelrc.quiet b/docker/perapp/files/bazelrc.quiet
deleted file mode 100644
index dc91d9920..000000000
--- a/docker/perapp/files/bazelrc.quiet
+++ /dev/null
@@ -1,2 +0,0 @@
-build --noshow_progress --color=no
-fetch --noshow_progress --color=no
diff --git a/docker/perapp/files/copy_package b/docker/perapp/files/copy_package
deleted file mode 100755
index e8be55016..000000000
--- a/docker/perapp/files/copy_package
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -ex
-[ -d /rootfs ] || mkdir /rootfs
-files=$(dpkg -L $1)
-if [ -n "$2" ]; then
-    files=$(dpkg -L $1 | grep -v $2)
-fi
-copyright=/usr/share/doc/"$1"/copyright
-if [ -e "$copyright" ]; then
-    mkdir -p /rootfs/LICENSES/"$1"
-    cp "$copyright" /rootfs/LICENSES/"$1"/
-fi
-for f in $files /etc/services; do
-    [ ! -d "$f" ] || continue
-    dir="/rootfs$(dirname "$f")"
-    mkdir -p "$dir"
-    cp -a "$f" "$dir/"
-done
diff --git a/docker/perapp/publish b/docker/perapp/publish
deleted file mode 100755
index 2bc02856f..000000000
--- a/docker/perapp/publish
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-REMOTE="scionproto"
-
-echo "Tag: ${1:-}"
-
-images="border dispatcher sig beacon cert path sciond"
-
-# Tag local apps and push to remote
-for app in $images; do
-    local_img="scion_$app"
-    remote_img="$REMOTE/$app"
-    docker tag "$local_img:latest" "$remote_img:$1"
-    docker tag "${local_img}_debug:latest" "${remote_img}_debug:$1"
-    docker push "$remote_img:$1"
-    docker push "${remote_img}_debug:$1"
-done
diff --git a/docker/perapp/remove_image b/docker/perapp/remove_image
deleted file mode 100755
index 3d9feb691..000000000
--- a/docker/perapp/remove_image
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-set -e
-
-image="scion_${1:?}:${2:?}"
-
-if [ -n "$(docker images -q $image)" ]; then
-    echo "Deleting image: $image"
-    echo "======================"
-    docker rmi "$image"
-fi
diff --git a/docker/profile b/docker/profile
deleted file mode 100644
index 7f670407d..000000000
--- a/docker/profile
+++ /dev/null
@@ -1,9 +0,0 @@
-export GOPATH="$HOME/go"
-export PATH="$HOME/.local/bin:$GOPATH/bin:/usr/local/go/bin:$PATH"
-export SHELL
-export BASEDIR="$GOPATH/src/github.com/scionproto/scion"
-export PYTHONPATH="$BASEDIR/python/:$BASEDIR"
-export USER=scion
-export LOGNAME=scion
-
-alias cdscion="cd $BASEDIR"
diff --git a/docker/perapp/scion_app.bzl b/docker/scion_app.bzl
similarity index 90%
rename from docker/perapp/scion_app.bzl
rename to docker/scion_app.bzl
index 17c6d8f2b..ac030204e 100644
--- a/docker/perapp/scion_app.bzl
+++ b/docker/scion_app.bzl
@@ -64,7 +64,8 @@ def scion_app_base():
 #   appdir - the directory to deploy the binary to
 #   workdir - working directory
 #   entrypoint - a list of strings that add up to the command line
-def scion_app_images(name, binary, appdir, workdir, entrypoint):
+#   stamp - whether to stamp the created images (default=True).
+def scion_app_images(name, binary, appdir, workdir, entrypoint, stamp=True):
     pkg_tar(
         name = name + "_docker_files",
         srcs = [binary],
@@ -75,21 +76,21 @@ def scion_app_images(name, binary, appdir, workdir, entrypoint):
     container_image(
         name = name + "_prod",
         repository = "scion",
-        base = "//docker/perapp:app_base",
+        base = "//docker:app_base",
         tars = [":" + name + "_docker_files"],
         workdir = workdir,
         entrypoint = ["/sbin/su-exec"] + entrypoint,
-        stamp = True,
+        stamp = stamp,
         visibility = ["//visibility:public"],
     )
 
     container_image(
         name = name + "_debug",
         repository = "scion",
-        base = "//docker/perapp:app_base_debug",
+        base = "//docker:app_base_debug",
         tars = [":" + name + "_docker_files"],
         workdir = workdir,
         entrypoint = entrypoint,
-        stamp = True,
+        stamp = stamp,
         visibility = ["//visibility:public"],
     )
diff --git a/docker/screenrc b/docker/screenrc
deleted file mode 100644
index 8cf0bf414..000000000
--- a/docker/screenrc
+++ /dev/null
@@ -1,4 +0,0 @@
-shell bash
-startup_message off
-hardstatus alwayslastline
-hardstatus string "%-w%{= BW}%50>%n %t%{-}%+w%< %=%{= ck}A%{-}"
diff --git a/go/lib/integration/integration.go b/go/lib/integration/integration.go
index 03cddcb3e..bc6f9a4b2 100644
--- a/go/lib/integration/integration.go
+++ b/go/lib/integration/integration.go
@@ -40,7 +40,7 @@ import (
 
 const (
 	// StartServerTimeout is the timeout for starting a server.
-	StartServerTimeout = 20 * time.Second
+	StartServerTimeout = 40 * time.Second
 	// DefaultRunTimeout is the timeout when running a server or a client.
 	DefaultRunTimeout = 8 * time.Second
 	// CtxTimeout is the timeout a context waits before being killed
diff --git a/integration/BUILD.bazel b/integration/BUILD.bazel
index 2d5c046e2..c32762877 100644
--- a/integration/BUILD.bazel
+++ b/integration/BUILD.bazel
@@ -1,5 +1,1 @@
-filegroup(
-    name = "bin_wrapper_script",
-    srcs = ["bin_wrapper.sh"],
-    visibility = ["//visibility:public"],
-)
+exports_files(["bin_wrapper.sh"])
diff --git a/scion.sh b/scion.sh
index b64ef537b..009d9091f 100755
--- a/scion.sh
+++ b/scion.sh
@@ -54,9 +54,9 @@ cmd_run() {
         make -s || exit 1
         if is_docker_be; then
             echo "Build perapp images"
-            ./tools/quiet make -C docker/perapp bazel
+            ./tools/quiet make -C docker prod
             echo "Build scion tester"
-            ./tools/quiet ./docker.sh tester
+            ./tools/quiet make -C docker test
         fi
     fi
     run_setup
diff --git a/tools/fetch.sh b/tools/fetch.sh
deleted file mode 100755
index e2f8ae8c8..000000000
--- a/tools/fetch.sh
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/bin/bash
-
-# This script will create a fake BUILD.bazel file that
-# can be used to fetch all external dependencies.
-# After the file is generated and stored along the WORKSPACE
-# do "bazel fetch //:fetch" to actually dowload the repos.
-
-set -e
-
-ROOTDIR=$(dirname "$0")/..
-
-extra_import() {
-    # For dependencies listed below the go code is in a sub folder.
-    # All go_repositories which don't have go code in the root folder must be
-    # listed here. Otherwise the fetching doesn't work.
-    case "$1" in
-        com_github_antlr_antlr4)
-            echo "runtime/Go/antlr" ;;
-        com_github_beorn7_perks)
-            echo "histogram" ;;
-        com_github_golang_mock)
-            echo "gomock" ;;
-        com_github_google_go_cmp)
-            echo "cmp" ;;
-        com_github_matttproud_golang_protobuf_extensions)
-            echo "ext" ;;
-        com_github_oncilla_gochecks)
-            echo "serrorscheck" ;;
-        com_github_pierrec_xxhash)
-            echo "xxhsum" ;;
-        com_github_prometheus_client_golang)
-            echo "prometheus" ;;
-        com_github_prometheus_common)
-            echo "model" ;;
-        com_github_syndtr_gocapability)
-            echo "capability" ;;
-        org_golang_x_crypto)
-            echo "acme" ;;
-        com_github_buildkite_go_buildkite)
-            echo "buildkite" ;;
-        com_github_google_go_querystring)
-            echo "query" ;;
-        com_github_uber_jaeger_lib)
-            echo "metrics" ;;
-        com_github_sergi_go_diff)
-            echo "diffmatchpatch" ;;
-        org_golang_x_net)
-            echo "ipv4" ;;
-        org_golang_x_sys)
-            echo "unix" ;;
-        org_golang_x_sync)
-            echo "semaphore" ;;
-        org_golang_x_tools)
-            echo "go/packages" ;;
-        com_github_pmezard_go_difflib)
-            echo "difflib" ;;
-        com_github_bazelbuild_buildtools)
-            echo "build" ;;
-        *)
-            echo "" ;;
-    esac
-}
-
-# Add any bazel packages to prefetch to the beginning of the following block.
-cat <<EOF
-load("@com_github_jmhodges_bazel_gomock//:gomock.bzl", "gomock")
-load("@io_bazel_rules_go//go:def.bzl", "nogo")
-
-nogo(
-    name = "nogo",
-    visibility = ["//visibility:public"],
-)
-
-genrule(
-    name = "fetch",
-    outs = ["dummy"],
-    cmd = "touch dummy",
-    tools = [
-        "@debian_stretch//file:Packages.json",
-        "@package_bundle//file:packages.bzl",
-EOF
-
-for q in $(bazel query "kind('go_repository rule', //external:*)" --noshow_progress); do
-    # Ignore some indirect test dependencies (will not be used) that would require extra_import for fetching
-    if echo $q | grep -qF -e "com_github_jmhodges_bazel_gomock" \
-                          -e "com_github_tinylib_msgp" \
-                          -e "com_github_kylelemons_godebug" \
-                          -e "com_github_gopherjs_gopherjs" \
-                          -e "com_github_golang_protobuf" \
-                          -e "com_github_gogo_protobuf" \
-                          -e "com_github_go_kit_kit" \
-                          -e "com_github_davecgh_go_spew" \
-                          -e "com_github_cloudflare_sidh" \
-                          -e "org_golang_google_appengine" \
-                          -e "com_github_google_go_containerregistry" \
-                          -e "com_github_onsi_ginkgo" \
-                          -e "com_github_onsi_gomega"
-    then
-        continue
-    fi
-    if [[ $q == //external* ]]; then
-        dep_name=${q#//external:} # remove "//external:" in front.
-        extra=$(extra_import $dep_name)
-        echo "        \"@$dep_name//$extra:go_default_library\","
-    fi
-done
-
-cat <<EOF
-    ]
-)
-EOF


Test patch:
diff --git a/docker/perapp/debug/Dockerfile.sig b/docker/dockerfiles/sig.debug
similarity index 100%
rename from docker/perapp/debug/Dockerfile.sig
rename to docker/dockerfiles/sig.debug
diff --git a/docker/perapp/app/Dockerfile.sig b/docker/dockerfiles/sig.prod
similarity index 100%
rename from docker/perapp/app/Dockerfile.sig
rename to docker/dockerfiles/sig.prod
diff --git a/docker/testimages/Dockerfile.sig_accept b/docker/dockerfiles/sig_accept
similarity index 100%
rename from docker/testimages/Dockerfile.sig_accept
rename to docker/dockerfiles/sig_accept
diff --git a/docker/testimages/sig.sh b/docker/files/sig.sh
similarity index 100%
rename from docker/testimages/sig.sh
rename to docker/files/sig.sh
diff --git a/docker/testimages/tester.sh b/docker/files/tester.sh
similarity index 96%
rename from docker/testimages/tester.sh
rename to docker/files/tester.sh
index 33dd6406c..00d7e8bde 100644
--- a/docker/testimages/tester.sh
+++ b/docker/files/tester.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-set -ex
+set -e
 
 if [ -n "$REMOTE_NETS" ] && [ -n "$SIG_IP" ]; then
     for net in $(echo $REMOTE_NETS | tr , ' '); do
diff --git a/docker/sig_tester.bzl b/docker/sig_tester.bzl
new file mode 100644
index 000000000..bcc5146e4
--- /dev/null
+++ b/docker/sig_tester.bzl
@@ -0,0 +1,40 @@
+load("@rules_pkg//:pkg.bzl", "pkg_tar")
+load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_bundle")
+load("@package_bundle//file:packages.bzl", "packages")
+
+def build_sigtester_image():
+
+    pkg_tar(
+        name = "sig_entrypoint",
+        srcs = ["files/sig.sh"],
+        package_dir = "/share",
+    )
+
+    container_image(
+        name = "scion_sig_acceptance_nocap",
+        base = "@ubuntu16//image",
+        env = {"TZ": "UTC"},
+        debs = [
+            packages["libc6"],
+            # needed by su-exec
+            packages["libgcc1"],
+            packages["libstdc++6"],
+            # needed for sig.sh
+            # ping and its dependencies
+            packages["iputils-ping"],
+            packages["libidn11"],
+            packages["libnettle6"],
+            # iproute2 and its dependencies
+            packages["iproute2"],
+            packages["libelf1"],
+            packages["libmnl0"],
+        ],
+        tars = [
+            ":app_base_files",
+            ":sig_docker_files",
+            ":sig_entrypoint",
+
+        ],
+        workdir = "/share",
+        entrypoint = ["./sig.sh"],
+    )
diff --git a/docker/tester.bzl b/docker/tester.bzl
new file mode 100644
index 000000000..57b5815c0
--- /dev/null
+++ b/docker/tester.bzl
@@ -0,0 +1,59 @@
+load("@rules_pkg//:pkg.bzl", "pkg_tar")
+load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_bundle")
+load("@package_bundle//file:packages.bzl", "packages")
+
+def build_tester_image():
+
+    pkg_tar(
+        name = "bin",
+        srcs = [
+            "//go/integration/cert_req:cert_req",
+            "//go/integration/end2end:end2end",
+            "//go/examples/pingpong:pingpong",
+            "//go/tools/scmp:scmp",
+            "//go/tools/showpaths:showpaths",
+        ],
+        package_dir="bin",
+    )
+
+    pkg_tar(
+        name = "integration",
+        srcs = [
+            "//integration:bin_wrapper.sh",
+        ],
+        package_dir = "integration",
+    )
+
+    pkg_tar(
+        name = "share",
+        deps = [
+            ":bin",
+            ":integration",
+        ],
+        srcs = [
+            "files/tester.sh",
+        ],
+        package_dir = "share",
+    )
+
+    container_image(
+        name = "scion_tester",
+        base = "@ubuntu16//image",
+        env = {"TZ": "UTC"},
+        debs = [
+            packages["libc6"],
+            # ping and its dependencies
+            packages["iputils-ping"],
+            packages["libidn11"],
+            packages["libnettle6"],
+            # iproute2 and its dependencies
+            packages["iproute2"],
+            packages["libelf1"],
+            packages["libmnl0"],
+        ],
+        tars = [
+            ":share",
+        ],
+        workdir = "/share",
+        cmd = "tail -f /dev/null",
+    )
diff --git a/docker/testimages/BUILD.bazel b/docker/testimages/BUILD.bazel
deleted file mode 100644
index 90c4c886c..000000000
--- a/docker/testimages/BUILD.bazel
+++ /dev/null
@@ -1,130 +0,0 @@
-load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
-load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_bundle")
-load("@package_bundle//file:packages.bzl", "packages")
-
-pkg_tar(
-    name = "app_base_files",
-    srcs = [
-        "@com_github_anapaya_su_exec//:su-exec",
-    ],
-    remap_paths = {
-        "": "sbin",
-    },
-    mode = "0755",
-)
-
-pkg_tar(
-    name = "sig_docker_files",
-    srcs = ["//go/sig:sig"],
-    package_dir = "/app",
-)
-
-filegroup(
-    name = "sig_entrypoint_files",
-    srcs = ["sig.sh"],
-)
-
-pkg_tar(
-    name = "sig_entrypoint",
-    srcs = [":sig_entrypoint_files"],
-    package_dir = "/share",
-)
-
-container_image(
-    name = "scion_sig_acceptance_nocap",
-    base = "@ubuntu16//image",
-    env = {"TZ": "UTC"},
-    debs = [
-        packages["libc6"],
-        # needed by su-exec
-        packages["libgcc1"],
-        packages["libstdc++6"],
-        # needed for sig.sh
-        # ping and its dependencies
-        packages["iputils-ping"],
-        packages["libidn11"],
-        packages["libnettle6"],
-        # iproute2 and its dependencies
-        packages["iproute2"],
-        packages["libelf1"],
-        packages["libmnl0"],
-    ],
-    tars = [
-        ":app_base_files",
-        ":sig_docker_files",
-        ":sig_entrypoint",
-
-    ],
-    workdir = "/share",
-    entrypoint = ["./sig.sh"],
-)
-
-filegroup(
-    name = "tester_setup_script",
-    srcs = ["tester.sh"],
-)
-
-pkg_tar(
-    name = "tester_shared_scripts",
-    srcs = [
-        ":tester_setup_script",
-    ],
-    package_dir = "/share",
-)
-
-pkg_tar(
-    name = "tester_integration_scripts",
-    srcs = [
-        "//integration:bin_wrapper_script",
-    ],
-    package_dir = "/share/integration",
-)
-
-pkg_tar(
-    name = "tester_binaries",
-    srcs = [
-        "//go/integration/cert_req:cert_req",
-        "//go/integration/end2end:end2end",
-        "//go/examples/pingpong:pingpong",
-        "//go/tools/scmp:scmp",
-        "//go/tools/showpaths:showpaths",
-    ],
-    package_dir="/share/bin",
-)
-
-container_image(
-    name = "scion_tester",
-    base = "@ubuntu16//image",
-    env = {"TZ": "UTC"},
-    debs = [
-        packages["libc6"],
-        # needed by su-exec
-        packages["libgcc1"],
-        packages["libstdc++6"],
-        # needed for tester.sh
-        # ping and its dependencies
-        packages["iputils-ping"],
-        packages["libidn11"],
-        packages["libnettle6"],
-        # iproute2 and its dependencies
-        packages["iproute2"],
-        packages["libelf1"],
-        packages["libmnl0"],
-    ],
-    tars = [
-        ":app_base_files",
-        ":tester_shared_scripts",
-        ":tester_integration_scripts",
-        ":tester_binaries",
-    ],
-    workdir = "/share",
-    cmd = "tail -f /dev/null"
-)
-
-container_bundle(
-    name = "scion_testing_bundle",
-    images = {
-        "scion_sig_acceptance_nocap:latest": ":scion_sig_acceptance_nocap",
-        "scion_tester:latest": ":scion_tester",
-    },
-)