1. Overview
    1. Services must listen for requests on the port defined by the PORT environment variable
    2. The service must be stateless. Service cannot rely on a persistent local state
    3. The service must not perform background activities outside the scope of request handling
    4. Cloud Run allows code to be written in the programming language
    5. Use a web server to listen on the required port, and process and route incoming requests
    6. To deploy to Cloud Run, users need to provide a container image
    7. A container image is a packaging format that includes code, its packages, any needed binary dependencies, the operating system to use, and anything else needed to run your service
    8. A file named Dockerfile is commonly used to declare how to build the container image
    9. Custom binaries must be compiled for Linux ABI x86_64
  2. Writing services
    1. When an application running on Cloud Run finishes handling a request, the container instance's access to CPU will be disabled or severely limited
    2. Do not start background threads or routines that run outside the scope of the request handlers
    3. Running background threads can result in unexpected behavior because any subsequent request to the same container instance resumes any suspended background activity
    4. Background activity is anything that happens after HTTP response has been delivered
    5. Review code to make sure all asynchronous operations finish before a response is delivered
    6. Check logs for background activity that maybe not readily apparent, and for anything that is logged after the entry for the HTTP request
    7. In the Cloud Run (fully managed) environment disk storage is an in-memory filesystem
    8. Files written to disk consume memory otherwise available to service, and can persist between invocations
    9. Failing to delete files can eventually lead to an out-of-memory error and a subsequent cold start
    10. Handle all exceptions and do not let service crash on errors
    11. A crash leads to a cold start while traffic is queued for a replacement container instance
  3. Optimizing performance
    1. Because container instances are scaled as needed, a typical method to improve performance is to initialise the execution environment completely
    2. This kind of initialisation is called "cold start"
    3. If a client request triggers a cold start, the container instance startup results in additional latency
    4. Optimizing for service startup speed minimizes the latency that delays a container instance from serving requests
    5. When using a dynamic language with dependent libraries, such as importing modules in Node.js, the load time for modules adds latency during a cold start
    6. Reduce startup latency by minimize the number and size of dependencies to build a lean service
    7. Reduce startup latency by lazily loading code that is infrequently used, if language supports it
    8. Reduce startup latency by using code-loading such as PHP's composer autoloader optimization
    9. In Cloud Run, users cannot assume that service state is preserved between requests
    10. Cloud Run reuses individual container instances to serve ongoing traffic, so users can declare a variable in global scope to allow its value to be reused in subsequent invocations
    11. Whether any individual request receives the benefit of this reuse cannot be known ahead of time
    12. Users can also cache objects in memory if they are expensive to recreate on each service request
    13. Moving this from the request logic to global scope results in better performance
    14. The initialization of global variables always occurs during startup, which increases cold start time
    15. Use lazy initialization for infrequently used objects to defer the time cost and decrease cold start times
    16. A larger container image size increases security vulnerability because more code is a larger attack surface
    17. Large images slow build time for container image while many files are downloaded
    18. Large images results in slower deployment time for service as the container image is prepared for use in a new revision
    19. It increases network egress costs with Container Registry if container storage bucket is geographically distant from service region
    20. On Cloud Run, the size of container image does not affect cold start or request processing time and does not count towards the available memory of container
    21. To build a minimal container, consider working off a lean base image such as alpine, distroless or scratch
    22. Ubuntu is larger in size, but is a commonly used base image with a more complete out-of-box server environment
    23. If service has a tool-heavy build process consider using multi-stage builds to keep container light at run time
    24. Cloud Run supports configurable concurrency
    25. Cloud Functions does not support concurrency
    26. Enable a service's container instances to serve multiple requests simultaneously, that is, "concurrently"
    27. The number of concurrent requests that each container instance can serve is limited by the technology stack and the use of shared resources like global variables and database connections
    28. Each service request requires some amount of additional memory
    29. When adjusting concurrency up or down, adjust memory limit as well
    30. To leverage mutable global state in a concurrent context, take extra steps in code to ensure this is done safely
    31. Minimize contention by limiting global variables to one-time initialization and reuse as described above under Performance
    32. When using mutable global variables in a service that serves multiple requests at the same time, use locks or mutexes to prevent race conditions
  4. Container security
    1. Use actively maintained and secure base images such as Container Registry's managed base images. or Docker Hub's official images
    2. Apply security updates to services by regularly rebuilding container images and redeploying your services
    3. Include in the container only what is necessary to run service.
    4. Extra code, packages, and tools are potential security vulnerabilities
    5. Implement a deterministic build process that includes specific software and library versions
    6. This prevents unverified code from being included in container
    7. Set container to run as a user other than root with the Dockerfile USER statement
    8. Some container images may already have a specific user configured
    9. Enable the Container Registry image vulnerability scanner for security scanning of container images stored in the Container Registry
    10. If using Cloud Run for Anthos on Google Cloud, use Binary Authorization to ensure only secure container images are deployed