Create a custom layer

Updated at:

Layers provide shared dependency libraries, runtime environments, and function extensions for your functions. You can extract the common libraries that your functions depend on into a layer, or use Function Compute public layers, to reduce the size of the code package when you deploy or update a function. This topic describes how layers work, the directories that each runtime supports, how to build a layer ZIP file, and how to create and delete a custom layer.

How it works

When you build a layer, package all of its content into a ZIP file. At runtime, Function Compute extracts the layer content and deploys it to the /opt directory. When you configure multiple layers for a function, the layer content is merged into /opt in the reverse order in which the layers are configured. If a file in one layer has the same name as a file in another layer, the file in the layer that is configured first overwrites the file in the layer that is configured later.

For example, if you configure Layer 1 and Layer 2 for a function, the function instance loads Layer 2 first and then Layer 1 when it starts, and extracts both layers to the /opt directory. In /opt, the content of Layer 1 comes first and the content of Layer 2 comes second. If Layer 1 and Layer 2 contain files with the same name, the files in Layer 1 overwrite the files in Layer 2.

Build requirements:

  • If a layer contains binary libraries or executables, build it on Linux (Debian 9 recommended).

  • Function Compute runs on x86_64. For instruction-set-dependent dependencies, use an x86_64 machine or cross-compile to ensure compatibility.

Supported directories by runtime

If a runtime supports layers, Function Compute adds the following directories to the dependency search path of the runtime language. Structure your layer ZIP package to match these paths so your function code can access layer content without specifying explicit paths. For details about how to build a layer ZIP file, see Build a layer ZIP file.

Runtime Directory path
Python /opt/python
Node.js /opt/nodejs/node_modules
Java /opt/java/lib
PHP /opt/php
Other runtimes (excluding custom runtime and custom container runtime) /opt/bin (PATH), /opt/lib (LD_LIBRARY_PATH)
Custom runtime and custom container runtime None

If you use a custom directory structure instead, explicitly add the dependency search path in your function code. For details, see How do I reference dependencies in a layer in a custom runtime.

Layer ZIP file structure

The following examples show the required ZIP file structure and the corresponding deployment paths for each runtime.

Python — packaging with the requests dependency:

my-layer-code.zip
└── python
    └── requests

Extracted to:
/opt/python/requests

Node.js — packaging with the uuid dependency:

my-layer-code.zip
└── nodejs
    ├── node_modules
    │   └── uuid
    ├── package-lock.json
    └── package.json

Extracted to:
/opt/nodejs/node_modules/uuid

Java — packaging with the commons-lang3 dependency:

my-layer-code.zip
└── java
    └── lib
        └── commons-lang3-3.12.0.jar

Extracted to:
/opt/java/lib/commons-lang3-3.12.0.jar

PHP — packaging with Composer dependencies:

my-layer-code.zip
└── php
    ├── composer.json
    ├── composer.lock
    └── vendor

Extracted to:
/opt/php/vendor

Build a layer ZIP file

Building a layer ZIP file is similar to building a code package. For Function Compute to correctly load the libraries published in a layer at runtime, the directory structure of the library code must follow the standard directory conventions of each language. For details, see Supported directories by runtime. If you package your layer dependencies as specified, Function Compute automatically adds the dependency search path for each language, and you do not need to specify the full path.

To build a layer ZIP file for each runtime, perform the following steps:

Note
  • When you build a layer locally, use the same programming language version as the runtime version that you select in Function Compute.

  • The my-layer-code working directory created in the following steps is only an example. You can replace the directory name as needed.

Python runtime

Note

When you build a layer locally, use the same Python version as the Python runtime version that you select in Function Compute.

  1. Create a working directory:

    mkdir my-layer-code
    cd my-layer-code
  2. Install dependencies into the python subdirectory:

    pip install --target ./python ${PackageName}

    For details about the pip install command, see pip install.

    Example with numpy:

    pip install --target ./python numpy

    After installation, the directory structure looks like this:

    my-layer-code
    └── python
        ├── bin
        ├── numpy
        ├── numpy-1.22.4.dist-info
        └── numpy.libs
  3. Package the dependencies from the my-layer-code directory:

    zip -r my-layer-code.zip python

Node.js runtime

Note

When you build a layer locally, use the same Node.js version as the Node.js runtime version that you select in Function Compute.

  1. Create a working directory:

    mkdir my-layer-code
    cd my-layer-code
  2. Install dependencies into the nodejs subdirectory:

    npm install --prefix ./nodejs --save ${PackageName}

    ${PackageName} is the name of the dependency package that you want to install. For details about the npm install command, see npm-install.

    Example with uuid:

    npm install --prefix ./nodejs --save uuid

    After installation, the directory structure looks like this:

    my-layer-code
    └── nodejs
        ├── node_modules
        │   └── uuid
        ├── package-lock.json
        └── package.json
  3. Package the dependencies from the my-layer-code directory:

    zip -r my-layer-code.zip nodejs

Java runtime

  1. Create a working directory:

    mkdir my-layer-code/java
    cd my-layer-code/java
  2. Create a pom.xml file that declares your dependencies. The following example installs commons-lang3 and copies it to ./lib using the maven-dependency-plugin:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>maven.util</groupId>
        <artifactId>install-layer</artifactId>
        <version>1.0</version>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.12.0</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <configuration>
                        <!-- Include transitive dependencies -->
                        <excludeTransitive>false</excludeTransitive>
                        <!-- Keep version suffixes in JAR file names -->
                        <stripVersion>false</stripVersion>
                        <!-- Output directory for downloaded JARs -->
                        <outputDirectory>./lib</outputDirectory>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
  3. Install the dependencies:

    mvn dependency:copy-dependencies

    After installation, the directory structure looks like this:

    my-layer-code
    └── java
        └── lib
            └── commons-lang3-3.12.0.jar
  4. Package the dependencies from the my-layer-code directory:

    zip -r my-layer-code.zip java

PHP runtime

  1. Create a working directory:

    mkdir -p my-layer-code/php
    cd my-layer-code/php
  2. Create a composer.json file that declares your dependencies. Example:

    {
      "require": {
        "aliyunfc/fc-php-sdk": "~1.2",
        "alibabacloud/fnf": "^1.7"
      }
    }
  3. Install the dependencies:

    composer install

    After installation, the directory structure looks like this:

    my-layer-code
    └── php
        ├── composer.json
        ├── composer.lock
        └── vendor
  4. Package the dependencies from the my-layer-code directory:

    zip -r my-layer-code.zip php

Create a custom layer

Using the console

Prerequisites

Before you begin, ensure that you have:

Steps

  1. Log on to the Function Compute console. In the left-side navigation pane, choose Advanced Features > Layers.

  2. In the top navigation bar, select a region. On the Layers page, click Create Layer.

  3. Configure the following parameters, then click Create.

    Parameter Description
    Name Enter a name for the layer.
    Description Enter a description for the layer to help you distinguish between layers.
    Compatible Runtime Select the runtimes compatible with this layer.
    Layer Upload Method Select how to upload the layer's dependencies: Upload Layer in ZIP Package — upload a .zip file (max 500 MB); Upload Layer in Folder — select a folder that Function Compute compresses into a .zip file (max 500 MB); Upload Layer Using OSS — specify the Bucket Name and Object Name of the .zip file in Object Storage Service (OSS) (max 500 MB); Build Dependency Layer Online — if your function is developed in Python or Node.js, or you need to install lightweight system libraries, you can build the layer online. Enter the content of the dependency file (requirements.txt for Python or package.json for Node.js) in the input box below. After you submit the request, Function Compute automatically installs the language-level dependency packages and system libraries, which simplifies layer dependency management.
    Build Environment Appears when Build Dependency Layer Online is selected. Choose the runtime for building the layer. Currently, only Python and Node.js runtimes are supported.
    apt command Appears when Build Dependency Layer Online is selected. Enter package names after apt install to install system packages into the layer.

    After the layer is created, a layer version is automatically generated. The version number starts from 1 and increments with each new version.

    Note

    If the OSS bucket is encrypted by Key Management Service (KMS), the Function Compute service-linked role (AliyunServiceRoleForFC) may not have permission to access the encrypted objects, resulting in an AccessDenied error. To resolve this, update the key policy in the KMS console to grant access to the AliyunServiceRoleForFC role. For details, see Modify a key policy. After updating the key policy, retry the layer upload to verify the permission change takes effect.

  4. To add a new version to an existing layer:

    Note

    You cannot modify an existing layer or any of its versions. To update a layer, create a new layer or a new layer version. If a referenced layer version is deleted, remove the reference before you update the layer configuration.

    1. On the Layers page, click the name of the target layer.

    2. In the Version Management section, click Create Version.

    3. Select a runtime, upload the new layer code, and click Create.

Using Serverless Devs

Prerequisites

Before you begin, ensure that you have:

Steps

  1. Run the following command to create a layer:

    s cli fc layer publish --code ./my-layer-code --compatible-runtime java8,java11,custom --region cn-hangzhou --layer-name my-layer

    The following table describes the parameters in the command.

    Parameter Description
    --code Path to the layer code package.
    --compatible-runtime Comma-separated list of compatible runtimes.
    --layer-name Name of the layer.

    After the layer is created, the command returns the Alibaba Cloud Resource Name (ARN) of the layer. The ARN consists of three parts separated by number signs (#): the identifier of the account ID, the layer name, and the layer version. You can also log on to the Function Compute console to view the information about the created layer.

  2. To add a new version to an existing layer, run the same command with the same layer name:

    s cli fc layer publish --code ./my-layer-code --compatible-runtime java8,java11,custom --region cn-hangzhou --layer-name my-layer
    Note

    You cannot modify an existing layer or any of its versions. To update a layer, create a new layer or a new layer version. If a referenced layer version is deleted, remove the reference before you update the layer configuration.

Delete a layer or layer version

You can delete layers or layer versions that you no longer need. A deleted layer can no longer be viewed or referenced in function configurations. However, the execution of functions that already reference the deleted layer is not affected.

  1. Log on to the Function Compute console. In the left-side navigation pane, choose Advanced Features > Layers.

  2. In the top navigation bar, select a region.

  3. On the Layers page, delete a layer or a layer version:

    • Delete a layer: Find the target layer, click Delete in the Actions column, select the confirmation checkbox, and click Delete.

    • Delete a layer version: Click the name of the target layer. In the Version Management section of the layer details page, find the target version, click Delete in the Actions column, and click Delete in the Confirm dialog box.

What's next

  • After you create a custom layer, bind it to a function through the Function Compute console or Serverless Devs so that the function can access the resources provided by the layer. For details, see Configure a custom layer.

  • You can also manage and configure layers by setting the layers parameter when you create or update a function by calling the API or by using the SDK. For details, see CreateFunction and UpdateFunction.

  • If your layer dependencies include shared libraries, or your local environment is incompatible with the Function Compute runtime, you cannot build the layer in the console or locally. Build the layer from a Dockerfile instead. For details, see Use a Dockerfile to build a layer.