如何通过 Lambda|API 网关访问 Dockerized R 图像?

How to access a Dockerized R image trough Lambda|API Gateway?

这个问题的第一个版本可能没有我想的那么清楚,因为有很多部分,问题出在过程的一部分。

尽可能简单: 我有一个 dockerized R 应用程序暴露给管道工的 http 访问,我想在 aws lambda 中使用它。

Dockerfile非常简单:

FROM rstudio/plumber:latest

WORKDIR /opt/ml

# system libraries of general use
RUN apt-get update && apt-get install -y --no-install-recommends \
    autoconf \
    automake \
    wget \
    libcurl4-openssl-dev\
    libsodium-dev \
    ca-certificates

# r pkgs (https://rstudio.github.io/renv/articles/docker.html)
RUN R -e "install.packages('renv', repos = c(CRAN = 'https://cloud.r-project.org'))"

# renv (https://nicd.ncl.ac.uk/blog/posts/deploying-model-predictions-using-plumber-and-docker/)
COPY . .
RUN R -e "renv::restore()" # uncomment to create docker image with renv

# plumber
ENTRYPOINT ["Rscript", "run_plumber.R"] # uncomment to create docker image with renv
EXPOSE 8080/tcp
docker build -t image-name:0.0.1 .
docker run --name sandbox --restart=always -p 8080:8080 -v C:\Users\User\Downloads\aws_s3:/data image-name:0.0.1

当我 运行 这个命令时,我得到一个容器,我可以像这样使用 curl 访问它:

curl -X POST "http://127.0.0.1:8080/functionName?param1=/data/archive.json&param2=/data/archive.csv"

或者按照文档的建议,我有这个功能

# plumber.R

#* Echo back the input
#* @param msg The message to echo
#* @get /echo
function(msg="") {
  list(msg = paste0("The message is: '", msg, "'"))
}

然后我得到了结果(这只是为了确认工作流程有效

curl -X GET"http://127.0.0.1:8080/echo?msg=hi"

到这里为止一切都还好;一旦图像被标记并推送到 ECR 并在其上创建了一个 lambda 函数,我通过 API 网关

访问它

在API网关中我设置了一个资源和一个方法,资源是curl和函数指定的函数“echo”的名称;部署后,我知道管道工库在端口 8080

中公开

当我通过 API 网关调用我的函数时:我在云监视中得到这个日志:


Error: failed to create directory at path '/home/sbx_user1051/.local/share/renv'
In addition: Warning message:
In dir.create(rownames(info), recursive = TRUE) :
cannot create dir '/home/sbx_user1051/.local', reason 'No such file or directory'
Traceback (most recent calls last):
19: source("renv/activate.R")
18: withVisible(eval(ei, envir))
17: eval(ei, envir)
16: eval(ei, envir)
15: local(...)
14: eval.parent(substitute(eval(quote(expr), envir)))
13: eval(expr, p)
12: eval(expr, p)
11: eval(quote(...), new.env())
10: eval(quote(...), new.env())
9: renv_bootstrap_load(project, libpath, version)
8: renv::load(project)
7: renv_load_renviron(project)
6: renv_paths_root(".Renviron")
5: Sys.getenv("RENV_PATHS_ROOT", unset = NA) %NA% renv_paths_root_default()
4: renv_paths_root_default()
3: ensure_directory(path)
2: stopf("failed to create directory at path '%s'", rownames(info))
1: stop(sprintf(fmt, ...), call. = call.)
Execution halted

这里的问题是 /home/sbx_user1051/.local 不可写,另见 docker-lambda #103。在 renv 部分之前的 Dockerfile 中,将 RENV_PATHS_ROOT 设置为默认用户具有写入权限的目录,以绕过错误,例如

ENV RENV_PATHS_ROOT="/tmp/.local/share/renv"
# ENV RENV_PATHS_ROOT="${LAMBDA_TASK_ROOT}/.local/share/renv" # works similarly

另请参阅 renv docs 以获取有关路径自定义的更多详细信息。此外,请注意,如果 use.cacherenv/settings.dcf 中未被禁用,您可能 运行 进入 AWS Lambda 上的 L2 缓存大小问题: