
# 使用Python构建容器镜像开发事件函数
使用容器镜像创建并执行事件函数的完整操作步骤可参考[使用容器镜像创建并执行事件函数](https://support.huaweicloud.com/qs-functiongraph/functiongraph_04_0104.html)，本章节介绍如何使用Python语言制作镜像，并进行本地验证。
#### 步骤一：制作镜像
以在Linux x86 64位系统上制作镜像为例（系统配置无要求）。
1. 执行以下命令，创建一个名为"custom_container_event_example"的空文件夹。
   ```
   mkdir custom_container_event_example && cd custom_container_event_example
   ```
   
2. 使用Python语言实现一个HTTP Server，处理函数初始化init请求和函数调用invoke请求并响应。 使用以下命令创建一个"main.py"文件。
   ```
   touch main.py
   ```
   在代码中引入flask框架，实现Method为POST和Path为/invoke的函数执行入口，实现Method为POST和Path为/init的函数初始化入口。main.py文件的代码内容如下：
   ```
   import json
   from flask import Flask, request
   # 创建 Flask 应用实例
   app = Flask(__name__, template_folder='templates', static_folder='static')
   # 定义初始化接口
   @app.route('/init', methods=['POST'])
   def init():
       # 打印请求路径，用于调试
       print("***" + request.path + "***", flush=True)
       # 构建响应数据
       data = {
           "statusCode": 200,
           "isBase64Encoded": False,
           "body": json.dumps("init successes"),
           "headers": {
               "Content-Type": "application/json"
           }
       }
       return json.dumps(data)
   # 定义调用接口
   @app.route('/invoke', methods=['POST'])
   def invoke():
       print("***" + request.path + "***", flush=True)
       data = {
           "statusCode": 200,
           "isBase64Encoded": False,
           "body": json.dumps("invoke successes"),
           "headers": {
               "Content-Type": "application/json"
           }
       }
       return json.dumps(data)
   # 主程序入口
   if __name__ == '__main__':
       app.run(host="0.0.0.0", port=8000)
   ```
   
3. 创建Dockerfile文件，
   ```
   touch Dockerfile
   ```
   Dockerfile文件内容如下：
   ```
   FROM ubuntu:22.04
   ENV HOME=/home/custom_container
   ENV GROUP_ID=1003
   ENV GROUP_NAME=custom_container
   ENV USER_ID=1003
   ENV USER_NAME=custom_container
   RUN mkdir -m 550 ${HOME} && groupadd -g ${GROUP_ID} ${GROUP_NAME} && useradd -u ${USER_ID} -g ${GROUP_ID} ${USER_NAME}
   RUN apt-get update &&  \
       apt-get install -y --no-install-recommends python3 pip &&  \
       apt-get clean
   RUN pip3 install --verbose flask jsons requests --no-cache-dir
   COPY main.py ${HOME}
   RUN chown -R ${USER_ID}:${GROUP_ID} ${HOME}
   RUN chmod -R 775 ${HOME}
   USER ${USER_NAME}
   WORKDIR ${HOME}
   EXPOSE 8000
   ENTRYPOINT ["python3", "main.py"]
   ```
   表1指令说明 
   | 指令         | 说明                                                                                                                        |
   |:---|:---|
   | FROM       | 指定基础镜像为ubuntu:22.04，基础镜像必须设置，值可修改。                                                                                        |
   | ENV        | 设置环境变量，设置HOME环境变量为/home/custom_container、GROUP_NAME和USER_NAME为custom_container、**USER_ID和GROUP_ID为1003**，这些环境变量必须设置，值可修改。 |
   | RUN        | 执行命令，格式为RUN \<命令\>。例如RUN mkdir -m 550 ${HOME}表示构建容器时创建${USER_NAME}用户的${HOME}目录。                                           |
   | COPY       | 从构建上下文复制文件或目录到镜像中。将main.py拷贝到容器的${USER_NAME}用户的${HOME}目录下。                                                                |
   | USER       | 切换${USER_NAME}用户。                                                                                                         |
   | WORKDIR    | 切换工作目录到${USER_NAME}用户的${HOME}目录下。                                                                                         |
   | EXPOSE     | 声明容器运行时监听的端口。暴露容器的8000端口，请勿修改。                                                                                            |
   | ENTRYPOINT | 设置容器启动时运行的命令，使用python3 main.py命令启动容器。                                                                                     |
      
   
4. 执行以下命令构建镜像。
   ```
   docker build -t custom_container_event_example:latest .
   ```
   指定镜像的名称为"custom_container_event_example"，版本为"latest"，"."指定Dockerfile所在目录，镜像构建命令将该路径下所有的内容打包给容器引擎帮助构建镜像。
   
#### 步骤二：本地验证
1. 执行以下命令启动docker容器。
   ```
   docker run -u 1003:1003 -p 8000:8000 custom_container_event_example:latest
   ```
   
2. 打开一个新的命令行窗口，向开放的8000端口发送消息，访问模板代码中指定的/init路径。
   ```
   curl -XPOST -H 'Content-Type: application/json' localhost:8000/init
   ```
   将按照模块代码返回以下内容：
   ```
   {
       "statusCode": 200,
       "isBase64Encoded": False,
       "body": json.dumps("init successes"),
       "headers": {
           "Content-Type": "application/json"
       }
   }
   ```
   
3. 打开一个新的命令行窗口，向开放的8000端口发送消息，访问模板代码中指定的/invoke路径。
   ```
   curl -XPOST -H 'Content-Type: application/json' -d '{"message":"HelloWorld"}' localhost:8000/invoke
   ```
   将按照模块代码返回以下内容：
   ```
   {
       "statusCode": 200,
       "isBase64Encoded": False,
       "body": json.dumps("invoke successes"),
       "headers": {
           "Content-Type": "application/json"
       }
   }
   ```
   
 
#### 步骤三：配置函数
在本地完成容器镜像构建后，即可进行控制台操作。
后续操作步骤请参考[使用容器镜像创建并执行事件函数](https://support.huaweicloud.com/qs-functiongraph/functiongraph_04_0104.html#section4)，从步骤三：上传镜像开始操作。
#### 相关文档
- 关于函数开发的更多说明，如函数支持的运行时、函数支持的触发事件、函数工程打包规范以及如何在函数中引入动态链接库，请参见[函数开发概述](https://support.huaweicloud.com/devg-functiongraph/functiongraph_02_0100.html)。
- 关于Python函数开发的接口定义和SDK接口说明，请参见[Python函数开发概述](https://support.huaweicloud.com/devg-functiongraph/functiongraph_02_0502.html)。
 
