Add production docker-compose.yml for the backend

Change-Id: Iea13f31fcb0887f4b8dad4c36dec5a434df0c673
diff --git a/README.md b/README.md
index fec0c12..82d91ca 100644
--- a/README.md
+++ b/README.md
@@ -8,11 +8,28 @@
 production.
 
 ## Frontend
-To serve the frontend, follow these instructions:
+To serve the frontend for development, follow these instructions:
 
 1. Run `docker-compose -f docker-compose.dev.yml up` to start the gRPC API,
 database and Envoy proxy (which will translate gRPC-Web <-> gRPC).
-1. Run `mysql -u root twpt < schema/*.sql`.
+1. Run `docker exec -i twpt-server_db_1 mysql -u root twpt < schema/common.sql`
+and `docker exec -i twpt-server_db_1 mysql -u root twpt < schema/kill-switch.sql`.
+1. Run `docker exec -it twpt-server_db_1 mysql -u root twpt` and enter the
+following SQL sentence with your data to create the first authorized user:
+`INSERT INTO KillSwitchAuthorizedUser (google_uid, email, access_level) VALUES ('', '{YOUR_EMAIL_ADDRESS}', 10);`.
 1. Run `docker-compose -f docker-compose.dev.yml restart`.
 1. Run `npm install`.
 1. Run `make serve`.
+
+## Backend
+You can run the backend for development purposes by running `go run .` in the
+`//cmd/serve` folder. You may also build its docker image to allow it to
+interact with the frontend (since it needs Envy (the gRPC-Web proxy) to
+translate between gRPC and HTTP requests).
+
+## Deploying
+Use the `docker-compose.yml` file instead of `docker-compose.dev.yml` and follow
+steps 1-4 from the "frontend" section to spin up the backend.
+
+For the frontend, run `make deploy` in the `//frontend` folder to deploy the
+frontend to Firebase.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..3e19820
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,33 @@
+version: "3"
+
+services:
+  envoy:
+    build:
+      context: ./docker/envoy
+    image: twpt-server/envoy
+    ports:
+      - "10123:8081"
+    depends_on:
+      - server
+    networks:
+      - backend
+  server:
+    build:
+      context: .
+      dockerfile: ./cmd/server/Dockerfile
+    image: twpt-server/golang-server
+    entrypoint: ["/sbin/tini", "--", "/server", "--db=root:@tcp(db)/twpt", "--port=10000"]
+    depends_on:
+      - db
+    networks:
+      - backend
+  db:
+    image: mariadb
+    environment:
+      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
+      MARIADB_DATABASE: twpt
+    networks:
+      - backend
+
+networks:
+  backend:
diff --git a/docker/envoy/Dockerfile b/docker/envoy/Dockerfile
new file mode 100644
index 0000000..a2c877b
--- /dev/null
+++ b/docker/envoy/Dockerfile
@@ -0,0 +1,5 @@
+FROM envoyproxy/envoy:v1.18-latest
+
+COPY envoy.yaml /etc/envoy/envoy.yaml
+
+CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml -l trace --log-path /tmp/envoy_info.log
diff --git a/docker/envoy/envoy.yaml b/docker/envoy/envoy.yaml
new file mode 100644
index 0000000..16df6f3
--- /dev/null
+++ b/docker/envoy/envoy.yaml
@@ -0,0 +1,54 @@
+static_resources:
+  listeners:
+  - name: listener_0
+    address:
+      socket_address: { address: 0.0.0.0, port_value: 8081 }
+    filter_chains:
+    - filters:
+      - name: envoy.filters.network.http_connection_manager
+        typed_config:
+          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+          use_remote_address: false # NOTE: This is because in our production setup we're using a reverse proxy.
+                                    # If you're exposing your backend to the public, set this to true.
+          codec_type: auto
+          stat_prefix: ingress_http
+          route_config:
+            name: local_route
+            virtual_hosts:
+            - name: local_service
+              domains: ["*"]
+              routes:
+              - match: { prefix: "/" }
+                route:
+                  cluster: echo_service
+                  timeout: 0s
+                  max_stream_duration:
+                    grpc_timeout_header_max: 0s
+              cors:
+                allow_origin_string_match:
+                - prefix: "https://twpt-dashboard.avm99963.com"
+                - prefix: "https://twpt-dashboard-frontend.web.app"
+                allow_methods: GET, PUT, DELETE, POST, OPTIONS
+                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout,authorization
+                max_age: "1728000"
+                expose_headers: custom-header-1,grpc-status,grpc-message
+          http_filters:
+          - name: envoy.filters.http.grpc_web
+          - name: envoy.filters.http.cors
+          - name: envoy.filters.http.router
+  clusters:
+  - name: echo_service
+    connect_timeout: 3s
+    type: logical_dns
+    http2_protocol_options: {}
+    lb_policy: round_robin
+    dns_lookup_family: V4_ONLY
+    load_assignment:
+      cluster_name: cluster_0
+      endpoints:
+        - lb_endpoints:
+            - endpoint:
+                address:
+                  socket_address:
+                    address: server
+                    port_value: 10000