Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud
Serverless Migration Station is a video mini-series from Serverless Expeditions focused on helping developers modernize their applications running on a serverless compute platform from Google Cloud. Previous episodes demonstrated how to migrate away from the older, legacy App Engine (standard environment) services to newer Google Cloud standalone equivalents like Cloud Datastore. Today's product crossover episode differs slightly from that by migrating away from App Engine altogether, containerizing those apps for Cloud Run.
There's little question the industry has been moving towards containerization as an application deployment mechanism over the past decade. However, Docker and use of containers weren't available to early App Engine developers until its flexible environment became available years later. Fast forward to today where developers have many more options to choose from, from an increasingly open Google Cloud. Google has expressed long-term support for App Engine, and users do not need to containerize their apps, so this is an optional migration. It is primarily for those who have decided to add containerization to their application deployment strategy and want to explicitly migrate to Cloud Run.
If you're thinking about app containerization, the video covers some of the key reasons why you would consider it: you're not subject to traditional serverless restrictions like development language or use of binaries (flexibility); if your code, dependencies, and container build & deploy steps haven't changed, you can recreate the same image with confidence (reproducibility); your application can be deployed elsewhere or be rolled back to a previous working image if necessary (reusable); and you have plenty more options on where to host your app (portability).
Legacy App Engine services are available through a set of proprietary, bundled APIs. As you can surmise, those services are not available on Cloud Run. So if you want to containerize your app for Cloud Run, it must be "ready to go," meaning it has migrated to either Google Cloud standalone equivalents or other third-party alternatives. For example, in a recent episode, we demonstrated how to migrate from App Engine ndb to Cloud NDB for Datastore access.
While we've recently begun to produce videos for such migrations, developers can already access code samples and codelab tutorials leading them through a variety of migrations. In today's video, we have both Python 2 and 3 sample apps that have divested from legacy services, thus ready to containerize for Cloud Run. Python 2 App Engine apps accessing Datastore are most likely to be using Cloud NDB whereas it would be Cloud Datastore for Python 3 users, so this is the starting point for this migration.
Because we're "only" switching execution platforms, there are no changes at all to the
application code itself. This entire migration is completely based on changing the apps'
configurations from App Engine to Cloud Run. In particular, App Engine artifacts such as
app.yaml
, appengine_config.py
, and the
lib
folder are not used in Cloud Run and will be removed. A
Dockerfile
will be implemented to build your container. Apps with
more complex configurations in their app.yaml
files will likely need
an equivalent service.yaml
file for Cloud Run — if so, you'll find
this
app.yaml to service.yaml conversion tool handy. Following best practices means
there'll also be a .dockerignore
file.
App Engine and Cloud Functions are sourced-based where Google Cloud automatically provides a
default HTTP server like gunicorn
. Cloud Run is a bit more "DIY"
because users have to provide a container image, meaning bundling our own server. In this
case, we'll pick gunicorn
explicitly, adding it to the top of the
existing requirements.txt
required packages file(s), as you can see
in the screenshot below. Also illustrated is the Dockerfile
where
gunicorn
is started to serve your app as the final step. The only
differences for the Python 2 equivalent Dockerfile
are: a) require
the Cloud NDB package (google-cloud-ndb
)
instead of Cloud Datastore, and b) start with a Python 2 base image.
The Python 3 requirements.txt
and
Dockerfile
To walk developers through migrations, we always "START" with a working app then make the necessary updates that culminate in a working "FINISH" app. For this migration, the Python 2 sample app STARTs with the Module 2a code and FINISHes with the Module 4a code. Similarly, the Python 3 app STARTs with the Module 3b code and FINISHes with the Module 4b code. This way, if something goes wrong during your migration, you can always rollback to START, or compare your solution with our FINISH. If you are considering this migration for your own applications, we recommend you try it on a sample app like ours before considering it for yours. A corresponding codelab leading you step-by-step through this exercise is provided in addition to the video which you can use for guidance.
All migration modules, their videos (when published), codelab tutorials, START and FINISH
code, etc., can be found in the migration
repo. We hope to also one day cover other legacy runtimes like Java 8 so stay tuned.
We'll continue with our journey from App Engine to Cloud Run ahead in Module 5 but will do so
without explicit knowledge of containers, Docker, or Dockerfile
s.
Modernizing your development workflow to using containers and best practices like crafting a
CI/CD pipeline isn't always straightforward; we hope content like this helps you progress in
that direction!