add Makefile and Dockerfile

Add the Dockerfile that builds the worker docker image.

Add a Makefile for testing the image.

Change-Id: I440e3f0e000130fb4f5901a8017b9816af46c493
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/468304
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Maceo Thompson <maceothompson@google.com>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6ca0649
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+**/.terraform/*
+.terraform.lock.hcl
+go-image.tar.gz
+go-vulndb
+config.json
+docker-build
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3a34eb5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,70 @@
+# Copyright 2023 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Makefile for common tasks.
+
+default:
+	@echo "usage: make TARGET"
+
+# Copy a gzipped tar of a Go docker image from a bucket.
+# The file must live in the repo directory so that cmd/worker/Dockerfile
+# can access it.
+# We assume that the file exists in the bucket. It can be created with
+#   docker export $(shell docker create golang:1.19.4) | gzip
+go-image.tar.gz:
+	gsutil cp gs://go-ecosystem/$@ $@
+
+# Download the Go vulnerability DB to a local directory, so vulndb can access it
+# from the sandbox, which has no network connectivity.
+#
+# Get the last-modified time of the index.json file, which is reported as the
+# last-modified time of the DB, and save it to a local file. (The last-modified
+# time of the local index.json is not what we want: it is the time that gsutil cp
+# wrote the file.)
+#
+# This directory must live in the repo directory so that cmd/worker/Dockerfile
+# can access it.
+go-vulndb:
+	gsutil -m -q cp -r gs://go-vulndb .
+	gsutil stat gs://go-vulndb/index.json | \
+		awk '$$1 == "Update" { for (i = 4; i <= NF; i++) printf("%s ", $$i); printf("\n"); }' \
+		> go-vulndb/LAST_MODIFIED
+
+# Remove comments from a json file.
+%.json: %.json.commented
+	sed '/^[ \t]*#/d' $< > $@
+
+IMAGE := ecosystem-worker-test
+
+# Build a docker image for testing.
+# This target is a local file that marks the time of the last
+# docker build. We use a file because make uses only local file timestamps to determine
+# whether a target needs to be regenerated.
+docker-build: go-image.tar.gz go-vulndb cmd/worker/*.go internal/**/*.go cmd/vulncheck_sandbox/* config.json cmd/worker/Dockerfile
+	docker build -f cmd/worker/Dockerfile -t $(IMAGE) . \
+          --build-arg DOCKER_IMAGE=$(IMAGE) \
+          --build-arg BQ_DATASET=disable
+	touch $@
+
+# Run the docker image locally, for testing.
+docker-run: docker-build
+	docker run --rm --privileged -p 8080:8080 $(IMAGE)
+
+# Run the docker image in the background, waiting until the server is ready.
+docker-run-bg: docker-build
+	docker run --detach --rm --privileged -p 8080:8080 $(IMAGE) > /tmp/ecosystem-docker-container-id
+	while ! curl -s --head http://localhost:8080 > /dev/null; do sleep 1; done
+
+# Test by scanning a small module.
+test: docker-run-bg
+	curl -s 'http://localhost:8080/test-vulncheck-sandbox/github.com/fossas/fossa-cli@v1.1.10?importedby=1' | grep GO-2020-0016
+	docker container stop `cat /tmp/ecosystem-docker-container-id`
+
+clean:
+	rm -f go-image.tar.gz
+	rm -rf go-vulndb
+	rm -f config.json
+	rm -f vulncheck_sandbox
+
+.PHONY: docker-run docker-run-bg test clean
diff --git a/cmd/worker/Dockerfile b/cmd/worker/Dockerfile
new file mode 100644
index 0000000..5a6df8f
--- /dev/null
+++ b/cmd/worker/Dockerfile
@@ -0,0 +1,90 @@
+# Copyright 2023 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This Dockerfile expects the build context to be the repo root.
+
+# To test that the worker built with this Dockerfile runs, run
+#   make test
+# from the repo root.
+
+FROM golang:1.19.4
+
+LABEL maintainer="Go Ecosystem Team <go-ecosystem-team@google.com>"
+
+#### Preliminaries
+
+WORKDIR /
+
+# Create some directories.
+# Binaries run inside the sandbox live here.
+RUN mkdir -p /bundle/rootfs/binaries
+# The worker binary and related files live here.
+RUN mkdir app
+# The module being analyzed is unzipped here.
+# The sandbox mounts this directory.
+RUN mkdir module
+
+#### Building binaries
+
+# Set the working directory outside $GOPATH to ensure module mode is enabled.
+WORKDIR /src
+
+# Copy go.mods and go.sums into the container.
+# If they don't change, which is the common case, then docker can
+# cache these COPYs and the subsequent RUN.
+COPY go.mod go.sum checks.bash ./
+
+# Copy the repo from local machine into Docker client’s current working
+# directory, so that we can use it to build the binary.
+# See .dockerignore at the repo root for excluded files.
+COPY . /src
+
+# Download the dependencies.
+RUN go mod download
+
+# Build the worker binary and put it in /app.
+RUN go build -mod=readonly -o /app/worker ./cmd/worker
+
+# Build the program that runs vulncheck inside the sandbox and install it in the sandbox's
+# binaries directory.
+RUN go build -mod=readonly -o /bundle/rootfs/binaries/vulncheck_sandbox ./cmd/vulncheck_sandbox
+
+# Build the sandbox runner program and put it in the bundle root.
+RUN go build -mod=readonly -o /bundle/rootfs/runner ./internal/sandbox/runner.go
+
+#### Sandbox setup
+
+# Install runsc.
+ADD https://storage.googleapis.com/gvisor/releases/release/20221107.0/x86_64/runsc /usr/local/bin/
+RUN chmod a+rx /usr/local/bin/runsc
+
+# Set up for runsc.
+# runsc expects a directory called a "bundle" that contains a config.json
+# file and an OS filesystem.
+
+# Create the runsc bundle.
+WORKDIR /bundle
+COPY config.json .
+
+# go-image.tar.gz is a complete Docker image of a Go installation in tar format.
+# Use it for the bundle's OS filesystem.
+COPY go-image.tar.gz .
+RUN tar --same-owner -pxzf go-image.tar.gz -C rootfs
+
+# Copy the downloaded copy of the vuln DB into the bundle root.
+COPY go-vulndb rootfs/go-vulndb
+
+#### Worker setup
+
+WORKDIR /app
+
+COPY static		static
+
+ARG DOCKER_IMAGE
+ENV DOCKER_IMAGE=$DOCKER_IMAGE
+
+ARG BQ_DATASET
+ENV GO_METRICS_BIGQUERY_DATASET=$BQ_DATASET
+
+CMD ["./worker"]