sandbox: use debian:jessie, add filesystem test, make image smaller

1. Don't use FROM golang, this gives more control over the versions that
are used.

2. Compress calls into one layer and remove bootstrap after it's used,
along with other unnecessary files. Saves about 500 MiB:
playground/sandbox                         703.3 MB
us.gcr.io/golang-org/appengine/sandbox.17  1.216 GB

I think more work can be done here.

3. Add a test for the fake filesystem.

Change-Id: I04d849c8bb81c67545e5528820df2838bfecff2f
Reviewed-on: https://go-review.googlesource.com/27237
Reviewed-by: Jessica Frazelle <me@jessfraz.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/sandbox/Dockerfile b/sandbox/Dockerfile
index 4cb00d6..43be725 100644
--- a/sandbox/Dockerfile
+++ b/sandbox/Dockerfile
@@ -2,36 +2,58 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-FROM golang:1.7
+FROM debian:jessie
 
-RUN apt-get update && apt-get install -yq --no-install-recommends patch bzip2
+ENV GOPATH /go
+ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
+ENV GOROOT_BOOTSTRAP /usr/local/gobootstrap
+ENV GO_VERSION 1.7
 
-# enable faketime
-ADD enable-fake-time.patch /usr/local/go/
-RUN patch /usr/local/go/src/runtime/rt0_nacl_amd64p32.s /usr/local/go/enable-fake-time.patch
+# Fake time
+COPY enable-fake-time.patch /usr/local/sandbox/
+# Fake file system
+COPY fake_fs.lst /usr/local/sandbox/
 
-# add fake file system
-ADD fake_fs.lst /usr/local/go/
-RUN cd /usr/local/go && go run misc/nacl/mkzip.go -p syscall fake_fs.lst src/syscall/fstest_nacl.go
+RUN set -x && buildDeps='curl ca-certificates bzip2'; \
+    apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \
+    curl -s https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/44.0.2403.157/naclsdk_linux.tar.bz2 | tar -xj -C /usr/local/bin --strip-components=2 pepper_44/tools/sel_ldr_x86_64 && \
+    apt-get purge -y --auto-remove $buildDeps
 
-# Install go1.4 ss $HOME/go1.4 (the default location), as we need it to build
-# Go 1.5+. We can't just use the existing Go installation to bootstrap, as the
-# first thing make.bash does is clean the existing binaries.
-RUN curl https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz | tar -xz -C /root && mv /root/go /root/go1.4
+RUN set -x && buildDeps='curl ca-certificates gcc patch libc6-dev'; \
+    apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \
+# Get the Go binary.
+    curl -sSL https://storage.googleapis.com/golang/go$GO_VERSION.linux-amd64.tar.gz -o /tmp/go.tar.gz && \
+    curl -sSL https://storage.googleapis.com/golang/go$GO_VERSION.linux-amd64.tar.gz.sha256 -o /tmp/go.tar.gz.sha256 && \
+    echo "$(cat /tmp/go.tar.gz.sha256)  /tmp/go.tar.gz" | sha256sum -c - && \
+    tar -C /usr/local/ -vxzf /tmp/go.tar.gz && \
+    rm /tmp/go.tar.gz /tmp/go.tar.gz.sha256 && \
 
-# Build the Go nacl tool chain.
-RUN cd /usr/local/go/src && GOOS=nacl GOARCH=amd64p32 ./make.bash --no-clean
-RUN curl -s https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/44.0.2403.157/naclsdk_linux.tar.bz2 | tar -xj -C /usr/local/bin --strip-components=2 pepper_44/tools/sel_ldr_x86_64
+# Make a copy for GOROOT_BOOTSTRAP, because we rebuild the toolchain and make.bash removes bin/go as its first step.
+    cp -R /usr/local/go $GOROOT_BOOTSTRAP && \
 
-# add and compile tour packages
-RUN GOOS=nacl GOARCH=amd64p32 go get \
-	golang.org/x/tour/pic \
-	golang.org/x/tour/reader \
-	golang.org/x/tour/tree \
-	golang.org/x/tour/wc \
-	golang.org/x/talks/2016/applicative/google
+# Apply the fake time and fake filesystem patches.
+    patch /usr/local/go/src/runtime/rt0_nacl_amd64p32.s /usr/local/sandbox/enable-fake-time.patch && \
+    cd /usr/local/go && go run misc/nacl/mkzip.go -p syscall /usr/local/sandbox/fake_fs.lst src/syscall/fstest_nacl.go && \
 
-# add tour packages under their old import paths (so old snippets still work)
+# Re-build the Go toolchain.
+    cd /usr/local/go/src && GOOS=nacl GOARCH=amd64p32 ./make.bash --no-clean && \
+    rm -rf $GOROOT_BOOTSTRAP
+
+# Add and compile tour packages
+RUN set -x && buildDeps='git'; \
+    apt-get update && apt-get install -y $buildDeps --no-install-recommends && rm -rf /var/lib/apt/lists/* && \
+    GOOS=nacl GOARCH=amd64p32 go get \
+    golang.org/x/tour/pic \
+    golang.org/x/tour/reader \
+    golang.org/x/tour/tree \
+    golang.org/x/tour/wc \
+    golang.org/x/talks/2016/applicative/google && \
+    rm -rf $GOPATH/src/golang.org/x/tour/.git && \
+    rm -rf $GOPATH/src/golang.org/x/talks/.git && \
+    apt-get purge -y --auto-remove $buildDeps
+
+
+# Add tour packages under their old import paths (so old snippets still work)
 RUN mkdir -p $GOPATH/src/code.google.com/p/go-tour && \
 	cp -R $GOPATH/src/golang.org/x/tour/* $GOPATH/src/code.google.com/p/go-tour/ && \
 	sed -i 's_// import_// public import_' $(find $GOPATH/src/code.google.com/p/go-tour/ -name *.go) && \
@@ -41,11 +63,11 @@
 		code.google.com/p/go-tour/tree \
 		code.google.com/p/go-tour/wc
 
-# add and compile sandbox daemon
-ADD . /go/src/sandbox/
+# Add and compile sandbox daemon
+COPY . /go/src/sandbox/
 RUN go install sandbox
 
-# make sure it works
+# Run tests
 RUN /go/bin/sandbox test
 
 EXPOSE 8080
diff --git a/sandbox/sandbox.go b/sandbox/sandbox.go
index 0c562dc..69ca24f 100644
--- a/sandbox/sandbox.go
+++ b/sandbox/sandbox.go
@@ -292,4 +292,37 @@
     println("test")
 }
 `, want: "", errors: "package name must be main"},
+	{prog: `
+package main
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+func main() {
+	filepath.Walk("/", func(path string, info os.FileInfo, err error) error {
+		fmt.Println(path)
+		return nil
+	})
+}
+`, want: `/
+/dev
+/dev/null
+/dev/random
+/dev/urandom
+/dev/zero
+/etc
+/etc/group
+/etc/hosts
+/etc/passwd
+/etc/resolv.conf
+/tmp
+/usr
+/usr/local
+/usr/local/go
+/usr/local/go/lib
+/usr/local/go/lib/time
+/usr/local/go/lib/time/zoneinfo.zip`},
 }