diff --git a/Dockerfile b/Dockerfile
new file mode 100755
index 0000000000000000000000000000000000000000..ea0d23a3dc28a6118bcf3ac9744ce64fc478d894
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,32 @@
+#	Copyright 2015, Google, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# [START docker]
+
+# The Google App Engine python runtime is Debian Jessie with Python installed
+# and various os-level packages to allow installation of popular Python
+# libraries. The source is on github at:
+# https://github.com/GoogleCloudPlatform/python-docker
+FROM gcr.io/google_appengine/python
+
+# Create a virtualenv for the application dependencies.
+# # If you want to use Python 2, use the -p python2.7 flag.
+RUN virtualenv -p python3 /env
+ENV PATH /env/bin:$PATH
+
+ADD requirements.txt /app/requirements.txt
+RUN /env/bin/pip install --upgrade pip && /env/bin/pip install -r /app/requirements.txt
+ADD . /app
+
+CMD gunicorn -b :$PORT mysite.wsgi
+# [END docker]
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000000000000000000000000000000000000..a06da05cc66b2d22086a7ad526c6a3571fbf37d3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,39 @@
+GCLOUD_PROJECT:=$(shell gcloud config list project --format="value(core.project)")
+
+.PHONY: all
+all: deploy
+
+.PHONY: create-cluster
+create-cluster:
+	gcloud container clusters create polls \
+		--scopes "https://www.googleapis.com/auth/userinfo.email","cloud-platform"
+
+.PHONY: create-bucket
+create-bucket:
+	gsutil mb gs://$(GCLOUD_PROJECT)
+	gsutil defacl set public-read gs://$(GCLOUD_PROJECT)
+
+.PHONY: build
+build:
+	docker build -t gcr.io/$(GCLOUD_PROJECT)/polls .
+
+.PHONY: push
+push: build
+	gcloud docker push -- gcr.io/$(GCLOUD_PROJECT)/polls
+
+.PHONY: template
+template:
+	sed -i ".tmpl" "s/\$$GCLOUD_PROJECT/$(GCLOUD_PROJECT)/g" polls.yaml
+
+.PHONY: deploy
+deploy: push template
+	kubectl create -f polls.yaml
+
+.PHONY: update
+update:
+	kubectl patch deployment polls -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
+
+.PHONY: delete
+delete:
+	kubectl delete rc polls
+	kubectl delete service polls
diff --git a/README.md b/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d45703e2b8ddb3de756ff70d3e678dc31ba269a 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,26 @@
+# Getting started with Django on Google Container Engine
+
+[![Open in Cloud Shell][shell_img]][shell_link]
+
+[shell_img]: http://gstatic.com/cloudssh/images/open-btn.png
+[shell_link]: https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/python-docs-samples&page=editor&open_in_editor=container_engine/django_tutorial/README.md
+
+This repository is an example of how to run a [Django](https://www.djangoproject.com/) 
+app on Google Container Engine. It uses the
+[Writing your first Django app](https://docs.djangoproject.com/en/1.11/intro/tutorial01/)
+Polls application (parts 1 and 2) as the example app to deploy. From here on
+out, we refer to this app as the 'polls' application.
+
+
+# Tutorial
+See our [Django on Container Engine](https://cloud.google.com/python/django/container-engine) tutorial for instructions for setting up and deploying this sample application.
+
+
+## Contributing changes
+
+* See [CONTRIBUTING.md](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/CONTRIBUTING.md)
+
+
+## Licensing
+
+* See [LICENSE](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/LICENSE)
diff --git a/__init__.py b/__init__.py
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/manage.py b/manage.py
new file mode 100755
index 0000000000000000000000000000000000000000..2062ecd2666d174a81e1e9c71126fed937f800eb
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)
diff --git a/mysite/__init__.py b/mysite/__init__.py
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/mysite/settings.py b/mysite/settings.py
new file mode 100755
index 0000000000000000000000000000000000000000..bdcb39913e9c86c531041f95eb48273af313e606
--- /dev/null
+++ b/mysite/settings.py
@@ -0,0 +1,115 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+import os
+
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'pf-@jxtojga)z+4s*uwbgjrq$aep62-thd0q7f&o77xtpka!_m'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+# SECURITY WARNING: If you deploy a Django app to production, make sure to set
+# an appropriate host here.
+# See https://docs.djangoproject.com/en/1.10/ref/settings/
+ALLOWED_HOSTS = ['*']
+
+# Application definition
+
+INSTALLED_APPS = (
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'polls'
+)
+
+MIDDLEWARE = (
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+)
+
+ROOT_URLCONF = 'mysite.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'mysite.wsgi.application'
+
+# Database
+# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
+
+# [START dbconfig]
+DATABASES = {
+    'default': {
+        # If you are using Cloud SQL for MySQL rather than PostgreSQL, set
+        # 'ENGINE': 'django.db.backends.mysql' instead of the following.
+        'ENGINE': 'django.db.backends.postgresql',
+        'NAME': 'polls',
+        'USER': os.getenv('DATABASE_USER'),
+        'PASSWORD': os.getenv('DATABASE_PASSWORD'),
+        'HOST': '127.0.0.1',
+        'PORT': '5432',
+    }
+}
+# [END dbconfig]
+
+# Internationalization
+# https://docs.djangoproject.com/en/1.8/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.8/howto/static-files/
+
+# [START staticurl]
+STATIC_URL = '/static/'
+# STATIC_URL = 'https://storage.googleapis.com/<your-gcs-bucket>/static/'
+# [END staticurl]
+
+STATIC_ROOT = 'static/'
diff --git a/mysite/urls.py b/mysite/urls.py
new file mode 100755
index 0000000000000000000000000000000000000000..bbb417c431e5f6dbff3466c8911d344c68233762
--- /dev/null
+++ b/mysite/urls.py
@@ -0,0 +1,29 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.conf import settings
+from django.contrib import admin
+from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+from django.urls import include, path
+
+
+urlpatterns = [
+    path('admin/', admin.site.urls),
+    path('', include('polls.urls')),
+]
+
+# Only serve static files from Django during development
+# Use Google Cloud Storage or an alternative CDN for production
+if settings.DEBUG:
+    urlpatterns += staticfiles_urlpatterns()
diff --git a/mysite/wsgi.py b/mysite/wsgi.py
new file mode 100755
index 0000000000000000000000000000000000000000..bd3a0d0c2b71afda19f90c92c54c25c94c187e0e
--- /dev/null
+++ b/mysite/wsgi.py
@@ -0,0 +1,22 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
+
+application = get_wsgi_application()
diff --git a/polls.yaml b/polls.yaml
new file mode 100755
index 0000000000000000000000000000000000000000..6ccc2d337b07f0de7432e7b9a9c49c864160b3b4
--- /dev/null
+++ b/polls.yaml
@@ -0,0 +1,114 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+# This file configures the polls application . The frontend serves
+# public web traffic.
+
+# The bookshelf frontend replication controller ensures that at least 3
+# instances of the bookshelf app are running on the cluster.
+# For more info about Pods see:
+#   https://cloud.google.com/container-engine/docs/pods/
+# For more info about Deployments:
+#   https://kubernetes.io/docs/user-guide/deployments/
+
+# [START kubernetes_deployment]
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: polls
+  labels:
+    app: polls
+spec:
+  replicas: 3
+  template:
+    metadata:
+      labels:
+        app: polls
+    spec:
+      containers:
+      - name: polls-app
+        # Replace  with your project ID or use `make template`
+        image: gcr.io/<your-project-id>/polls
+        # This setting makes nodes pull the docker image every time before
+        # starting the pod. This is useful when debugging, but should be turned
+        # off in production.
+        imagePullPolicy: Always
+        env:
+            # [START cloudsql_secrets]
+            - name: DATABASE_USER
+              valueFrom:
+                secretKeyRef:
+                  name: cloudsql
+                  key: username
+            - name: DATABASE_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: cloudsql
+                  key: password
+            # [END cloudsql_secrets]
+        ports:
+        - containerPort: 8080
+
+      # [START proxy_container]
+      - image: gcr.io/cloudsql-docker/gce-proxy:1.05
+        name: cloudsql-proxy
+        command: ["/cloud_sql_proxy", "--dir=/cloudsql",
+                  "-instances=<your-cloudsql-connection-string>=tcp:5432",
+                  "-credential_file=/secrets/cloudsql/credentials.json"]
+        volumeMounts:
+          - name: cloudsql-oauth-credentials
+            mountPath: /secrets/cloudsql
+            readOnly: true
+          - name: ssl-certs
+            mountPath: /etc/ssl/certs
+          - name: cloudsql
+            mountPath: /cloudsql
+      # [END proxy_container] 
+      # [START volumes]
+      volumes:
+        - name: cloudsql-oauth-credentials
+          secret:
+            secretName: cloudsql-oauth-credentials
+        - name: ssl-certs
+          hostPath:
+            path: /etc/ssl/certs
+        - name: cloudsql
+          emptyDir:
+      # [END volumes]        
+# [END kubernetes_deployment]
+
+---
+
+# [START service]
+# The polls service provides a load-balancing proxy over the polls app
+# pods. By specifying the type as a 'LoadBalancer', Container Engine will
+# create an external HTTP load balancer.
+# For more information about Services see:
+#   https://cloud.google.com/container-engine/docs/services/
+# For more information about external HTTP load balancing see:
+#   https://cloud.google.com/container-engine/docs/load-balancer
+apiVersion: v1
+kind: Service
+metadata:
+  name: polls
+  labels:
+    app: polls
+spec:
+  type: LoadBalancer
+  ports:
+  - port: 80
+    targetPort: 8080
+  selector:
+    app: polls
+# [END service]
diff --git a/polls/__init__.py b/polls/__init__.py
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/polls/admin.py b/polls/admin.py
new file mode 100755
index 0000000000000000000000000000000000000000..d0fde6f1f6e3be742f37bd80925240b53843262f
--- /dev/null
+++ b/polls/admin.py
@@ -0,0 +1,19 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.contrib import admin
+
+from .models import Question
+
+admin.site.register(Question)
diff --git a/polls/apps.py b/polls/apps.py
new file mode 100755
index 0000000000000000000000000000000000000000..6f98d05c893fc2f4a3b7954340a6580132676a70
--- /dev/null
+++ b/polls/apps.py
@@ -0,0 +1,19 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.apps import AppConfig
+
+
+class PollsConfig(AppConfig):
+    name = 'polls'
diff --git a/polls/migrations/0001_initial.py b/polls/migrations/0001_initial.py
new file mode 100755
index 0000000000000000000000000000000000000000..0609ba72f430670f080db8c73c0720ebddf894df
--- /dev/null
+++ b/polls/migrations/0001_initial.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2015-12-28 23:27
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Choice',
+            fields=[
+                ('id', models.AutoField(
+                    auto_created=True, primary_key=True, serialize=False,
+                    verbose_name='ID')),
+                ('choice_text', models.CharField(max_length=200)),
+                ('votes', models.IntegerField(default=0)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Question',
+            fields=[
+                ('id', models.AutoField(
+                    auto_created=True, primary_key=True, serialize=False,
+                    verbose_name='ID')),
+                ('question_text', models.CharField(max_length=200)),
+                ('pub_date', models.DateTimeField(
+                    verbose_name=b'date published')),
+            ],
+        ),
+        migrations.AddField(
+            model_name='choice',
+            name='question',
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                to='polls.Question'),
+        ),
+    ]
diff --git a/polls/migrations/__init__.py b/polls/migrations/__init__.py
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/polls/models.py b/polls/models.py
new file mode 100755
index 0000000000000000000000000000000000000000..c38f6e55c06c75fea0322597787d52988490cd61
--- /dev/null
+++ b/polls/models.py
@@ -0,0 +1,28 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.db import models
+
+
+class Question(models.Model):
+    question_text = models.CharField(max_length=200)
+    pub_date = models.DateTimeField('date published')
+
+
+class Choice(models.Model):
+    question = models.ForeignKey(Question, on_delete=models.CASCADE)
+    choice_text = models.CharField(max_length=200)
+    votes = models.IntegerField(default=0)
+
+# Create your models here.
diff --git a/polls/tests.py b/polls/tests.py
new file mode 100755
index 0000000000000000000000000000000000000000..d85408e51791f792f0270736a559fc31e2bb9f90
--- /dev/null
+++ b/polls/tests.py
@@ -0,0 +1,13 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/polls/urls.py b/polls/urls.py
new file mode 100755
index 0000000000000000000000000000000000000000..672ee5c879a669b17fc66dacfa75cc802f1f24e1
--- /dev/null
+++ b/polls/urls.py
@@ -0,0 +1,21 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.urls import path
+
+from . import views
+
+urlpatterns = [
+    path('', views.index, name='index')
+]
diff --git a/polls/views.py b/polls/views.py
new file mode 100755
index 0000000000000000000000000000000000000000..acc5671ba625cfd57c8d1b084a80971cb5461489
--- /dev/null
+++ b/polls/views.py
@@ -0,0 +1,19 @@
+# Copyright 2015 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from django.http import HttpResponse
+
+
+def index(request):
+    return HttpResponse("Hello, world. You're at the polls index.")
diff --git a/requirements.txt b/requirements.txt
new file mode 100755
index 0000000000000000000000000000000000000000..c19a8e2bed0a30e6f5f1e4436c64745cf0da5c6f
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+Django==2.1.5
+mysqlclient==1.4.1
+wheel==0.32.3
+gunicorn==19.9.0
+psycopg2==2.7.7